我知道我发布得很晚,但详细的示例可能对某些人有用。
我注意到的是,如果在onRequestPermissionsResult()回调方法中检查shouldShowRequestPermissionRationale()标志,它只显示两个状态:
状态1:返回true:任何时候用户点击Deny权限(包括第一次)。
状态2:返回false:如果用户选择“不再询问”。
这是一个多个权限请求的示例:
应用程序在启动时需要2个权限。SEND_SMS和ACCESS_FINE_LOCATION(均在manifest.xml中列出)。
应用程序一启动就会一起要求多个权限。如果两个权限都被授予,则正常流程继续。
![输入图像描述](https://istack.dev59.com/TmOCS.webp)
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(checkAndRequestPermissions()) {
}
}
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS);
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (locationPermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
如果一个或多个权限未被授予,activityCompat.requestPermissions()将请求权限,并且控制流程转到onRequestPermissionsResult()回调方法。
在onRequestPermissionsResult()回调方法中,您应该检查shouldShowRequestPermissionRationale()标志的值。
只有两种情况:
情况1:每当用户拒绝权限(包括第一次),它将返回true。因此,当用户拒绝时,我们可以显示更多解释并继续请求。
情况2:只有当用户选择“不再询问”时,它才会返回false。在这种情况下,我们可以继续使用有限功能并引导用户从设置中激活权限以获得更多功能,或者如果权限对于应用程序来说是微不足道的,则可以完成设置。
情况1
![Case - 1](https://istack.dev59.com/nbTo6.webp)
情况2
![Case - 2](https://istack.dev59.com/rQqYp.webp)
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
perms.put(Manifest.permission.SEND_SMS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
if (perms.get(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "sms & location services permission granted");
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
showDialogOK("SMS and Location Services Permission required for this app",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
}
});
}
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
SharedPreferences
可能与Android自身存储的权限信息不同步。在运行时权限方面,Android是“记录系统”。它显然拥有这些信息,否则它将无法从shouldShowRequestPermissionRationale()
返回true
。我只是想看看是否有一些我错过的方法被添加了。 - CommonsWareshouldShowRequestPermissionRationale()
并添加一个返回int
值的新方法。 - Kevin Krumwiede