Jump to content

KMarb

Members
  • Content Count

    77
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by KMarb

  1. KMarb

    delphi camera focus

    I just discovered that some cameras can continuously auto focus and some cannot. Trying to set focusMode to ContinuousAutoFocus blows up the app, in an unrecoverable way... The code below never gets to the except statement: var camera : TCameracomponent; try camera.FocusMode := TFocusMode.ContinuousAutoFocus; except camera.FocusMode := TFocusMode.AutoFocus; end; is there a way to query the camera to find if it supports ContinuousAutoFocus? Or how to make use of continuous auto focus when available? Keith
  2. KMarb

    delphi camera focus

    well, my app is only for a small set of users, and we might have 20 different devices right now. On 3 that I have tested, this works: create: camera := TCameraComponent.Create (nil); camera.Kind := FMX.Media.TCameraKind.FrontCamera; camera.FocusMode := TFocusMode.Locked; when need back camera: if camera.Kind <> FMX.Media.TCameraKind.BackCamera then begin camera.Kind := FMX.Media.TCameraKind.BackCamera; camera.FocusMode := TFocusMode.ContinuousAutoFocus; camera.OnSampleBufferReady := backCameraSampleBufferReady; end; and to flip back to front camera: if camera.Kind <> FMX.Media.TCameraKind.FrontCamera then begin camera.FocusMode := TFocusMode.Locked; camera.Kind := FMX.Media.TCameraKind.FrontCamera; camera.OnSampleBufferReady := frontCameraSampleBufferReady; end; It sounds like some devices (Samsung S4) might fail with the above code, but for the most part this should work. Thank you for the help.
  3. KMarb

    delphi camera focus

    Thank you very much. One related question... I'm also using the rear camera capability for barcoding. I'm using a single TCameraComponent and flipping between back and front camera. camera.Kind := FMX.Media.TCameraKind.BackCamera; Should I be able to set focusMode for the back camera always, or do some back cameras not handle continuousAutoFocus? I was having problems switching back and forth between the back and front cameras so I changed my code to only set focusMode when I create the TCameracomponent (which is done with kind = FaceCamera), but the bar code reader will not work or not very well unless the focus mode is set. Thanks again. Keith
  4. KMarb

    delphi camera focus

    More discovery... I'm finding I get the same error now with this line: camera.FocusMode := TFocusMode.AutoFocus; with some devices and not others. Not sure it matters but I have the component created as a face camera: camera := TCameraComponent.Create (nil); camera.Kind := FMX.Media.TCameraKind.FrontCamera; It seems that some models of phone (or some front cameras) +might not allow me to set focusMode at all... is that correct? Appreciate any thoughts on how to work past this.
  5. I'm using Dave Nottage's Kastri library and it is pretty great. I'm running into an issue, though, with the barcode feature and I'm not sure what's wrong. I use a TCameraComponent to capture the user's selfie when they sign in with their employee ID number. The code to create the camera is this: if not assigned (faceCamera) then begin faceCamera := TCameraComponent.Create (nil); faceCamera.Kind := FMX.Media.TCameraKind.FrontCamera; faceCamera.FocusMode := TFocusMode.ContinuousAutoFocus; faceCamera.OnSampleBufferReady := faceCameraSampleBufferReady; end; I'm not having any problem with the "selfie" camera. The barcode capability is only available in user interface after the user logs in. So, since my app has either the front or back camera on at any one time, my thinking is to use the same cameraComponent for the barcode scanning. First question I have: should I instantiate a second TCameraComponent for the back camera? Or can I share the component for both functions? I have another variable, barcodeCamera, but I don't instantiate a new object... I just point to faceCamera, like this: procedure TfrmMain.StartBarcodeCamera; begin barcode := ''; // the scan capability might find multiple barcodes, but only one will be returned in our code barcodeCamera := faceCamera; // 12/20/22 - share the camera component if barcodeCamera.Kind <> FMX.Media.TCameraKind.BackCamera then begin barcodeCamera.Kind := FMX.Media.TCameraKind.BackCamera; barcodeCamera.OnSampleBufferReady := barcodeCameraSampleBufferReady; end; FIsScanning := True; // i have a call to log.d to output to android log here, something like log.d ('StartBarcodeCamera - before barcodeCamera.Active := True'); barcodeCamera.Active := True; end; I think I have a problem with google vision library not loading properly, so my 2nd question is, what does the following tell you, if anything, about my problem: What's happening is that the camera doesn't show... the barcodeCameraSampleBufferReady fires, and I get a few lines in DeviceLens that might shed some light: FMX: JCM Material: StartBarcodeCamera - before barcodeCamera.Active := True type=1400 audit(0.0:77655): avc: denied { read } for name="u:object_r:vendor_camera_prop:s0" dev="tmpfs" ino=4472 scontext=u:r:untrusted_app:s0:c117,c256,c512,c768 tcontext=u:object_r:vendor_camera_prop:s0 tclass=file permissive=0 Access denied finding property "vendor.camera.hal1.packagelist" send ACTION_CAMERA_DEVICE_STARTED FMX: JCM Material: barcodeCameraSampleBufferReady FMX: JCM Material: barcodeCameraSampleBufferReady - setting FProcessTime := Now FMX: JCM Material: barcodeCameraSampleBufferReady - before FReader.Scan(FSectionBitmap) Local module descriptor class for com.google.android.gms.vision.dynamite.barcode not found. Considering local module com.google.android.gms.vision.dynamite.barcode:0 and remote module com.google.android.gms.vision.dynamite.barcode:0 Cannot load feature, fall back to load whole module. Local module descriptor class for com.google.android.gms.vision.dynamite not found. Unsupported class loader Skipping duplicate class check due to unsupported classloader Considering local module com.google.android.gms.vision.dynamite:0 and remote module com.google.android.gms.vision.dynamite:2703 Selected remote version of com.google.android.gms.vision.dynamite, version >= 2703 Dynamite loader version >= 2, using loadModule2NoCrashUtils ClassLoader referenced unknown path: Unsupported class loader Verification of ix ix.d(android.content.Context, ir, java.lang.String) took 106.493ms Wrote stack traces to '[tombstoned]' Accessing hidden field Lsun/misc/Unsafe;->theUnsafe:Lsun/misc/Unsafe; (light greylist, reflection) Considering local module com.google.android.gms.vision.barcode:0 and remote module com.google.android.gms.vision.barcode:224404100 Selected remote version of com.google.android.gms.vision.barcode, version >= 224404100
  6. I found my problem. I thought the barcodeHandler was only called when a barcode was found in the image. Things are working fine now. Thanks again for the help.
  7. Pretty sure I'm good with that step: One odd thing... I can add the two vision jars to 64-bit android but not 32-bit. I'm only testing in 64-bit right now, but will need 32-bit to work as well. I had some success with scanning a few days ago, so I don't think it is my search path, but here is that: I'm not sure where to set the Framework search path... Maybe that is the problem.
  8. What's the best way to install a shortcut on android home screen when I install my app? If it matters I'm not using the play store. I'm using Delphi 11.1. I found some code (that was pretty old) but it is not working. My slight modifications of it is below: procedure addShortcut (const AppID : string); var ShortcutIntent: JIntent; addIntent: JIntent; wIconIdentifier : integer; wIconResource : JIntent_ShortcutIconResource; begin ShortcutIntent := TJIntent.JavaClass.init(SharedActivityContext, SharedActivityContext.getClass); ShortcutIntent.setAction(TJIntent.JavaClass.ACTION_MAIN); addIntent := TJIntent.Create; addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_INTENT, TJParcelable.Wrap((shortcutIntent as ILocalObject).GetObjectID)); // here we need to cast the intent as it's not done in delphi by default, not like java addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_NAME, StringToJString(Application.Title)); addIntent.setAction(StringToJString('com.android.launcher.action.INSTALL_SHORTCUT')); //'com.embarcadero.HeaderFooterApplication' // get icon resource identifier wIconIdentifier := SharedActivity.getResources.getIdentifier(StringToJString('ic_launcher'), StringToJString('drawable'), StringToJString (AppID)); // if the app name change, you must change the package name wIconResource := TJIntent_ShortcutIconResource.JavaClass.fromContext(SharedActivityContext, wIconIdentifier); // set icon for shortcut addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_ICON_RESOURCE, TJParcelable.Wrap((wIconResource as ILocalObject).GetObjectID)); SharedActivityContext.sendBroadcast(addIntent); end;
  9. I had been testing my app on a samsung tablet and a ulefone Armor X9 and had it all working, i thought. Now I'm trying to deploy to some other ulefone models (armor x3 and x5) and I'm able to install, but when i launch the app i get error "Application does not support this device" or the app immediately closes. Any thoughts on how to fix? Using deviceLens here is some of the logging 12-05 16:52:39.495 I com.zunna.JCMPhotos 20787 20787 zunna.JCMPhoto Late-enabling -Xcheck:jni 12-05 16:52:39.592 W com.zunna.JCMPhotos 20787 20787 re-initialized> type=1400 audit(0.0:1727): avc: denied { read } for name="u:object_r:mtk_amslog_prop:s0" dev="tmpfs" ino=3397 scontext=u:r:untrusted_app:s0:c109,c256,c512,c768 tcontext=u:object_r:mtk_amslog_prop:s0 tclass=file permissive=0 12-05 16:52:39.596 E com.zunna.JCMPhotos 20787 20787 libc Access denied finding property "persist.vendor.sys.activitylog" 12-05 16:52:40.054 D com.zunna.JCMPhotos 20787 20787 AndroidRuntime Shutting down VM 12-05 16:52:40.064 E com.zunna.JCMPhotos 20787 20787 AndroidRuntime FATAL EXCEPTION: main 12-05 16:52:40.064 E com.zunna.JCMPhotos 20787 20787 AndroidRuntime Process: com.zunna.JCMPhotos, PID: 20787 12-05 16:52:40.064 E com.zunna.JCMPhotos 20787 20787 AndroidRuntime java.lang.RuntimeException: Unable to get provider androidx.core.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/com.zunna.JCMPhotos-pBkN5adkbbYEbIb8Jtd9VQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.zunna.JCMPhotos-pBkN5adkbbYEbIb8Jtd9VQ==/lib/arm, /data/app/com.zunna.JCMPhotos-pBkN5adkbbYEbIb8Jtd9VQ==/base.apk!/lib/armeabi-v7a, /system/lib]] 12-05 16:52:40.064 E com.zunna.JCMPhotos 20787 20787 AndroidRuntime at android.app.ActivityThread.installProvider(ActivityThread.java:6427)
  10. I'm sure this is not appropriate forum behavior, but I want to say that I love you. Maybe I should say I'm feeling a lot of love for you. Online correctness is not my thing. I did as you suggested (deleted the output folders), then I built and installed again and now it is working. You saved me an unknown amount of time. I am truly grateful to you.
  11. Not sure if there is a good way to compare list of jar files between two apps, but here is the top of list for both the working app and the non-working app. I did the "revert system files" click on both of these, several times on the one that is not working. I hate to do it, but at this point I think I need to start chopping out functionality until I get the non-working app to work again, and then work forward until I find what is causing the problem. In term of function, the one that is not working allows submission of photos to our server, so it wants to access gallery... the other working app does not try to access the gallery, so that is where I will start. I will report back with questions and progress. Thanks very much. Working app: NON-working app:
  12. The app is not giving me the error message anymore. When I launch it, I see splash screen, and then message "<MyAppName> has stopped, App info, close app". I added a log.d call in the project file before Application.Initialize; That log call does not show up in android log file. Here is the full android log. I bolded a line that seems really odd to meq: 12-06 15:50:15.015 I com.zunna.JCMPhotos 29570 29570 zunna.JCMPhoto Late-enabling -Xcheck:jni 12-06 15:50:15.249 E com.zunna.JCMPhotos 29570 29570 libc Access denied finding property "persist.vendor.sys.activitylog" 12-06 15:50:18.107 D com.zunna.JCMPhotos 29570 29570 AndroidRuntime Shutting down VM 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime FATAL EXCEPTION: main 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime Process: com.zunna.JCMPhotos, PID: 29570 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime java.lang.RuntimeException: Unable to get provider androidx.core.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/com.zunna.JCMPhotos-YQiq9zZupR4iE_EdtFvljA==/base.apk"],nativeLibraryDirectories=[/data/app/com.zunna.JCMPhotos-YQiq9zZupR4iE_EdtFvljA==/lib/arm, /data/app/com.zunna.JCMPhotos-YQiq9zZupR4iE_EdtFvljA==/base.apk!/lib/armeabi-v7a, /system/lib]] 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread.installProvider(ActivityThread.java:6427) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread.installContentProviders(ActivityThread.java:5969) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5884) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread.access$1200(ActivityThread.java:206) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1678) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.os.Handler.dispatchMessage(Handler.java:106) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.os.Looper.loop(Looper.java:193) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread.main(ActivityThread.java:6702) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at java.lang.reflect.Method.invoke(Native Method) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" on path: DexPathList[[zip file "/data/app/com.zunna.JCMPhotos-YQiq9zZupR4iE_EdtFvljA==/base.apk"],nativeLibraryDirectories=[/data/app/com.zunna.JCMPhotos-YQiq9zZupR4iE_EdtFvljA==/lib/arm, /data/app/com.zunna.JCMPhotos-YQiq9zZupR4iE_EdtFvljA==/base.apk!/lib/armeabi-v7a, /system/lib]] 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at java.lang.ClassLoader.loadClass(ClassLoader.java:379) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at java.lang.ClassLoader.loadClass(ClassLoader.java:312) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.AppComponentFactory.instantiateProvider(AppComponentFactory.java:121) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime at android.app.ActivityThread.installProvider(ActivityThread.java:6411) 12-06 15:50:18.117 E com.zunna.JCMPhotos 29570 29570 AndroidRuntime ... 10 more
  13. Really glad to have your feedback. I had already tried that and it did not help. Here is a bit of an odd thing I don't understand yet... I have 2 apps that use a lot of the same code, identical manifests and associated xml files. One works and one doesn't. I compared the deployment lists and they seem identical. The Armor X3 is a 32-bit device, so I'm running release version of 32-bit app. Here is the start of the android log for the WORKING app (non-working app log is above). I can send more of either log if that would help identify what is different. In the working app log, there is no mention of "fileprovider", but the same entries are in manifest. 12-06 15:23:09.444 I com.zunna.JCMTime 26899 26899 m.zunna.JCMTim Late-enabling -Xcheck:jni 12-06 15:23:09.593 W com.zunna.JCMTime 26899 26899 re-initialized> type=1400 audit(0.0:5735): avc: denied { read } for name="u:object_r:mtk_amslog_prop:s0" dev="tmpfs" ino=3397 scontext=u:r:untrusted_app:s0:c106,c256,c512,c768 tcontext=u:object_r:mtk_amslog_prop:s0 tclass=file permissive=0 12-06 15:23:09.598 E com.zunna.JCMTime 26899 26899 libc Access denied finding property "persist.vendor.sys.activitylog" 12-06 15:23:12.404 D com.zunna.JCMTime 26899 26899 OpenGLRenderer Skia GL Pipeline 12-06 15:23:12.406 I com.zunna.JCMTime 26899 26899 SurfaceFactory [static] sSurfaceFactory = com.mediatek.view.impl.SurfaceFactoryImpl@9eeb266 12-06 15:23:12.695 E com.zunna.JCMTime 26899 26899 appName=com.zunna.JCMTime, acAppName=/system/bin/surfaceflinger 12-06 15:23:12.696 E com.zunna.JCMTime 26899 26899 0 12-06 15:23:12.700 I com.zunna.JCMTime 26899 26899 ConfigStore android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0 12-06 15:23:12.701 I com.zunna.JCMTime 26899 26899 ConfigStore android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0 12-06 15:23:12.703 I com.zunna.JCMTime 26899 26899 BufferQueue [unnamed-26899-0](this:0x8f58e000,id:0,api:0,p:-1,c:-1) BufferQueue core=(26899:com.zunna.JCMTime) 12-06 15:23:12.706 W com.zunna.JCMTime 26899 26899 m.zunna.JCMTime type=1400 audit(0.0:5736): avc: denied { read } for name="u:object_r:graphics_debug_prop:s0" dev="tmpfs" ino=3373 scontext=u:r:untrusted_app:s0:c106,c256,c512,c768 tcontext=u:object_r:graphics_debug_prop:s0 tclass=file permissive=0 12-06 15:23:12.713 E com.zunna.JCMTime 26899 26899 libc Access denied finding property "vendor.debug.sf.stc_interval" 12-06 15:23:12.714 E com.zunna.JCMTime 26899 26899 libc Access denied finding property "vendor.debug.bq.dump" 12-06 15:23:12.710 W com.zunna.JCMTime 26899 26899 m.zunna.JCMTime type=1400 audit(0.0:5737): avc: denied { read } for name="u:object_r:debug_bq_dump_prop:s0" dev="tmpfs" ino=3334 scontext=u:r:untrusted_app:s0:c106,c256,c512,c768 tcontext=u:object_r:debug_bq_dump_prop:s0 tclass=file permissive=0 12-06 15:23:12.723 I com.zunna.JCMTime 26899 26899 BufferQueueConsumer [unnamed-26899-0](this:0x8f58e000,id:0,api:0,p:-1,c:26899) connect(C): consumer=(26899:com.zunna.JCMTime) controlledByApp=true 12-06 15:23:12.724 E com.zunna.JCMTime 26899 26899 libc Access denied finding property "vendor.debug.bq.dump" 12-06 15:23:12.720 W com.zunna.JCMTime 26899 26899 m.zunna.JCMTime type=1400 audit(0.0:5738): avc: denied { read } for name="u:object_r:debug_bq_dump_prop:s0" dev="tmpfs" ino=3334 scontext=u:r:untrusted_app:s0:c106,c256,c512,c768 tcontext=u:object_r:debug_bq_dump_prop:s0 tclass=file permissive=0 12-06 15:23:12.724 E com.zunna.JCMTime 26899 26899 libc Access denied finding property "vendor.debug.bq.line" 12-06 15:23:12.720 W com.zunna.JCMTime 26899 26899 m.zunna.JCMTime type=1400 audit(0.0:5739): avc: denied { read } for name="u:object_r:graphics_debug_prop:s0" dev="tmpfs" ino=3373 scontext=u:r:untrusted_app:s0:c106,c256,c512,c768 tcontext=u:object_r:graphics_debug_prop:s0 tclass=file permissive=0 12-06 15:23:12.724 E com.zunna.JCMTime 26899 26899 libc Access denied finding property "vendor.debug.bq.dump" 12-06 15:23:12.720 W com.zunna.JCMTime 26899 26899 m.zunna.JCMTime type=1400 audit(0.0:5740): avc: denied { read } for name="u:object_r:debug_bq_dump_prop:s0" dev="tmpfs" ino=3334 scontext=u:r:untrusted_app:s0:c106,c256,c512,c768 tcontext=u:object_r:debug_bq_dump_prop:s0 tclass=file permissive=0
  14. Related to tog message, java.lang.RuntimeException: Unable to get provider androidx.core.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider" Here is entry in androidmanifest.xml: <provider android:name="androidx.core.content.FileProvider" android:authorities="com.zunna.JCMPhotos.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> and here is the provider_paths.xml file: <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="internal_private_files" path="." /> <cache-path name="internal_cache_files" path="." /> <external-path name="external_public_files" path="." /> <external-files-path name="external_private_files" path="." /> <external-cache-path name="external_cache_files" path="." /> <external-media-path name="external_media_files" path="." /> </paths> Do those entries make sense?
  15. I've only ever used TClientDataset with TSQLQuery, with the needed TDatasetProvider in between (TSQLQuery -> TDatasetProvider -> TClientDataset). I have a project to update an old datasnap server that used DBExpress (TSQLQuery comes from there). I'm wondering if I can drop DBExpress and use FireDac, which I know much better. Does this component linking work or make sense: (TFDStoredProc -> TDatasetProvider -> TClientDataset)? Or better, is there a way to pass an entire dataset using datasnap, but using FD datasets, not DBExpress datasets? With DBX, you use TClientDatasets (CDS) to pass an entire table of data with metadata with these lines: transData := CDS.Data; // on the client side, then a server call passes the transData (array of OleVariants) to a server procedure. CDS is linked to a local SQLite table CDS.Data := transData ; // on the server side, and now the TClientDataset has an entire table. The big picture is to have an efficient way for a client (android datasnap client) to send tables of data to the server, and for the server to efficiently save that data as new rows in existing SQL Server tables. I mention that because I feel there is probably a good way to take CDS.Data (or its FD equivalent) and save all rows to a server table without writing much code, but I wouldn't know where to start my research to do that. Discussion and feedback are really apprecaited. Keith
  16. I needed to get something working, so I wrote the code below. I want to use FireDac for database access, but I want to pass entire datasets to the datasnap client, and the only way I know how to do that now is to put the data in a TClientdataset and then send to client using CDS.Data. If I could use DBExpress to access the server database it is FAR simpler to pass datasets. If you feel like looking at code (working code, although not sure how efficient), please read below and tell me if there is a better way to do what I'm trying to do. Thank you. cdsFD : TClientDataset; // created with data module create procedure linkCDS; // sub-procedure var i : integer; s, s2, s3 : string; begin if cdsFD.Active then cdsFD.Close; cdsFD.FieldDefs.Clear; cdsFD.FieldDefs.Assign(spFD.FieldDefs); // spFD is the TFDStoredProc with data from server that needs to be sent to client // field definitions from the server might have auto-increment fields, readonly fields and required fields... Turn all those off in the CDS for i := 0 to cdsFD.FieldDefs.Count - 1 do begin if cdsFD.FieldDefs .DataType = ftAutoinc then cdsFD.FieldDefs .DataType := ftInteger; if DB.faReadonly in cdsFD.FieldDefs .Attributes then cdsFD.FieldDefs .Attributes := cdsFD.FieldDefs .Attributes - [DB.faReadonly]; if DB.faRequired in cdsFD.FieldDefs .Attributes then cdsFD.FieldDefs .Attributes := cdsFD.FieldDefs .Attributes - [DB.faRequired]; end; cdsFD.CreateDataSet; cdsFD.Active := true; spFD.First; while not spFD.EOF do begin cdsFD.Insert; cdsFD.copyFields (spFD); cdsFD.Post; spFD.Next; end; end; // start of main procedure begin GetFDConnection; // create new TFDConnection named DBCFD spFD.Connection := DBCFD; spFD.StoredProcName := 'JCMGetAllTimeLookupLists'; spFD.Prepare; spFD.paramByName ('@TSLastRequest').Value := lastRequestTimeStamp; spFD.paramByName ('@ReturnTS').Value := 'N'; spFD.open; // retrieves 19 datasets Result := VarArrayCreate ([0, 19], varVariant); linkCDS; // see above... put FDStoredProc data into a CDS result [0] := cdsFD.Data; for i := 1 to 18 do begin spFD.NextRecordSet; linkCDS; result := cdsFD.Data; // weird... I keep trying to make this result [ i ] :=, but when I hit save (on delphipraxis), the [ i ] keeps disappearing end; spFD.Close; end;
  17. For anyone who reads through this post, I never did figure out why CDSSv.applyUpdates (-1); throws the "invalid parameter" exception The thought I had related to ftDatetime versus ftTimestamp was a false lead. I'm rewriting my server to use FIredac rather than DBExpress to access the server database.
  18. My server needs to send 19 datasets to the android client (datasnap). I nearly have things working using Firedac, but I cannot figure out how to make a Clientdataset use datasets in the TFDStoredProc other than the 1st dataset. I have a SQL (Microsoft) stored procedure, 'JCMGetAllLookupLists' that returns 19 datasets. The TFDStoredProc (spFD) can step through those datasets easily enough using spFD.NextRecordset, but I don't know how to get the dataset in the CDS so I can send CDS.Data back to the cliente. here is the gyst of my code. The code below is in a server function that returns an OleVariant Result := VarArrayCreate ([0, 19], varVariant); // result [19] is not a dataset spFD.StoredProcName := 'JCMGetAllLookupLists'; spFD.Prepare; spFD.paramByName ('@TSLastRequest').Value := lastRequestTimeStamp; spFD.paramByName ('@ReturnTS').Value := 'N'; cdsFD.Open; // cdsFD is linked to a datasetprovider (dspFD) using cdsFD.Providername, and dspFD.Dataset is set to spFD // at this point, cdsFD can access the first dataset in spFD // but, how to get to the other 18 datasets? result [0] := cdsFD.Data; // this works fine // the loop below does not work... cdsFD.Data always has the data from spFD's FIRST dataset... for i := 1 to 18 do begin spFD.NextRecordSet; result := cdsFD.Data; end; I could make 19 different calls to the SQL server to get the 19 datasets (that's what I'm doing now), but it seems much more efficient if the server returns all 19 datasets at once and then my server code pulls out the data for each to send back to the client. Does anyone know how to step through FD datasets using NextRecordset in a way that a linked ClientDataset "sees" each of the FD datasets?
  19. I tested a simple case and have found that even in very simple example (3 integer fields), I get the "invalid parameter" error. So the problem or concern I have about the ftTimestamp versus ftDatetime may or may not be relevant. Here is my test code: procedure testCDS; var i : integer; s : string; begin resetCDS (CDSSv); // the reset calls clear fields and parameters from the clientdataset and query resetQ (QSv); s := 'select fld1, fld2, fld3 from testTbl where 1=0'; // I have other code that builds this select statement, but allowing the select from database to build the dataset fields in memory has many advantages (works with multiple tables, for exampe) QSv.SQL.Add (s); CDSSv.Open; // open empty dataset, all fields should be available now // attempt to add 3 rows to the table (brand new table, no indexes, just for testing) for i := 1 to 3 do begin CDSSv.Insert; CDSSv.fields [0].Value := i; CDSSv.fields [1].Value := i; CDSSv.fields [2].Value := i; CDSSv.Post; // no error yet... rows are successfully added to the CDS end; try CDSSv.ApplyUpdates (-1); // This is the statement that throws the invalid parameter exception... except on e:exception do begin {$IFDEF DBUG} DMServerContainer.writeDbugS ('testCDS - exception - ' + e.Message); {$ENDIF} end; end; end; Also... if i go a different route and build an SQL Insert statement and then execute it, the rows are saved to the SQL database as expected... IOW, the code below works, so there is something broken with TSQLQuery -> TDatasetProvider -> TClientDataset s := 'insert testTbl (fld1, fld2, fld3) values (1, 1, 1), (2, 2, 2), (3, 3, 3)'; QSv.SQL.Add (s); QSv.ExecSQL; So... I can rewrite my code, but then I need to handle strings, datetimes and blob/photo fields which is more work or not possible with an SQL statement (how to insert a photo into image field using an insert statement?).
  20. The exception reported by CDS.applyUpdates is "Invalid parameter." I do not think the datasnap part of this is relevant... maybe I should not have mentioned that at all, but was trying to be complete. With a TSQLQuery (named QSv), if I run a select statement like select fld1, fld2 from tbl where 1=0, and fld2 is a datetime field in SQL Server, the QSv.fields [1].datatype is not ftDatetime, it is ftTimestamp (16 bits long), and I think that is the source of the failure when applyUpdates tries to add rows back to the database table.
  21. One more thing... I've read that for certain field types, you will get the "invalid parameter" error, particularly with strings and GUID if datasize is not specified... Here's something I'm seeing that might be the problem, but I don't know how to fix. After CDSSv.open (which opens the blank dataset on the server), I loop through all fields to see that fieldtype, datasize, etc are... I have several fields in the underlying SQL table defined as datetime fields (8 bytes). In Delphi, after cdsSv.open, these fields show datatype as ftTimeStamp and datasize as 16 (not ftDateTime and size 8). Why would that happen? And how to fix? To summarize: My SQL is like this: select RegID, myDate from table; myDate in the sQL table is datetime After I open the dataset, the field type of myDate is ftTimestamp, not ftDatetime. That seems like it might cause the invalid parameter error when I apply updates. Thanks for looking through all this.
  22. I added some debugging output and have determined a few things: After CDSSv.open... CDSSv.CanModify is TRUE, cdsSv.ReadOnly is FALSE And I loop through all fields in CDSSv and each field also has CanModify = TRUE and ReadOnly = FALSE So I don't think it is a problem that the dataset or any field is read only. I have searched for why TClientDataSet.ApplyUpdates might generate and exception "Invalid Parameter" but I haven't found anything.
  23. My android app (Delphi 11) wants to download a file to the external storage download folder. I call the line below: PermissionsService.RequestPermissions([FPermissionReadExternalStorage, FPermissionWriteExternalStorage], ExternalStoragePermissionRequestResult, externalStorageRationale); I understand the call to requestPermissions happens asynchronously. When user accepts or rejects the request, the following handler runs: procedure TDMCommon.ExternalStoragePermissionRequestResult(Sender: TObject; const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray); begin if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then begin toast ('Downloading file...', shortToast); AsyncDownload.Download(FileURL, LocalFilename, asyncDownloadFinished) then ... I've chopped out code I feel is not relevant. Here are my questions: 1 - The handler is not running in the main thread, correct? 2 - If 1 is correct, then I should not call "toast" directly like it's shown, correct? I should call TThread.Queue(nil, procedure begin toast... end);? 3 - I'm downloading a file in the background using the AsyncDownload code (taken from one of the Delphi samples). It works great when run from main thread, but, if the handler is running code in a secondary thread (not the main thread), is it a bad idea to kickoff another thread to download a file? Could I just initiate a synchronous download here? I'm having some strange behavior and trying to get things right. The strangeness: - running in debug mode, sometimes I end up with a "CPU" window where I'm stepping through assembly code... I'm not sure what can cause that. - I set breakpoints in the finally section of "Try" blocks, but the breakpoints never fire, as if the "finally" blocks are not actually executing. I have calls to log.d in the finally and they do execute, so I think things are fine, but execution does not pause at my breakpoint. Any light on the subject is much appreciated. Keith
  24. I decided to follow your advice, and to call requestPermissions only from the main UI thread. I've been running my app for several hours today and the odd errors and debugger stepping into assembly code seems to have stopped. So maybe that's why I've been having some problems lately. Thanks for the feedback.
  25. That's not my case... I can download a file regardless of whether i can save in external storage. I can save in private storage, which is fine for the app. I just prefer the shared downloads folder to have better visibility outside the app of the downloaded file.
×