编辑:对不起,我没有在FireMonkey上做更多的功课.这就是我坚持不懈的主题.我添加了这些内容,试图让我的答案更值得赏心悦目.
如果您可以将应用清单上的targetSdk限制为22(5.1 Lollipop),那么用户必须在安装时授予权限,因此HasPermission永远不会返回false. (不确定FireMonkey的工作原理).
如果您想使用Marshmallow中的动态权限功能,以下是我从this page收集的一些信息:
您需要有权访问Activity回调方法onRequestPermissionsResult.以下是您必须跳过的所有箍:
>使用开源工具Dex2Jar将Delphi中的Android classes.dex文件转换回Java,这样就可以针对FMXNativeActivity类进行编译.
>在Java中编写FMXNativeActivity的子类,定义本机方法(让我们将其命名为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而不打算制作或管理电话.所以
>检查您是否拥有该权限
>如果您没有权限,请检查是否应显示说明
>如果您不需要显示说明,请启动权限请求操作
我应该提一下,shouldShowRequestPermissionRationale和requestPermissions是Activity类的方法.
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操作的结果,您需要覆盖Activity的onRequestPermissionsResult方法:
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,因此他们无法一遍又一遍地获得免费试用,jeez.应用程序调用doPermissionsStuff().
>应用程序调用checkSelfPermission()并确定尚未授予权限
>应用程序调用shouldShowRequestPermissionRationale().根据我的经验,shouldShowRequestPermissionRationale()仅在用户拒绝一次权限后才返回true.因此,您尚未向用户显示基本原理UI.
>应用程序调用requestPermissions()
>系统会询问用户“允许应用程序拨打和管理电话?”
>用户认为这是WAAAAAAY太吓人了,按下否按钮.
>使用deny结果调用onRequestPermissionsResult()并设置mPermissionDenied.
> onResumeFragments()被调用,并向用户显示一个对话框,他们无法获得免费试用,因为该应用程序没有权限.
>用户决定再试一次.调用doPermissionsStuff().
>应用程序调用checkSelfPermission()和(再次)确定尚未授予权限
>应用程序调用shouldShowRequestPermissionRationale().这次它返回true.
>应用程序向用户显示一个平静和舒缓的消息,不,我们不会接管您的手机,我们只想要一个非常好的IMEI号码,就是这样,如果您不允许该应用访问IMEI ,你没有得到免费试用.我必须在某处画线.
>用户按下继续,因此mHasReadRationale标志设置为true,并再次调用doPermissionsStuff()方法.
>应用程序调用checkSelfPermission()和 – 猜猜是什么?许可尚未授予
>由于设置了标志,因此用户无法获得基本原理UI.
>应用程序调用requestPermissions()
>系统会询问用户“允许应用程序拨打和管理电话?”
>用户将自己重新命名为命运,然后按是.
> onRequestPermissionsResult()使用授予的结果调用,免费试用注册向前移动.