KMarb
-
Content Count
77 -
Joined
-
Last visited
-
Days Won
1
Posts posted by KMarb
-
-
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
-
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.
- 1
-
18 hours ago, Dave Nottage said:It seems you may not have included the vision jars in your project, as per the readme.
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. -
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 codebarcodeCamera := 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
-
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;
-
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.
- 1
-
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:
-
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 -
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
-
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?
-
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)
-
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 DBCFDspFD.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; -
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.
-
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?
-
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
-
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 -> TClientDatasets := '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?).
-
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.
-
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.
-
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.
-
Delphi 11 using DataSnap, although the communication between client and server seems fine, so datasnap I don't think is relevant. Problem is with DBExpress and readonly dataset, I think.
I don't know a short way to ask for help on this, but here goes:
On my datasnap server I'm using TSQLConnection to access SQL Server. I use TSQLQuery to run a query that gets an empty dataset from the SQL Server. The TSQLQuery is connected to a dataset provider which in turn is connected to a TClientDataset. here is some of my code... this code is called after to datasnap client calls the server method to add 1 or more rows to tables on the server:
function copyDataToServer (tblName : string;
dataIndex : integer) : integer;
var
i : integer;
s : string;
s2 : string;
begin
result := 0;// tmpCDS is a TClientDataset that has the data to be added to the server... the client passes a clientDataset.Data to the server using a Variant array.
tmpCDS.Data := transData [dataIndex];
// build a query to pull empty dataset from server
s := '';
for i := 0 to tmpCDS.FieldCount - 1 do
if s = '' then
s := tmpCDS.Fields .FieldName
else
s := s + ', ' + tmpCDS.Fields .FieldName;s := 'select ' + s + ' from ' + tblName + 'Transfer where RegID = ' + intToStr (RegID);
// QSv is a TSQLQuery
QSv.SQL.Add (s);
QSv.Prepared := true;// CDSSv is the TClientDataset connected to datasetprovider, which in turn is connected to QSv
CDSSv.Open; // this successfully gets an empty dataset for the table in question - after the open, CDSSv.CanModify is true, Readonly is false, recordCount is 0... all as they should be.
tmpCDS.First; // this is the dataset from the datasnap client
while not tmpCDS.EOF do
beginCDSSv.Insert;
// not all fields might be present, and order of fields might change...
for i := 0 to tmpCDS.FieldCount - 1 do
CDSSv.FieldByName (tmpCDS.Fields .FieldName).Value := tmpCDS.Fields .Value;CDSSv.Post; // this works, new row is saved in the clientdataset
tmpCDS.Next;
end;// at this point 100 +/- rows are in the clientdataset, CDSSv
try
result := CDSSv.ApplyUpdates (-1); // save recs to the transfer table - THIS BLOWS UP!!!
except on e:exception do
begin
writeDbugS ('result := CDSSave.ApplyUpdates (-1) exception - ' + e.Message;); // exception message is Invalid parameter
end;
end;
Any help is much appreciated... The above code has worked for 5 years. I'm updating things to try to keep up with android versions (for the client side of the datasnap) and in the process needed to update the datasnap server, but I've done something to make the above code stop working and I havn't been able to track it down.
-
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.
-
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.
-
Thank you for the link.
Re: when permissions are requested, it's not that I think I need to request outside the main thread, but the logic makes more sense to me to request the permission within the task that downloads the file.
IE, within the task, request permission to save to external storage, then if not granted, save the downloaded file to private storage
rather than:
request permission to save to external storage
start task to download a file.
Do you think it's a problem to request permissions outside the main ui?
-
One other question... If I have started a process using TTask.Run, and then within that thread I RequestPermission, then the permission handler is running in the context of the TTask thread, not the main thread, correct?
delphi camera focus
in FMX
Posted
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.