In my last article, I discussed the new requirements for Android apps on Google Play to target Android 8 (API level 26) and higher, and described one possible way of handling permission requests at runtime, as required when targeting Android 6 (API level 23) and higher. In this article, I describe an alternative, and also cover the requirement for apps targeting Android 7.0 (API level 24) and higher when accessing “external” URIs.
As per the last article, this article and demo was produced using Delphi Tokyo 10.2.3. The code may or may not work with earlier versions. NOTE: If you’re using Delphi 10.3 or higher, you should use the built-in support for permissions and external URIs.
UPDATE (July 20th, 2018): The demo has been modified to allow for a workaround for local notifications when targeting API 26 or greater. See below for details.
TL;DR: The demo code for this article can be found in the KastriFree project, here.
Targeting an API level
There has been some confusion over what “targeting” a particular API level means. It does not mean which Android SDK you have configured in the SDK Manager in the Delphi IDE. It means what value is set for the targetSdkVersion value in the application manifest:
This is the API level at which Android will act in “compatibility mode” for. By default, Delphi sets this value to 14 (Android 4.0). The device can still have a later version of Android installed, and your application can still use API calls that apply for the installed version, however it will act as if it were at the target level. For example, an app targeting API level 14 on a device running Android 6 will not require requesting permissions at runtime.
At present, to target a particular API level, you need to manually modify the AndroidManifest.template.xml file, as described in the previous article.
A change in the method for responding to runtime permission requests
In the previous article, I devised a method of requesting permissions at runtime that required “overriding” FMXNativeActivity in the manifest. Unfortunately, that meant having to launch the application from the device manually in order to debug via the IDE. Thanks to a suggestion from Stephane Vanderclock, author of the Alcinoe library, I’ve devised a different method that removes the need to “override” the activity.
Through necessity (which will become clearer later), I have created a new class called TPermissionsRequester, which more accurately reflects what it does anyway. This replaces the TSystemHelper class, which I recommend you stop using altogether, if you choose to change to using this new solution.
When a runtime permissions request is made, the focus moves away from the application, and once the user has granted or denied permission, the application receives focus again, and the BecameActive event fires. TPermissionsRequester handles this event, and if a permissions request has been made, checks whether such permissions were granted:
procedure TPlatformPermissionsRequester.ApplicationEventMessageHandler(const Sender: TObject; const AMsg: TMessage); begin case TApplicationEventMessage(AMsg).Value.Event of TApplicationEvent.BecameActive: CheckPermissionsResults; end; end; procedure TPlatformPermissionsRequester.CheckPermissionsResults; var LResults: TPermissionResults; LIndex, I: Integer; begin if FRequestCode = -1 then Exit; SetLength(LResults, Length(FPermissions)); for I := Low(FPermissions) to High(FPermissions) do begin LIndex := I - Low(FPermissions); LResults[LIndex].Permission := FPermissions[I]; LResults[LIndex].Granted := TOSDevice.CheckPermission(FPermissions[I]); end; TOpenPermissionsRequester(PermissionsRequester).DoPermissionsResult(FRequestCode, LResults); FRequestCode := -1; end;
So all the developer needs to be concerned with is requesting the actual permissions, and handling the OnPermissionsResult event:
constructor TForm1.Create(AOwner: TComponent); begin inherited; FRequester := TPermissionsRequester.Create; FRequester.OnPermissionsResult := PermissionsResultHandler; end; procedure TForm1.TakePhotoButtonClick(Sender: TObject); begin FRequester.RequestPermissions([cPermissionReadExternalStorage, cPermissionWriteExternalStorage, cPermissionCamera], cPermissionsCodeExternalStorage); end;
As TPlatformPermissionsRequester (in DW.PermissionsRequester.Android) uses TApplicationEventMessage which comes from the FMX.Platform unit, it cannot be used in a service (at least at present). That’s why TPermissonsRequester was created, and CheckPermission method has been moved to TOSDevice, so that it can be used in a service.
Note that in this demo, permissions are requested only when absolutely required (i.e. when the user wants to take a photo). This makes the application a little more user friendly than if the permissions were requested as soon as the application starts.
In the code, I am passing the string representation of the permission, e.g.
cPermissionCamera = ‘android.permission.CAMERA‘;
The format for all of the “dangerous” permissions is the same, i.e. it follows the pattern: android.permission.XXXX, where XXXX is one of the “Permissions” values in this list, so you can define your own values to be passed to the RequestPermissions method in the same manner.
Note that even though you’re requesting permissions at runtime, you still need to check the checkboxes for those permissions in the Uses Permissions section of the Project Options
Accessing “external” URIs
If you have tried to target API 26, and attempted to use the TTakePhotoFromCameraAction, you would have noticed that it fails, with the error:
android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
From Android 7.0 (API level 24), when accessing “external” URIs, it is necessary to use the FileProvider class. Unfortunately, the code that causes the problem for TTakePhotoFromCameraAction is actually within the Java binaries (FMX.jar) that Delphi uses, so rather than expect developers to patch and recompile FMX.jar, I’ve come up with an alternative solution.
TMediaLibrary is an alternative for (at least for the present), TTakePhotoFromCameraAction. I may or may not expand on it, depending on how useful it becomes, and how Embarcadero handle the required changes. It has a single method: TakePhoto, and has event handlers for when the image is captured successfully, or when the user canceled.
TMediaLibrary = class(TObject) private FPlatformMediaLibrary: TCustomPlatformMediaLibrary; FOnCanceled: TNotifyEvent; FOnReceivedImage: TReceivedImageEvent; protected procedure DoCanceled; procedure DoReceivedImage(const AImagePath: string; const ABitmap: TBitmap); public constructor Create; destructor Destroy; override; procedure TakePhoto; property OnCanceled: TNotifyEvent read FOnCanceled write FOnCanceled; property OnReceivedImage: TReceivedImageEvent read FOnReceivedImage write FOnReceivedImage; end;
Also it is currently useful only on Android, as there are no implementations for the other platforms.
TMediaLibrary makes use of a function from the newly created unit DW.Android.Helpers, called UriFromFile. This method checks what the targetSdkVersion value is, and if >= 24 it uses the FileProvider class to create a Uri from the file reference, passing in the “authority” which needs to be specified in the manifest. This is done by adding a Provider section, like this:
When using the UriFromFile function, the value specified in the manifest for android:authorities will need to match the application’s package name. This value appears in the Project Options under Version Info.
Note the entry: <meta-data android:name=”android.support.FILE_PROVIDER_PATHS” android:resource=”@xml/provider_paths”/>. This is a reference to a file that needs to be deployed with the application, called (in this case): provider_paths.xml. This is what the file looks like:
This file needs to be added to the application’s deployment using Deployment Manager, and the Remote Path value set to: res\xml\
Remember that when targeting API level 24 or greater, your app will need to request the appropriate permissions at runtime (as per the demo), before attempting to use the TakePhoto method. I had considered making TMediaLibrary handle all this automatically; perhaps in the future 🙂 You should also remember that there are a number of other “dangerous” permissions that may be used throughout Delphi (e.g. by TLocationSensor). Be sure to request permissions at runtime for any of those that require it, before you attempt to use them.
Remember also that the UriFromFile function can be used in your own code if your app needs to access “external” files. You will certainly know this is the case if your application throws the dreaded FileUriExposedException.
Taking care of the status bar
In the previous article, it had slipped past me that when changing the API target, the status bar was no longer visible!
In this demo, the workaround was to change the Fill property of the form, setting the Color to Null, and the Kind to Solid. In addition, a Rectangle is added to the form, the Align property set to Contents, and the Color property of Fill set to Whitesmoke. Now the status bar is visible again, however remember that this is just a workaround; hopefully an official solution will present itself in the next update.
Getting notified..
The demo has been updated (July 20th, 2018) to allow for a workaround for local notifications. In order for them to work however, you will need to patch the System.Android.Notification unit from the Delphi source. Details on how to do this are in the readme. Also, you will need to use new files added to KastriFree, namely:
DW.Androidapi.JNI.App
DW.Androidapi.JNI.Support
DW.NotificationReceiver
support-compat-26.1.0.jar
Note also in the demo that the original android-support-v4.dex.jar is disabled. This is because the demo uses a newer version of the Android support libraries:
Are there other issues that need to be accounted for when targeting later API levels?
I’m glad you asked! At present, I’m unaware of any other issues, however my plan is to expand the demo in the future if any others come to light. If you are aware of any that are not related to what I’ve already covered, please let me know in the comments.
The demo code for this article can be found in the KastriFree project, here.
Thank you for the article Dave. It will surely help allot. Have you posted you solution on the EMBT quality portal? I see there some issues logged there, and the guys are getting nervous. I don’t see any useful communication from EMBT regarding this issue.
Can you let me know which issues in the quality portal that are affected that you know of, where I haven’t already commented about my workarounds? Thanks!
I’m sure Embarcadero read your posts. I Hope they support or sponsorize your work because I read a solution (with some problems of course) in your website several weeks before embt said any word.
We are nervous because the countdown continues and we have no roadmap to solve this issue.
Thank you very much Dave,and sorry, my English is not good
What NDK version and API version combo is able to be used? Will API 28 work ok with NDK r9c (Standard in Tokyo?)
API 27 (Android 8.1) works OK with it. I don’t have a device with API 28, so I could not say for sure. Perhaps someone else can check?
just installed NDK r17c and getting segfaults in app at TAndroidApplicationGlue.OnCreate at startup so guessing something is not compatible with Delphi with newer NDK’s, No EMB documentation on this at all. Read somewhere that someone was using NDK 14 or 15.
Installing the 64 bit version of NDK seems to have worked, odd as r9c doesent look to be 64bit,
So have API 28 and NDK r17b running our app.
Hello Matt,
just a question regarding the SDK / NDK.
Do you use SDK and NDK 17b 64 Bit downloaded from https://developer.android.com/ndk/downloads/ with Delphi Tokyo 10.2.3 and does this work?
For some external libraries I have to update the NDK from 9 to somewhat higher but when I did I get crashes when my apps start.
Android 5.0.2 errors: Invoke error: method not found:
Project AndroidDangerousPermissions.apk raised exception class EJNIFatal with message ‘Invoke error: method not found’.
line 288: raise EJNIFatal.CreateRes(@SJNIUnknownMethod); in unit unit Androidapi.JNIMarshal
Delphi Tokyo
I don’t have an Android 5 device where I can check this issue. Can you provide a callstack so that it can be determined exactly which method is the problem?
Android 5. Project AndroidDangerousPermissions.apk raised exception class EJNIFatal with message ‘Invoke error: method not found’.
CallStack printScreen http://prntscr.com/kax7ma
I’ve updated this file:
https://github.com/DelphiWorlds/KastriFree/blob/master/Core/DW.SystemHelper.Android.pas
Which should fix the problem. Note that it requires this file:
https://github.com/DelphiWorlds/KastriFree/blob/master/Core/DW.Android.Helpers.pas
[…] Head over and check out the full solution for targeting Android 8 (SDK 26) with Delphi 10.2.3 Tokyo. […]
[…] Targeting Android 8 and higher, continued […]
[…] In light of this requirement, Embarcadero Technologies has announced that they plan to deliver support for Android API level 26 in their next major release of RAD Studio, 10.3. In the meantime, they suggest that their customers on Update Subscription join the upcoming 10.3 Beta. They also recommend that you take a look at Embarcadero MVP Dave Nottage’s blog post on how to target Android API level 26 with Delphi, C++Builder and RAD Studio 10.2.3 Tokyo (read it here). […]
Do you know if for Delphi Berlin Aniversario version contemplates this your correction for the new permissions method?
I don’t know what the Aniversario version is, however I do not use Berlin any more. Perhaps someone who does use it can check?
Hello Delphi Words, would you help me please. I’m having trouble getting “Gettubg notified”. I can not complete the last step.
“3. Open a command prompt, change to the project folder, and execute the following command:”
Could you tell me if you are having any problems with the procedure?
1. Install the Patch tool from http://gnuwin32.sourceforge.net/packages/patch.htm
Location of installation: C:\Program Files (x86)\GnuWin32\
2. Copy System.Android.Notification.pas from the Delphi source (described above) to the demo project folder
Copied to: D:\Embacadeiro\Projetos\KastriFree-master\KastriFree-master\Demos\AndroidAPI26\System.Android.Notification.pas
3. Copy System.Android.Notification.10.2.3.API26.patch from the Workarounds folder in the KastriFree library (described above) to the demo project folder
Copied to: D:\Embacadeiro\Projetos\KastriFree-master\KastriFree-master\Demos\AndroidAPI26\FMX.VirtualKeyboard.Android.10.2.3.patch
3. Open a command prompt, change to the project folder, and execute the following command:
1 Open CMD as administrator!
2 I went in the project folder
CMD – d:
CMD – cd D:\Embacadeiro\Projetos\KastriFree-master\KastriFree-master\Demos\AndroidAPI26\
3 \Patch System.Android.Notification.pas < System.Android.Notification.10.2.3.API26.patch
Command executed: C:\Program Files (x86)\GnuWin32\Patch System.Android.Notification.pas < System.Android.Notification.10.2.3.API26.patch
[…] http://delphiworlds.com/2018/06/targeting-android-8-and-higher-continued/ […]
Hi Dave, brilliant solution for 10.2.3. However, have you thought of a solution concerning earlier versions of Delphi. It appears that some of the AndroidAPI units such as Androidapi.JNI.GraphicsContentViewText have changed for 10.2.3 when compared with 10.1 🙁
Hi Sam,
Aside from the copyright notice, Androidapi.JNI.GraphicsContentViewText is identical between 10.1 and 10.2.3. Perhaps you mean some other unit(s)? If so, please describe exactly what is different, and what problems the differences cause.
I’m lost ! I don know how o make this work. What I need is API26 requirement for Android (read external storage, push notifications).. even I dont know if i have to patch some tokio files and wich files
1- Downloaded patch from http://gnuwin32.sourceforge.net/packages/patch.htm.. doesn´t work in w10 or at least I only see a command box.. if i write in it .. System.Android.Notification.pas < System.Android.Notification.10.2.3.API26.patch do NOTHING
I followed all other steps (manifest,etc)
What I missing? all… i cant go forward
Patch is a command-line program, i.e. you should open a command-line window to run it. As per the instructions, make a copy of System.Android.Notification.pas in the *same* folder as the demo project. It makes things easier if you copy the .patch file to the same folder, then change directory to the project folder and use this command:
C:\Utils\patch System.Android.Notification.pas < System.Android.Notification.10.2.3.API26.patch Replacing C:\Utils with whatever folder you installed Patch in. This is the only source file that needs to be patched, and it is for Local Notifications to work in API 26+
Thank you Dave. It works fine… the reason was because I was not running CMD as administrator
Hi Dave, I have used the TMediaLibrary for the Camera Action fix, but it seems to rotate an image (90 deg Anticlockwise) when picture is taken in portrait on Android device, it’s OK if taken in landscape. I tried my same project on an old device (Android 4.4) where the my code will then use TTakePhotoFromCameraAction instead and the image comes in correctly in portrait (no rotation). Do you have any ideas what I can do to fix that?
Thanks
Tom
Hi Tom,
Not sure why it would be doing that (it works ok on both my devices), however there’s some code in this demo:
https://github.com/DelphiWorlds/KastriFree/tree/master/Demos/ObtainPhotoInfoDemo
That shows how to obtain information about an image using the ExifInterface Java class, specifically in the GetEXIF method of TForm1 in Unit1.pas. You could modify the code in TPlatformMediaLibrary.MessageResultNotificationHandler in the DW.MediaLibrary.Android unit to make a call like this:
LEXIF.getAttributeInt(TJExifInterface.JavaClass.TAG_ORIENTATION, -1)
which retrieves the orientation, and compare it to TJExifInterface.JavaClass.ORIENTATION_NORMAL, TJExifInterface.JavaClass.ORIENTATION_ROTATE_180 etc. You could then use the Rotate method of the LBitmap to correct the orientation.
I’m unable to give a complete solution right now as I am travelling at the moment and my time is a bit limited. If you get stuck, let me know and I’ll see what I can do.
Thanks a lot for the reply I will look into that today. Another thing we discovered is the image is very large (probably original size) compared to the old Camera Action method, any suggestions on that would be appreciated.
Hi Dave, using your suggestion I got the Orientation corrected if it happens to be out, and have found a way to resize the image
Thanks
Hello, what solution did you find for resizing the image?
I can’t seem to get the WRITE_SETTINGS permission to work. Even though it is checked in the permissions of the project options, when I check the app permissions within the application manager on the phone, it doesn’t show up. Other permissions – calendar, camera, etc. – they are all there, but nothing for write_settings. I want to change the screen brightness. Can someone try to get that permission working? Thanks.
There’s some details on how to make the permission work here:
https://www.dev2qa.com/how-to-grant-write-settings-permission-in-android/
Though it’s in Java. If you’re unable to work it out in Delphi code, I might be able to find time to
In the many hours I spent searching for a solution, I ran across that web page, and I tried making the extra changes to the manifest file (the activity part)…and of course the write_settings permission was already in there….but the application manager still missing “allow modify system settings” as shown on that web page, and there is still an error when the permission requester tries to request that permission. I assume the permission requester has no chance of working if the OS doesn’t even think the app should have that permission.
I was able to use the following code to enable write settings (make sure to enable Write Settings in the Permissions section of the Project Options):
The trick is to alert the user to use the “Back” button once they have changed the settings
Thanks! It works. It works differently than the other permissions (i.e., instead of a dialog box with allow/deny, it provides a full screen form with a toggle switch). I wonder if that is the only way in which it was intended to work for that particular permission. In any case, thanks for looking into the issue.
[…] In lieu of using the 10.3 beta to deliver Android API level 26 ready apps, another option is to follow Embarcadero MVP Dave Nottage’s excellent blog post on how to target Android API Level 26 with Delphi, C++Builder and RAD Studio 10.2.3 Tokyo: http://delphiworlds.com/2018/06/targeting-android-8-and-higher-continued/ […]
Hi Dave, thank you very much for your article.
By following your instructions, Play Store accepted my .apk file.
However, I got a strange side effect: my App’s BluetoothLE component doesn’t anymore Discover any device, when searching !!!
Restoring targetSdkVersion to it’s default value, the App finds devices again …
Any idea about what could be the reason, or how to proceed?
Thanks again!
Hi Vilson,
In order for Bluetooth scanning to work, you need to request permissions for location services, i.e. android.permission.ACCESS_COARSE_LOCATION and android.permission.ACCESS_FINE_LOCATION
Thanks for the article, Dave. I have tried to follow each step in an app that I want to compile for Android 8.0 but it reports an error in the System.Android.Notification file that I previously patched. Specifically, the error is on line 367:
LIntent.setAction (TNotificationReceiver.ACTION_NOTIFICATION);
[dcc32 Error] System.Android.Notification.pas (367): E2003 Undeclared identifier: ‘ACTION_NOTIFICATION’
I suppose that in some step I have lost.
Greetings and thanks again for the great article.
Hi Javier,
It’s very odd that the compiler would error on ACTION_NOTIFICATION, but not on TNotificationReceiver. Can you make sure that the implementation uses clause of the patched System.Android.Notification unit looks like this?:
..and that the DW.NotificationReceiver unit is in the compiler path?
Hi Dave, thanks for answering. If I have DW.NotificationReceiver in the path of the compiler and also, when in doubt, I added the file directly in the project, but I keep reporting the error. And the file System.Android.Notification.pas seems to be correctly patched with your patch because I can see the comments with // DW …..
Greetings and thanks.
Hello Dave.- I add one more error when compiling in case it helps:
[DCC Error] System.Android.Notification.pas(368): E2250 There is no overloaded version of ‘putExtra’ that can be called with these arguments
Greetings and Thanks. And sorry for my poor English. I’m Spanish and I only read some English.
Dave, Why Never Enter to IF AResults.AreAllGranted ……..
Does the problem occur in the demo, without any modifications, or is this your own code? If it is your own code, please provide the code so that the problem can be found.
Your Demo AndroidAPI26, get Request Permission occured when Button Event Click.
It’s my own program base on AndroidAPI26 on KastriFree, I put at Drive : https://drive.google.com/drive/folders/14Xvx8gmYajDxtoDfXamEhbdGtXhXsuQ6?usp=sharing
It’s just First Form
Sorry with My English
Have you made sure that you have added all the permissions in the Project Options?
Does it reach the line where AreAllGranted is called? Have you debugged into that routine to see which permissions have not been granted?
Your English is fine 🙂 I assume from your code that you speak Indonesian? I speak it, a little
OK Dave, I try again later (there’s something make be little busy), I think I was forget to check Permission list.
Right Dave I’m Indonesia. Do You have been visit my country ? It’s supprise that you can speak Indonesia
I have been in Bali for the past 6 weeks.. just going back to Australia today!
Dave, After I checked Uses Permission, It’s still the program never reach line …. IF AResults.AreAllGranted
I got Request Permission for twice
Iam creating a PDF and then viewing it using intents but aafter following the instructions here it cannot find the pdf I’ve created. Where should I create it and do you have an example please? The user permission side of this works perfectly.
Hi Ken,
I’ve sent you an email about it
Hi Dave,
I have now successfully implemented all your solutions for targetAPI 26.
Thanks again!
I have some suggestions for the text and demos:
(1) Demo project AndroidAPI26: it needs ..\..\Include to be added to the Search path (Project Options)
(2) Regarding manifest template for TMediaLibrary: maybe better to use android:authorities=”%package%.fileprovider”
In that case Delphi will automatically replace %package% for the package name, and people (like me;)) will not forget the .fileprovider part.
(3) Maybe obvious, but if an app needs a dangerous permission, this permission should also be added in the manifest (by select them in Project Options, User Permisions). Maybe wise to add that to the text (if a dangerous permission is missing in the manifest, TPermissionsRequester.RequestPermissions will deny the permission without even ask for it).
(4) Status bar: it is also wise to set the Sides property of the workaround rectangle to [], especially if the form contains transparent objects like a VertScrollbox. Otherwise you will see the black border of the workaround rectangle shining through.
KInd regards,
Robbert
Hi Robbert,
Thanks for the feedback! I’ve updated the project options to include the Include folder in the search path, modified AndroidManifest.template.xml, and updated the article regarding checking the permissions in the Uses Permissions section. The background rectangle already has its sides set to [].
Can i use my Delphi Berlin to work with API 26?
I tried the demo using Berlin, and the “Take Photo” part had an issue which I’ve now worked around and I have updated this file:
https://github.com/DelphiWorlds/KastriFree/blob/master/Core/DW.MediaLibrary.Android.pas
So it should be all good to go once you update that file
Hi Dave,
Thank you very much for your post, it has been very helpful.
I have followed your instructions and thanks to you I have managed to solve most of the problems. But I have not yet come up with the solution to admob ads notifications. The ads work in the application compiled with the ideo tokyo 10.2.3 but with your method it always returns the error: failed to load ad: 3.
Can you help me?
Thank you so much
It may not be an API 26+ issue. There’s a few things to check:
Do you have AdMob Service checked in the Entitlement List in the project options?
Is your AdMob account configured for interstitial ads, or banner ads? Which ones are you using?
Was your app removed previously due to a privacy policy violation? Check this link: https://stackoverflow.com/a/52972599/3164070
If that all fails, use this form to ask for help: https://support.google.com/admob/?visit_id=636782518356328174-725873167&hl=en&rd=1#topic=7383088
Hi Dave,
Thank you very much for your quick response.
All these checks have already been made.
In fact the ads, banner and interstitials, are shown both in test mode and also real with my application compiled with IDE Tokyo 10.2.3.
However, when I implement your method, both types of ads in real mode return the error: failed to load ad: 3
Thanks for your help,
Best regards.
Hi Dave,
Subject solved, your method works perfectly!!!
The problem was that I generated a new Keystore for the application that did not match the one registered in the ad manager and returned the error.
Sorry for the inconvenience and thank you very much for your invaluable help.
Best regards.
Hello, Dave.
Congratulations on your code, I also use the code to push.
I compiled my app, uploaded it to the Play Store and it was published. In Android phones version 7 and 8 runs normal, but in versions 6 and 5 gives error and closes when open / run.
Is this because of level 26?
Without knowing what the errors are, I don’t know what is causing them. Do you have a link to the app on Google Play? I have a device with Android 5.1.1
Failing that, it would be preferable if you either used the LogCat viewer from my Codex add-in:
http://delphiworlds.com/codex
Or the Monitor app from the Android SDK to view the messages from the device, if possible.
Dave,
I found the error:
When you send the apk to the Play Store, you must have configured the privacy policy, otherwise you can not send the app with the READ_PHONE_STATE permission. I had removed this permission since I thought the code “FRequester.RequestPermissions (cDangerousPermissions, 1);” would enable it. In fact enabled, but only for versions 7 and 8 of Android.
After properly setting up the privacy policy, enabling this permission on the IDE, recompiling the app, and sending it back to the Play Store, it worked.
Again thank you very much for your attention and willingness to help.
Cheers,
Danny.
Hi Dave,
After take photo is there any way to resize the bitmap? When I try this, the app crash and restart.
Is it possible set the resolution for the photo too? Using TParamsPhotoQuery.RequiredResolution I didn´t have success.
Thank you for this post. It was very usefull for me.
“When I try this, the app crash and restart”
What exactly have you tried?
I could modify the code in the DW.MediaLibrary.Android unit to resize the image to what is specified in RequiredResolution, however I am a bit short on time at the moment.
I have the exact same problem. It crashes and restarts.
The MediaLibraryReceivedImageHandler runs fine, the aImage has width/height but the app crashes.
In the adb log I see:
System.err: java.io.IOException: BufferedOutputStream is closed
java.io.BufferedOutputStream.checkNotClosed
Hi Dave.
Thank you for your post.
I’ve tested api26 project sample.
In this sample, requesting permission through the ‘Request SMS Permissions’ Button works fine.
but If I request permission when creating form, ‘PermissionsResultHandler’ function retruned before I click the Okay of permission checking alert button.
After that I click on the permission check button ‘Okay’, no callback ‘PermissionsResultHandler’ function .
example in Deomos – AndroidAPI26)
constructor TForm1.Create(AOwner: TComponent);
begin
inherited;
FRequester := TPermissionsRequester.Create;
FRequester.OnPermissionsResult := PermissionsResultHandler;
FRequester.RequestPermissions([cPermissionSendSMS, cPermissionReceiveSMS, cPermissionReadSMS, cPermissionReceiveMMS, cPermissionReceiveWAPPush], cPermissionsCodeSMS);
end;
procedure TForm1.PermissionsResultHandler(Sender: TObject; const ARequestCode: Integer; const AResults: TPermissionResults);
begin
case ARequestCode of
cPermissionsCodeExternalStorage:
begin
if AResults.AreAllGranted then
FMediaLibrary.TakePhoto
else
ShowMessage(‘You need to grant all required permissions for the app to be able to take photos!’);
end;
cPermissionsCodeSMS:
begin
if AResults.AreAllGranted then
ShowMessage(‘SMS permissions granted’)
else
ShowMessage(‘You need to grant all required permissions for the app to be able to handle SMS!’);
end;
end;
end;
This problem as I have experienced and I have been find a solution. Try not to place FRequester.RequestPermissions on the Form Create or Form Show. I put the FRequester.RequestPermissions on the Timer and it’s works
Thank you!!!
Hi Dave,
i’m using C++ not delphi, will the work around of targeting API level 26 solution also apply for C++?
thanks.
It should work the same.
Hello Dave, good afternoon. I implemented the solution for camera access by actioLits, I use Berlin 10.1. However, when you open the camera and I click to take the picture, instead of filling my IMAGE component, the screen turns black. How do I solve this friend? a big hug.
You cannot use that method with Delphi 10.1 Berlin if you are targeting Android 8 or higher. You need to use the TMediaLibrary alternative that is in the article.
Hi Dave
Interesting one have a 10.3 android app and deploying to samsung phone i get this error and cant install it via APK manually:
java.lang.ClassNotFoundException: com.android.packageinstaller.InstallFlowAnalytics
This appears to be the solution but i cannot find where to set the Java Signing v1 or V2 options in delphi:
https://stackoverflow.com/questions/42292185/cannot-update-the-app-after-updating-sdk-app-not-installed
Delphi is not using Gradle so not much help with that one i can see.
Any idea how to tell delphi to change Java Signing Settings, haven’t found any config file yet.
Ta
Matt
Is there a way to add a separate Launcher Icon (Different image) from the notification icons? Or to add additional notification icons that can be selected by the notification received when the app is in the background.