How can I get read_phone_state permission at runtime to get IMEI number?
if not HasPermission('android.permission.READ_PHONE_STATE') then
begin
//ASK AND GET PERMISSION ?
end;
function TForm1.HasPermission(const Permission: string): Boolean;
begin
//Permissions listed at http://d.android.com/reference/android/Manifest.permission.html
{$IF RTLVersion >= 30}
Result := TAndroidHelper.Context.checkCallingOrSelfPermission(
{$ELSE}
Result := SharedActivityContext.checkCallingOrSelfPermission(
{$ENDIF}
StringToJString(Permission)) =
TJPackageManager.JavaClass.PERMISSION_GRANTED;
end;
EDIT: Sorry I didn't do a little more homework on FireMonkey. This is what I get for sticking my head into topics where it doesn't belong. I've added this content to try to make my answer more deserving of the bounty.
If you can restrict the
targetSdk
on the app manifest to 22 (5.1 Lollipop) then the user will have to grant the permission on install soHasPermission
should never return false. (Not sure how that works with FireMonkey).If you want to use the dynamic permissions capabilities in Marshmallow+, here is some information that I gleaned from this page:
You need to have access to the
Activity
callback methodonRequestPermissionsResult
. Here's all the hoops you will have to jump through:classes.dex
file from Delphi back to Java so you can compile against theFMXNativeActivity
class.FMXNativeActivity
in Java that defines anative
method (let's call itonRequestPermissionsResultNative
and also overrides theonRequestPermissionsResult
method to call through to the native method.javac
to get a .class file with your subclassjar
to put the .class file into a .jar filedx.bat
to turn your .jar file into an Android .dex fileDexMerger
to merge your .dex file into Delphi's classes.dex fileonRequestPermissionsResultNative
method and register it with the JNI Environment. Oh, and don't forget to switch to the correct thread in your native method.The link I referenced shows how to do this with
onActivityResult
. You'll have to adapt these steps for the other method.And I haven't even talked about how to handle the OS pausing your app to ask the user for permission and resuming it after.
Let this be a lesson to all: Don't put your faith in cross-platform tools; you will be disappointed.
I work in Java not Delphi, so you'll have to extrapolate a little bit here.
Like you, I have to get the IMEI number, and the system dialog asks the user something like: "Allow app to make and manage phone calls?" I need to explain to the user that that app is just getting the device ID and isn't going to make or manage phone calls. So
I should mention that
shouldShowRequestPermissionRationale
andrequestPermissions
are methods on theActivity
class.In the positive button of this dialog (i.e. user wants to continue) set the
mHasReadRationale
flag to true and calldoPermissionsStuff
again. (For Cancel, I send the user back to the previous screen.)In order to get the result of the
requestPermissions
operation you need to override theActivity
'sonRequestPermissionsResult
method:Apparently when the system asks the user for the permission, it stops your app, so you can't show a UI at that point to tell the user you don't have permission. So I set a flag and when the app resumes, then I tell the user that the app doesn't have permission to do the operation.
So here's an example flow:
doPermissionsStuff()
.checkSelfPermission()
and determines the permission isn't granted yetshouldShowRequestPermissionRationale()
. In my experience,shouldShowRequestPermissionRationale()
only returns true after the user has denied the permission once. So you don't display the rationale UI to the user yet.requestPermissions()
onRequestPermissionsResult()
is called with the deny result and themPermissionDenied
gets set.onResumeFragments()
gets called and a dialog is displayed to the user that they can't get the free trial because the app doesn't have permission.doPermissionsStuff()
is called.checkSelfPermission()
and (again) determines the permission isn't granted yetshouldShowRequestPermissionRationale()
. This time it returns true.mHasReadRationale
flag is set to true anddoPermissionsStuff()
method gets called again.checkSelfPermission()
and — guess what? the permission isn't granted yetrequestPermissions()
onRequestPermissionsResult()
is called with the granted result and the free trial registration moves forward.You should also check out Google's sample code at https://developer.android.com/samples/RuntimePermissions/index.html