Chester Wilson 5 Posted March 10, 2021 I am having great difficulty getting a firemonkey programme to take piccies on an android device. This is the simplest programme I have managed to put together for this. It keeps blowing up no matter what I try! (I have put 3 full days work into it, with no success, and now seek help!) I am using Delphi in Embarcadero® RAD Studio 10.4 Version 27.0.37889.9797 (it will be a month before I can get home to download Sydney). The phone I am working on is a Huawei P20 Pro with android 10 (can I have android 7 back please?????) I got Marco's GitHub main form for a camera, and got the same error from it. I wondered if it were a Delphi bug, and sent it off to Quality.Embarcadero. Dave Nottage kindly replied, telling me to set the permissions. However, if the permissions are not set, the error message is different, and setting the permissions did not help. I sent back that Dave's considered response did not help any, but have heard nothing since. It is necessary to run it once, then go and set up the android settings permissions since android have become cripplingly paranoid from V10. The error message is: Project TryCamera1.spk raised exception class EJNIException with message 'java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData (android.content.pm.PackageManager, java.lang.String)' on a null object reference'. The crash comes on ExecuteTarget in FMX.MediaLibrary.Action where it is called with FCameraService.TakePhoto TryCamera1.dpr TryCamera1.dproj TryCamera1.dproj.local TryCamera1.identcache TryCamera1.res TryCameraMainUnit.fmx TryCameraMainUnit.pas TryCameraMainUnit1.fmx TryCameraMainUnit1.pas Share this post Link to post
Guest Posted March 10, 2021 (edited) hi @Chester Wilson try my CAM for Android test based on Fernando Rizzato (MVP leader Embarcadero on South America) hug Edited March 10, 2021 by Guest Share this post Link to post
Chester Wilson 5 Posted March 10, 2021 Thanks, hug! I will tackle it over the next few days. Even if the permissions for a programme have been set in "Settings" on an android device, and set up in the programme (project/options etc), is it still necessary to go through all the code for the permissions in the programme as well? Or is that so that the user can get an error message telling him which permissions have not been set? Share this post Link to post
Guest Posted March 11, 2021 6 hours ago, Chester Wilson said: ...Or is that so that the user can get an error message telling him which permissions have not been set? your software, SHOULD verify if the permissions was or not conceded by Android (OS) - ALWAYS! the Android, as know, store this info for each app, but, the app should verify if the permissions still granted! hug Share this post Link to post
Chester Wilson 5 Posted March 13, 2021 Have you any idea how to get location permission not only for when the programme is the primary one on the screen, but always? In earlier androids I could continue tracking, go off an do something else briefly, then return to the tracking programme. In recent androids this turns off the location to the tracking programme, really messing up the data collection! (Why they think location is a dangerous privilege I do not know. The only time I can see it being dangerous is if I am going somewhere where my wife does not want me to go, and she finds out about it!) Share this post Link to post
Guest Posted March 13, 2021 (edited) in app, one time conceded the permition by user, it stay until he remove the app or the permitions. now, about Android O.S., you can go in SETUP-APPLICATION find you app and change or see its permitions. or click on app-icon and hold until appears some menu. https://developer.android.com/guide/topics/permissions/overview note: my nickname is EMAILX45 not HUG 😂 hug Edited March 13, 2021 by Guest Share this post Link to post
KodeZwerg 54 Posted March 14, 2021 Hello Hug emailx54 and Chester, isnt it that nowadays the Android system uses stronger battery saving features? To always be able to run tasks in background is what a User tells his Android -> allow/set background-tasks manually. Am i wrong? I just found this info about how to create background tasks, there is nothing about Android setting explained... mhhhhh strange world. noHug, Corona forbid it :-] Share this post Link to post
Chester Wilson 5 Posted March 14, 2021 Sorry, EmailX45! I will accept the "hug" at the bottom of your email as a friendly "man hug" and call you by your preferred name! The problem is that the later versions of android will only allow you in the "Settings" for a programme to have location as either deniet or "Only while app is in use"! It seems to be part of their idea that some permissions are regarded as "dangerous", and therefore are limited in their availability. Unfortunately I need to be able to continue tracking (small furry animals in remote areas of Australia) without interruption - and I cannot find out how to get android to cooperate!!!! i go to another app briefly, and the GPS gets turned off my tracking programme! This is a real problem, and I would like to get a useful answer to it. Any idea whom I should ask? Share this post Link to post
Guest Posted March 14, 2021 hi @Chester Wilson in Android 9/10 you need to say that you "need that your app dont use POWER MANAGEMENT...", or be, you need exclude your app this behavior. Manually, you need find your app, and, in Battery options, say that your app dont "SLEEP" in background. Then, here, you need access the permitions more restrictive on system. Many app, should use a certificate for that, for security, as say the Android rules in link above. You see? Unfortunatelly, I dont have a sample for this in my tests for Android. But, basically, you needs ask the permittions for access this area on Android for you app. For that, the restriction for security area on Android, else, any app would can access this area and access the user-datas. and, location is a basic area to find a user in a city for example... now, imagine you been followed by a "psico-killer" hmmmmmmmm hug Share this post Link to post
Guest Posted March 14, 2021 14 hours ago, KodeZwerg said: To always be able to run tasks in background is what a User tells his Android -> allow/set background-tasks manually. yes and not. Yes, for that user know this necessity. No, because, in programming you can do it. please, read the Android permitions (link above), and the secction about "use of certifacates" for OEM Android. As in another area, web for example, and today in many others "local" places, the certificate use, do more simple truth a app/user as secure or same give-a-pass as right. hug Share this post Link to post
KodeZwerg 54 Posted March 14, 2021 1 hour ago, emailx45 said: yes and not. Yes, for that user know this necessity. No, because, in programming you can do it. please, read the Android permitions (link above), and the secction about "use of certifacates" for OEM Android. As in another area, web for example, and today in many others "local" places, the certificate use, do more simple truth a app/user as secure or same give-a-pass as right. hug With my current little level of knowledge about Android internals, I can only say that you can't force it on the program level. But what you can do is to use the release authorizations (permissions) to oblige the user to enter into a contract with you. So the user is the decisive factor. (As always hehehe) Since my knowledge is poor I will do follow your advice with glance and put my head into documention. Hugging thanks back. Share this post Link to post
Guest Posted March 14, 2021 (edited) remember, some "techs" is not allowed, but, it's possible... else, we would have no problems with adware, spyware, and other virus-family ... now, with a 'truth certificate' you can do it. hug Edited March 14, 2021 by Guest Share this post Link to post
Chester Wilson 5 Posted March 18, 2021 Well, fellas, thanks for your ideas. I can request required permissions now, and get some of them! (Why it won't give me WAKE_LOCK I know not. Reasonable not to give me ELEPHANT though!) The location one still comes up with the annoyance of "only while active". I am not sure that the argument about a tracking predator is good enough to bugger it up for everyone, especially as a tracking predator would have to get hold of the victim's phone and set it all up. However, it really buggers up my job of tracking small furry mammals in the middle of Australia! I could not find anything explanatory in the suggested reading on certificates, how to use them, where to get them, and what they may be capable of doing for this problem. Unfortunately, I have had no luck with the camera stuff. I have taken your ideas, and other ideas from the net, and put together two means of accessing the camera. Neither of them works, and they still prang with the extremely unhelpful message of : "java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager,java.lang.String)' on a null object reference." The sample files are attached in a single .zip. I would greatly appreciate any ideas, as the various delphi help facilities and the net have been no help at all! Permissions.zip Share this post Link to post
Guest Posted March 18, 2021 hi @Chester Wilson try review your code!!! really it is not good at all... if it should works... really, I dont know! Your environment, your problems. try this changes and other if necessar ... when clicking in button to take a picture or choice the CAM PermissionsService.RequestPermissions( { } [lMyCAMPermission], { } prcPermissionsResulted, { } prcDisplayRationale { = nil, if you DONT WANT show any message! } ); //****************************************** {$IF DEFINED(ANDROID)} // DisplayRationale and PermissionsResulted is used only mobile! procedure TfrmFormMain.prcDisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc); var lRationaleMsg: string; i : integer; begin for i := 0 to high(APermissions) do begin if APermissions[i] = lMyCAMPermission then lRationaleMsg := lRationaleMsg + 'This app needs access your CAM to works' + SLineBreak + SLineBreak; end; // // Show an explanation to the user *asynchronously* - don't block this thread waiting for the user's response! // After the user sees the explanation, invoke the post-rationale routine to request the permissions // TDialogService.ShowMessage(lRationaleMsg, procedure(const AResult: TModalResult) begin // TProc is defined in System.SysUtils // APostRationaleProc; // used by System to go-back in before function... end) end; procedure TfrmFormMain.prcPermissionsResulted(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); begin // verifying if the permissions was granted! - Here, testing only 1 permission = CAM if (Length(AGrantResults) = 1) {my CAM permission} and (AGrantResults[0] = TPermissionStatus.Granted) {was granted or not?} then // // here it's where your CAM should have the permission confirmed or not by System!!! prcCAMStartCapture { execute your procedure here if all it's ok } /// else TDialogService.ShowMessage('The permission <<CAMERA access>> not allowed by user'); end; {$ENDIF} //***************************************************** // same unit than your procedure to CAM use, or in any other levelup // the "initialization section" is called on "order than unit-use", or be, in "uses clauses" order // initialization // prefere use here!!! aPermissions[0] := JStringToString(TJManifest_permission.JavaClass.CAMERA); aPermissions[1] := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE); aPermissions[2] := JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION); aPermissions[3] := JStringToString(TJManifest_permission.JavaClass.ACCESS_COARSE_LOCATION); aPermissions[4] := JStringToString(TJManifest_permission.JavaClass.CALL_PHONE); aPermissions[5] := JStringToString(TJManifest_permission.JavaClass.WAKE_LOCK); // aPermissions[6] := JStringToString(TJManifest_permission.JavaClass.ELEPHANT); ??? finalization end. hug Share this post Link to post
Chester Wilson 5 Posted March 18, 2021 Thanks for your response, emailx45! I was trying to simplify it down to a minimalist programme to hone in on where the error may be coming from. I do not need to send any rationale to the user. The system box requesting permission is quite, quite enough! The RequestPermissions is sending me the correct information - ie that the programme has been granted CAMERA permission, and it works without any problems. The problem is in the next bit, where I try to access the camera. The error message comes after either the TakePhoto() or the TakePhotoFromCameraAction1.Execute Dave Nottage suggested that I had to get camera permissions first. I have done that successfully (well, the RequestPermissions returned .Granted, so I assume that means all is well), but the same error message persists, and I would love to be able to get rid of it. My apologies if my pascal reads like programming by a Fortran programmer! As I have nobody else for 1000km whom I know of to interact Delphi programming with, I am stuck with my background. Share this post Link to post
Guest Posted March 18, 2021 as I said in my sample post... ALWAYS IS NECESSARY VERIFY THE PERMISSIOBS BEFORE ANY ITERATION WITH CAM OR OTHERS. Then, if you SDK is right with your IDE and project, it should works.... except uf exist any bug on parts (you, IDE or Android). but if works in another device, then, you can compare with Huawey P20... Now, RAD10.4.x is bugged in many areas, mainly in another platforms. My tip: try compile in RAD10.3.3 and see if same error happens. Try my sample in my post link (it was tested in Androud 7.0 Nougat and works. Later, try in your Huawaey P20. hug Share this post Link to post
Guest Posted March 18, 2021 (edited) now about have your Android 7.0 back... no way without hack your device. Or be, you need install the Android 7.0 image (as a ISO in MSWindows) using a tool for that. But can be a risk do it, you see? on Internet you found many tools for that, mainly in forums about Android not official. But warning about download Android images from unknow sources. Google Android Developers site: https://developer.android.com/topic/generic-system-image Here, a project to emulate Android system on VirtualBox or VMWare for tests using your pc. https://www.linuxvmimages.com/images/android-x86/ hug Edited March 18, 2021 by Guest Share this post Link to post
Chester Wilson 5 Posted March 20, 2021 Thanks for your warnings, emaiilx45! No, I am not going to take my phone back to a7 - and nor would the other users of the programme. It is interesting that Dave Nottage, to whom I sent the latest version of the programme, had no trouble running it under 10.3.3. I tried it with 10.3.3 on m computer and still got the same error message. My android seems to be 25.2.5. Could that be a problem? Otherwise my option seems to be getting / writing a java wrapper for camera2 - which looks pretty daunting! Share this post Link to post
Dave Nottage 557 Posted March 20, 2021 1 hour ago, Chester Wilson said: Otherwise my option seems to be getting / writing a java wrapper for camera2 - which looks pretty daunting! It was pretty daunting for me: Native Camera for iOS and Android – Delphi Worlds There's still a number of issues to resolve... 1 Share this post Link to post
Rollo62 536 Posted March 21, 2021 (edited) Hi Dave, thanks for that, always one step ahead 👍 I just briefly looked into it, I wonder if it would be possible to intercept the texture stream, and if so where its best to do that ? Beside facedetetion, I find it much more interesting to implement own filters in the image stream on the fly, and to put features and drawings on top of the preview video. I'm not sure if any FMX control can be above the Camera preview, but shouldn't that be possible with the updated Z-order in Android ( in iOS too ) ?. So far I'm not sure where the textures can be intercepted. I find the (for Android) FSurfaceTexture: JSurfaceTexture; FSurfaceTextureListener: JTextureView_SurfaceTextureListener; which leads to the assumption that this could be tapped somehow. Just checked the Andoid part, not sure about iOS, but IOS was more performant anyway. Would be interesting to know if you are also work on such kind of image-processing for video stream from the camera ? Edited March 21, 2021 by Rollo62 Share this post Link to post
Dave Nottage 557 Posted March 21, 2021 10 hours ago, Rollo62 said: I wonder if it would be possible to intercept the texture stream I have been working on that. I needed to make a substantial change to using an OpenGL surface - a problem I am having is doing a transform when the device is not oriented in the "normal" position. 10 hours ago, Rollo62 said: I find the (for Android) FSurfaceTexture: JSurfaceTexture; FSurfaceTextureListener: JTextureView_SurfaceTextureListener; which leads to the assumption that this could be tapped somehow. That already is "tapped", however the SurfaceTextureListener is not the right place. As per my comment above, I've switched to using GLSurfaceView: https://developer.android.com/reference/android/opengl/GLSurfaceView Which uses: https://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer The GLSurfaceView calls onDrawFrame of the Renderer when a new frame is available, so the capture/filtering can be done there. This part is all done in Java, however the Delphi code could "hook" into the filtering, and can already pass a Java bitmap of the resulting frame to Delphi. Again as per above, I want to resolve the transform issue which is currently eluding me. I'm willing to share the work in progress with others if they think they can help. Best to join my Slack workspace to do so: https://slack.delphiworlds.com 1 Share this post Link to post
Chester Wilson 5 Posted March 21, 2021 All I want to do is take a bloody piccie! Here is the next episode - trying to use the definitions in Androidapi.JNI.Hardware. It crashed most effectively with non-explanatory error messages in both 10.3 and 10.4. It needs 2 buttons (ButtonPiccie and ButtonExit) and an Image. (Not sure if this is easier than trying to send the files, or more of a nuisance - please tell me!) unit TryCamera3MainUnit; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Memo.Types, FMX.Objects, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, System.Permissions, FMX.Memo, Androidapi.JNI.JavaTypes, Androidapi.JNIBridge, Androidapi.JNI.Hardware, Androidapi.Helpers; type TForm1 = class(TForm) ButtonPiccie: TButton; Memo1: TMemo; ButtonExit: TButton; procedure FormCreate(Sender: TObject); procedure FormActivate(Sender: TObject); procedure ButtonPiccieClick(Sender: TObject); procedure RequestPermissionsResultProc( const aPermissions : System.TArray<string>; const aGrantResults : System.TArray<tPermissionStatus>); procedure ButtonExitClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; aPermissions : System.TArray<string>; aGrantResults : System.TArray<tPermissionStatus>; implementation {$R *.fmx} procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Lines.Clear; end; procedure TForm1.FormActivate(Sender: TObject); begin aPermissions := ['android.permission.CAMERA']; PermissionsService.RequestPermissions( aPermissions, RequestPermissionsResultProc); end; procedure TForm1.ButtonExitClick(Sender: TObject); begin Application.Terminate; end; procedure tForm1.ButtonPiccieClick(Sender : tObject); var Cam : JCamera; h, w : integer; begin Cam := TJCamera.Create; //Crashes here Memo1.Lines.Add(JstringToString(Cam.toString)); Application.ProcessMessages; Cam.startPreview; //Originally crashed here h := Cam.getParameters.getPictureSize.height; w := Cam.getParameters.getPictureSize.width; Memo1.Lines.Clear; Memo1.Lines.Add('Height: ' + inttostr(h)); Memo1.Lines.Add('Width: ' + inttostr(w)); end; procedure tForm1.RequestPermissionsResultProc( const aPermissions : System.TArray<string>; const aGrantResults : System.TArray<tPermissionStatus>); var s : string; begin s := 'Unknown'; case aGrantResults[0] of tPermissionStatus.Granted: s := 'Granted'; tPermissionStatus.Denied: s := 'Denied'; tPermissionStatus.PermanentlyDenied: s := 'Permanently Denied'; end; Memo1.Lines.Add(aPermissions[0]); Memo1.Lines.Add(s); end; end. Share this post Link to post
Dave Nottage 557 Posted March 21, 2021 50 minutes ago, Chester Wilson said: Cam := TJCamera.Create; //Crashes here You do not create an instance of JCamera using Create. As per the documentation: Camera | Android Developers To take pictures with this class, use the following steps: Obtain an instance of Camera from open(int). Share this post Link to post
Chester Wilson 5 Posted March 25, 2021 Dear Everyone, More from the struggling department! Click on that Camera | Android Developers reference and you get taken to a deprecated page. I have looked at the Java Camera2 page - which is fine if you want to write in Java! Not so helpful if you can't get the Delphi basics sorted out (but yes, it would be very helpful after that.) I have tried to get the files from Github. It does not give me an option to download. I can look at each of the files in turn, select all the text, copy then paste into notepad then save with the correct filename. Messy - but there must be a better way (which I have not found yet). Any ideas please? In Androidapi.JNI.Hardware Delphi pseudo-interfaces are created, with what should ideally be class methods, but for syntactic reasons they are just methods. Unfortunately when you type something to reference one of these methods it will not let you. (If you write one yourself, does the UUID have to match something deep in the bowels of Java, or can you just generate your own UUID?) For example, trying to get the number of cameras available to decide which to open: i := JCameraClass.getNumberOfCameras; - can't find any getNumberOfCameras function. In fact, typing JCameraClass. gives none of the "Class" functions which should be available. What syntax should be used to get this to work please? Share this post Link to post
Chester Wilson 5 Posted March 25, 2021 Found! On the Kastri page, you have to click on "Code" before you can Download. (Beats me, but it rhymes.) NOW I can start to get some understanding. 1 Share this post Link to post