如何在运行时获取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;
答案 0 :(得分:3)
如果您可以将应用清单上的targetSdk
限制为22(5.1 Lollipop),则用户必须在安装时授予权限,以便HasPermission
永远不会返回false。 (不确定FireMonkey是如何工作的。)
如果您想使用Marshmallow +中的动态权限功能,以下是我从this page收集的一些信息:
您需要有权访问Activity
回调方法onRequestPermissionsResult
。以下是您必须跳过的所有箍:
classes.dex
文件转换回Java,以便您可以针对FMXNativeActivity
类进行编译。FMXNativeActivity
的子类,用于定义native
方法(让我们称之为onRequestPermissionsResultNative
,并覆盖onRequestPermissionsResult
方法以调用原生方法。javac
以获取包含子类的.class文件jar
将.class文件放入.jar文件dx.bat
将您的.jar文件转换为Android .dex文件DexMerger
将您的.dex文件合并到Delphi的classes.dex文件中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
的{{1}}方法:
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
}
}
}
以下是一个示例流程:
@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;
}
}
仅在用户拒绝一次权限后才返回true。因此,您还没有向用户显示基本用户界面。doPermissionsStuff()
并设置checkSelfPermission()
。shouldShowRequestPermissionRationale()
被调用,并向用户显示一个对话框,表明他们无法获得免费试用,因为该应用没有获得许可。shouldShowRequestPermissionRationale()
被称为。{/ li>
requestPermissions()
标志设置为true,并再次调用onRequestPermissionsResult()
方法。mPermissionDenied
,免费试用注册将继续进行。您还应该在https://developer.android.com/samples/RuntimePermissions/index.html
查看Google的示例代码