根据这个:http://developer.android.com/preview/features/runtime-permissions.html#coding一个应用程序可以检查运行时权限和请求权限,如果它还没有被授予。弹出如下对话框:
如果用户拒绝一个重要的权限,在我看来,应用程序应该显示一个解释为什么需要权限和什么影响拒绝。该对话框有两个选项:
重试(再次请求许可)
拒绝(应用程序将工作没有该许可)。
但是,如果用户选中“Never ask again”,则不应该显示带有解释的第二个对话框,特别是如果用户之前已经拒绝了一次。
现在的问题是:我的应用程序如何知道用户是否选中了Never ask again?IMO onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)没有给我这个信息。
第二个问题是:谷歌是否计划在权限对话框中包含一个自定义消息,以解释为什么应用程序需要权限?这样就不会出现第二个对话框,这肯定会带来更好的用户体验。
您可以通过检查权限原理是否显示在onRequestPermissionsResult()回调方法中来确定它。如果您发现任何权限集永远不会再次请求,您可以请求用户从设置中授予权限。
我的完整实现如下所示。它适用于单个或多个权限请求。使用以下或直接使用我的库。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(permissions.length == 0){
return;
}
boolean allPermissionsGranted = true;
if(grantResults.length>0){
for(int grantResult: grantResults){
if(grantResult != PackageManager.PERMISSION_GRANTED){
allPermissionsGranted = false;
break;
}
}
}
if(!allPermissionsGranted){
boolean somePermissionsForeverDenied = false;
for(String permission: permissions){
if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
//denied
Log.e("denied", permission);
}else{
if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
//allowed
Log.e("allowed", permission);
} else{
//set to never ask again
Log.e("set to never ask again", permission);
somePermissionsForeverDenied = true;
}
}
}
if(somePermissionsForeverDenied){
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Permissions Required")
.setMessage("You have forcefully denied some of the required permissions " +
"for this action. Please open settings, go to permissions and allow them.")
.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setCancelable(false)
.create()
.show();
}
} else {
switch (requestCode) {
//act according to the request code used while requesting the permission(s).
}
}
}
请不要为这个解决办法向我扔石头。
这是可行的,但有点“俗气”。
当调用requestPermissions时,注册当前时间。
mAskedPermissionTime = System.currentTimeMillis();
然后在onRequestPermissionsResult中
如果结果不允许,请再次检查时间。
if (System.currentTimeMillis() - mAskedPermissionTime < 100)
由于用户不可能那么快地点击拒绝按钮,我们知道他选择了“永不再问”,因为回调是即时的。
使用风险自负。
您可以通过检查权限原理是否显示在onRequestPermissionsResult()回调方法中来确定它。如果您发现任何权限集永远不会再次请求,您可以请求用户从设置中授予权限。
我的完整实现如下所示。它适用于单个或多个权限请求。使用以下或直接使用我的库。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(permissions.length == 0){
return;
}
boolean allPermissionsGranted = true;
if(grantResults.length>0){
for(int grantResult: grantResults){
if(grantResult != PackageManager.PERMISSION_GRANTED){
allPermissionsGranted = false;
break;
}
}
}
if(!allPermissionsGranted){
boolean somePermissionsForeverDenied = false;
for(String permission: permissions){
if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
//denied
Log.e("denied", permission);
}else{
if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
//allowed
Log.e("allowed", permission);
} else{
//set to never ask again
Log.e("set to never ask again", permission);
somePermissionsForeverDenied = true;
}
}
}
if(somePermissionsForeverDenied){
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Permissions Required")
.setMessage("You have forcefully denied some of the required permissions " +
"for this action. Please open settings, go to permissions and allow them.")
.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setCancelable(false)
.create()
.show();
}
} else {
switch (requestCode) {
//act according to the request code used while requesting the permission(s).
}
}
}
一旦用户标记了“不要再问”,该问题就不能再次显示。
但是可以向用户解释,他之前拒绝了权限,必须在设置中授予权限。并参考他的设置,使用以下代码:
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// now, you have permission go ahead
// TODO: something
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_CALL_LOG)) {
// now, user has denied permission (but not permanently!)
} else {
// now, user has denied permission permanently!
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "You have previously declined this permission.\n" +
"You must approve this permission in \"Permissions\" in the app settings on your device.", Snackbar.LENGTH_LONG).setAction("Settings", new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
}
});
View snackbarView = snackbar.getView();
TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
textView.setMaxLines(5); //Or as much as you need
snackbar.show();
}
}
return;
}
我有点晚了,我也遇到过类似的问题。解决此问题如下
假设您需要位置权限
请求权限启动器
private final ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(
new RequestPermission(),
isGranted -> {
if (isGranted) {
// Permission is granted go ahead
} else {
shouldShowRequestPermissionRationale();
}
});
权限检查
private boolean hasPermissions() {
if (checkSelfPermission(requireActivity(), ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) {
// Permission is granted go ahead
} else {
requestPermissionLauncher.launch(ACCESS_FINE_LOCATION);
}
}
检查是否需要显示权限理性/自定义对话来教育用户
private void shouldShowRequestPermissionRationale() {
if (!shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
// need to show permission rational custom dialog.
}
}