编辑:对不起,我没有在FireMonkey上多做一点家庭作业。这就是我把我的头伸到不属于它的话题上所得到的。我添加此内容是为了使我的答案更值得赏金。
如果你能限制
targetSdk
在22(5.1棒棒糖)的应用程序清单上,用户必须授予安装许可
HasPermission
不应返回false。(不确定FireMonkey是如何工作的)。
如果您想在Marshmallow+中使用动态权限功能,下面是我从中收集的一些信息
this page
:
您需要访问
Activity
回调方法
onRequestPermissionsResult
. 以下是你需要跳过的所有障碍:
-
使用开源工具Dex2Jar转换Android
classes.dex
文件从Delphi返回Java,以便您可以根据
FMXNativeActivity
班
-
编码的子类
FMX本地活动
在Java中,定义了
native
方法(我们称之为
onRequestPermissionsResultNative
并覆盖
onRequestPermissionsResult
方法调用本机方法。
-
跑
javac
-
跑
jar
把。将文件分类为。jar文件
-
跑
dx.bat
转动你的。将jar文件放入Android。dex文件
-
DexMerger
合并您的。dex文件转换到Delphi的类中。dex文件
-
现在只需编写一些复杂的Delphi代码来定义
onRequestPermissionsResultNative
方法并将其注册到JNI环境。哦,别忘了在本地方法中切换到正确的线程。
onActivityResult
. 您必须将这些步骤调整为其他方法。
我甚至没有谈到如何处理操作系统暂停你的应用程序以请求用户许可,然后再恢复。
我用的是Java而不是Delphi,所以你必须在这里进行一些推断。
和你一样,我必须获得IMEI号码,系统对话框会询问用户:“允许应用程序拨打和管理电话?”我需要向用户解释,该应用程序只是获取设备ID,不会拨打或管理电话。所以
-
检查您是否有权限
-
如果您没有权限,请检查是否应显示解释
-
如果不需要显示解释,请启动权限请求操作
shouldShowRequestPermissionRationale
和
requestPermissions
方法是否在
活动
班
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
再一次(对于取消,我将用户发送回上一个屏幕。)
为了得到
请求权限
您需要覆盖的操作
活动
的
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,这样他们就不能一次又一次地获得免费试用了,天哪。应用程序调用
doPermissionsStuff()
.
-
应用程序调用
checkSelfPermission()
并确定权限尚未授予
-
shouldShowRequestPermissionRationale()
. 根据我的经验,
仅在用户拒绝权限一次后返回true。因此,您还没有向用户显示基本原理UI。
-
应用程序调用
requestPermissions()
-
系统将询问用户“允许应用程序拨打和管理电话?”
-
用户认为这太可怕了,按下了“否”按钮。
-
onRequestPermissionsResult()
使用拒绝结果和
mPermissionDenied
设置。
-
onResumeFragments()
调用并向用户显示一个对话框,用户无法获得免费试用版,因为该应用程序没有权限。
-
用户决定重试。
doPermissionsStuff()
被称为。
-
checkSelfPermission()
并且(再次)确定权限尚未授予
-
shouldshowRequestPermissionRegustion()
. 这次它返回true。
-
该应用程序向用户显示了一条平静而舒缓的信息,不,我们不会接管你的手机,我们只想要该死的IMEI号码,仅此而已,如果你不允许该应用程序访问IMEI,你就不会得到免费试用。我必须划清界限
在某处
.
-
用户按continue,因此
标志设置为true,并且
方法再次被调用。
-
应用程序调用
你猜怎么着?权限尚未授予
-
由于设置了标志,用户无法获得基本原理UI。
-
应用程序调用
requestPermissions()
-
系统将询问用户“允许应用程序拨打和管理电话?”
-
用户向命运屈服并按下Yes。
-
onRequestPermissionsResult()
使用授予的结果调用,免费试用注册向前移动。
您还应该在以下网址查看谷歌的示例代码:
https://developer.android.com/samples/RuntimePermissions/index.html