Firemonkey android read_phone_state运行时权限要求获取IMEI



如何在运行时获得read_phone_state权限以获取IMEI号码?

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:对不起,我没有在FireMonkey上多做一点功课。这就是我对不属于我的话题的执着。我添加这些内容是为了让我的答案更值得奖励。

如果您可以将应用程序清单上的targetSdk限制为22(5.1棒棒糖),则用户必须授予安装权限,因此HasPermission永远不应返回false。(不确定FireMonkey是如何工作的)。

如果你想在Marshmallow+中使用动态权限功能,下面是我从这个页面收集到的一些信息:

您需要有权访问Activity回调方法onRequestPermissionsResult。以下是你必须克服的所有困难:

  • 使用开源工具Dex2Jar将Androidclasses.dex文件从Delphi转换回Java,这样您就可以根据FMXNativeActivity类进行编译
  • 在Java中编写FMXNativeActivity的子类,定义native方法(让我们称之为onRequestPermissionsResultNative,并覆盖onRequestPermissionsResult方法以调用本机方法)
  • 运行javac获取一个带有子类的.class文件
  • 运行jar将.class文件放入.jar文件中
  • 运行dx.bat将.jar文件转换为Android.dex文件
  • 运行DexMerger将.dex文件合并到Delphi的classes.dex文件中
  • 现在所要做的就是编写一些棘手的Delphi代码来定义onRequestPermissionsResultNative方法,并将其注册到JNI环境中。哦,别忘了在本机方法中切换到正确的线程

我引用的链接显示了如何使用onActivityResult执行此操作。您将不得不根据其他方法调整这些步骤。

我甚至还没有谈到如何处理操作系统暂停你的应用程序以请求用户许可,然后再恢复。

让这成为所有人的一个教训:不要相信跨平台工具;你会失望的。


我在Java而不是Delphi中工作,所以你必须在这里进行一点推断。

和你一样,我必须获取IMEI号码,系统对话框会询问用户:"允许应用程序拨打和管理电话?"我需要向用户解释,该应用程序只是获取设备ID,不会拨打或管理电话。所以

  • 检查您是否有权限
  • 如果您没有权限,请检查是否应该显示解释
  • 如果不需要显示说明,请启动权限请求操作

我应该提到shouldShowRequestPermissionRationalerequestPermissionsActivity类上的方法。

private static final int READ_PHONE_STATE_PERMISSIONS_REQUEST = 2;
private boolean mHasReadRationale;
void doPermissionsStuff() {
// version checking code omitted, this block runs for marshmallow and later
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
// do the operation that needs the permission here
} else {
// the flag indicates if the rationale dialog has already been displayed
if (! mHasReadRationale && shouldShowRequestPermissionRationale(Manifest.permission.READ_PHONE_STATE)) {
// pop a dialog that explains what's going on to the user
} else {
requestPermissions(new String[] {Manifest.permission.READ_PHONE_STATE}, READ_PHONE_STATE_PERMISSIONS_REQUEST);
}
}
}

在该对话框的肯定按钮中(即用户希望继续),将mHasReadRationale标志设置为true,然后再次调用doPermissionsStuff。(对于"取消",我将用户发送回上一个屏幕。)

为了获得requestPermissions操作的结果,您需要覆盖ActivityonRequestPermissionsResult方法:

private boolean mPermissionDenied;
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case READ_PHONE_STATE_PERMISSIONS_REQUEST:
// I'm only checking for one permission, so I make assumptions here
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// you can do the operation that needs the permission now
} else {
mPermissionDenied = true;  // set a flag for checking later
}
}
}

显然,当系统向用户请求权限时,它会停止你的应用程序,所以你不能在此时显示UI来告诉用户你没有权限。所以我设置了一个标志,当应用程序恢复时,然后我告诉用户该应用程序没有执行操作的权限。

@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (mPermissionDenied) {
// show dialog to the user that the app can't do the operation because it doesn't have permission
mPermissionDenied = false;
}
}

下面是一个流程示例:

  • 用户想要免费试用&应用程序需要获得IMEI,这样他们就不能一次又一次地获得免费试用,天哪。应用程序调用doPermissionsStuff()
  • 应用程序调用checkSelfPermission()并确定权限尚未授予
  • 应用程序调用shouldShowRequestPermissionRationale()。根据我的经验,shouldShowRequestPermissionRationale()只有在用户拒绝了一次权限后才会返回true。因此,您还没有向用户显示基本原理UI
  • 应用程序调用requestPermissions()
  • 系统会询问用户"是否允许应用程序拨打和管理电话?">
  • 用户认为这是WAAAAAAY太可怕,并按下"否"按钮
  • 用拒绝结果调用onRequestPermissionsResult(),并且设置mPermissionDenied
  • 调用onResumeFragments()并向用户显示一个对话框,说明他们无法获得免费试用,因为该应用程序没有权限
  • 用户决定重试。调用CCD_ 33
  • 应用程序调用checkSelfPermission()并(再次)确定权限尚未授予
  • 应用程序调用shouldShowRequestPermissionRationale()。这一次它变成了真的
  • 应用程序会向用户显示一条平静而舒缓的信息,不,我们不会接管你的手机,我们只想要这个奇怪的IMEI号码,仅此而已,如果你不允许应用程序访问IMEI,你就无法获得免费试用。我必须在某个地方画一条线
  • 用户按continue,则mHasReadRationale标志设置为true,并再次调用doPermissionsStuff()方法
  • 应用程序调用checkSelfPermission()和—你猜怎么着?许可尚未授予
  • 由于设置了该标志,用户无法获得基本原理UI
  • 应用程序调用requestPermissions()
  • 系统会询问用户"是否允许应用程序拨打和管理电话?">
  • 用户听天由命,按下Yes
  • CCD_ 40被调用,并且免费试用注册向前移动

您还应该在https://developer.android.com/samples/RuntimePermissions/index.html

最新更新