Android 对话框的 M 权限问题 "Don't ask again"
Android M permission issue with Dialog "Don't ask again"
通过 Scoped Directory Access 授予权限是一种更简单的方法,但对话框会显示一个名为 "Don't ask again" 的复选框。如果用户选择“不再询问”并拒绝请求,则您应用程序对给定目录的所有未来请求都将被自动拒绝,并且不会向用户显示任何请求 UI。
如果用户后悔或错误地点击了那个复选框,应用程序如何补救?应用无法获取权限对话框。
我们该如何处理?
我认为您需要做的是使用 shouldShowRequestPermissionRationale(String) 方法,如果用户拒绝权限并检查 "Don't ask again",它会 return false。
你应该做的是向用户显示一个警告,解释为什么你需要权限或实施回退,比如禁用某些功能。
希望对您有所帮助。
我们应该使用 shouldShowRequestPermissionRationale.Please 完成这个:
private void insertDummyContactWrapper() {
int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {
showMessageOKCancel("You need to allow access to Contacts",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS},
REQUEST_CODE_ASK_PERMISSIONS);
}
});
return;
}
requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
insertDummyContact();
}
is any way to change that flag ?
开发人员无法更改该标志。否则,拥有复选框将毫无意义,因为开发人员会通过更改标志来忽略它。
但是,您的问题指出了范围目录访问中的一个相当大的缺陷:用户更改该标志的能力有限。设置中似乎没有专门更改此状态的地方,用户可以手动授予被拒绝的运行时权限的方式。
在 Nexus 5X 运行 7.1 预览版上,"Clear Data" 将重置此标志,尽管这具有更广泛的影响。在 Google Pixel 运行 7.1 和 Nexus 5X 运行 Android 7.0 上,nothing 将重置此标志,即使是完全卸载应用程序。
我已就此事提交 a bug report。我怀疑这种情况在短期内是否会得到很大改善 — 充其量,他们可能会修复它,以便 "Clear Data" 可靠地工作。
public class AccessDenied implements View.OnClickListener{
public Dialog dialog;
private LinearLayout contentLayout;
private Activity context;
private EditText password;
private String passwordStr;
private Runnable doOnAccessPermitted;
private int wrongColor = Color.RED, defColor = Color.parseColor("#80000000");
public AccessDenied(Activity con, String pwd) {
passwordStr = pwd;
context = con;
dialog = new Dialog(context, R.style.AnimatedDialog);
setCancelable(false);
//init the dialog with content view/animations etc.
dialog.setContentView(R.layout.access_denied_layout);
contentLayout = dialog.findViewById(R.id.layoutIconDialogLinearLayout);
password = dialog.findViewById(R.id.accessdeniedlayoutpassword);
Button ok = dialog.findViewById(R.id.accessdeniedlayoutok);
ok.setOnClickListener(this);
//now the dialog is ready
}
public void setActionOnAccess(Runnable doOnAccess) {
doOnAccessPermitted = doOnAccess;
}
public void setCancelable(boolean set) {
dialog.setCancelable(set);
}
public void show() {
dialog.show();
}
public void cancel() {
dialog.cancel();
}
public void setPassword(String pwrd) {
passwordStr = pwrd;
}
public void tryPassword(String tryp) {
if(passwordStr.equals(tryp)){
cancel();
if(doOnAccessPermitted != null)
doOnAccessPermitted.run();
}
}
@Override
public void onClick(View view) {
if(passwordStr.equals(password.getText().toString())) {
cancel();
if(doOnAccessPermitted != null)
doOnAccessPermitted.run();
}else{
password.getText().clear();
Animation anim = AnimationUtils.loadAnimation(context, R.anim.edittext_shake);
anim.setDuration(200);
anim.setRepeatCount(5);
decView().startAnimation(anim);
decView().setBackgroundColor(wrongColor);
new android.os.Handler().postDelayed(new Runnable() {
@Override
public void run() {
decView().setBackgroundColor(defColor);
}
}, 1000);
}
}
private View decView() {
return password;
}
}
打开应用程序的权限设置。
如果用户已勾选,则无法显示另一个权限对话框"Don't ask again."
但是,您可以帮助用户并打开应用程序的设置,用户可以在其中手动启用所需的权限。
为此,您需要启动一个 Intent,类似于:
public void openAppSettings() {
Uri packageUri = Uri.fromParts( "package", getApplicationContext().getPackageName(), null );
Intent applicationDetailsSettingsIntent = new Intent();
applicationDetailsSettingsIntent.setAction( Settings.ACTION_APPLICATION_DETAILS_SETTINGS );
applicationDetailsSettingsIntent.setData( packageUri );
applicationDetailsSettingsIntent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
getApplicationContext().startActivity( applicationDetailsSettingsIntent );
}
现在,要知道用户何时勾选了 "Don't ask again" 复选框是另一回事,可以使用 来完成。
我创建了一种方法,通过使用串联的 if...else if...else 来捕获所有用户操作,它对我来说效果很好。
首先,为了确定是否 两个权限都被拒绝并且不再询问是否也是 'ticked',我结合了权限状态检查和 shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS ).
然后判断是否只有权限被拒绝without 'ticking' 不要再问了,我用权限状态检查。以下片段:
@RequiresApi(api = Build.VERSION_CODES.M) //this is added for API lower than 23
public void myPermissionRationale(){
//This checks both permission status and the Don't ask again check box
if (ContextCompat.checkSelfPermission(this,Manifest.permission.SEND_SMS )
== PackageManager.PERMISSION_DENIED && !shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS)) {
//open app permission settings here for instance
}
//only checks permission status then shows permission request pop up again
else if (ContextCompat.checkSelfPermission(this,Manifest.permission.SEND_SMS )
== PackageManager.PERMISSION_DENIED){
// Request the permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.SEND_SMS},
10);
}
}
我为此找到了一个干净有效的解决方案(但这里没有代码示例,- 阅读并理解它的原因)确保在采取通常要求许可的操作时没有任何场景,不做任何事情.
标志 shouldShowPermission() - 仅此一项,应用程序第一次请求给定权限与“点击不再显示”后没有区别,在这两种情况下它都会 return false。每次都将保持 returning 为真,直到设置了不再询问权限。意思是第二次开始我们请求无限权限或直到用户点击不再询问。
因此,为了区分首次请求权限和请求权限的时间,在用户已经设置“不再询问”后,您可以使用自定义标志。
这是一个干净而简单的解决方法,它将确定是否设置了不再询问选项。 (经过测试并在 2 个制作应用程序中工作)
解决方案:
添加一个名为“rationaleDisplayed”的标志(或任何您想要的,这将指示向用户显示 permissionRationeDialog)- 默认值为 false,将其存储在 prefs 中。至少向用户展示一次基本原理对话框后,将此标志设置为真。
现在你有两个参数,当 shouldShowRationaleDialog = false 和 rationalePermissionDisplayed = true 时,它们的组合有效地设置了“不再显示”的指示。
为什么这有效?
它之所以有效,是因为 shouldShowRationale, will return false 当第一次请求许可时并且 rationaleDisplayedFlag 都是 false,所以弹出窗口会正确显示。 (2 false) - 这是第一次请求权限的情况。
然后,如果您第一次拒绝,sshouldShowRationale 将为 true,rationaleDisplayed 将为 true - (2 trues),直到使用 dont set again 选项之前都是如此。 - 这是在第一次请求被拒绝后第二次请求许可的情况。
最后,如果您设置不再询问 - 或 Android api 30 并拒绝许可 2 次,下次调用 shouldShowRationale 标志时将 return 为 false。
这里有一个 shouldShowRationale = false 的情况,并且您自己的标志 rationaleDisplayed = true,它告诉您已设置不再询问。 (否则,shouldShowRationale 仍然是错误的)。 - 当用户拒绝权限两次 (api 30) 或在拒绝时设置“不再显示”选项时就是这种情况。
有了这个逻辑案例,您现在可以添加一个自定义权限对话框,其中包含有关如何手动启用权限的说明,并使用确定按钮打开应用程序设置。 (意图在对话积极听众中打开设置)。
基本原理 rationaleDisplayed 标志基本上是为了确保应用第一次请求权限时它会正确显示,但它的值允许确定用户设置为不再询问时的状态。
很有魅力。
通过 Scoped Directory Access 授予权限是一种更简单的方法,但对话框会显示一个名为 "Don't ask again" 的复选框。如果用户选择“不再询问”并拒绝请求,则您应用程序对给定目录的所有未来请求都将被自动拒绝,并且不会向用户显示任何请求 UI。 如果用户后悔或错误地点击了那个复选框,应用程序如何补救?应用无法获取权限对话框。
我们该如何处理?
我认为您需要做的是使用 shouldShowRequestPermissionRationale(String) 方法,如果用户拒绝权限并检查 "Don't ask again",它会 return false。
你应该做的是向用户显示一个警告,解释为什么你需要权限或实施回退,比如禁用某些功能。
希望对您有所帮助。
我们应该使用 shouldShowRequestPermissionRationale.Please 完成这个:
private void insertDummyContactWrapper() {
int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {
showMessageOKCancel("You need to allow access to Contacts",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS},
REQUEST_CODE_ASK_PERMISSIONS);
}
});
return;
}
requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
insertDummyContact();
}
is any way to change that flag ?
开发人员无法更改该标志。否则,拥有复选框将毫无意义,因为开发人员会通过更改标志来忽略它。
但是,您的问题指出了范围目录访问中的一个相当大的缺陷:用户更改该标志的能力有限。设置中似乎没有专门更改此状态的地方,用户可以手动授予被拒绝的运行时权限的方式。
在 Nexus 5X 运行 7.1 预览版上,"Clear Data" 将重置此标志,尽管这具有更广泛的影响。在 Google Pixel 运行 7.1 和 Nexus 5X 运行 Android 7.0 上,nothing 将重置此标志,即使是完全卸载应用程序。
我已就此事提交 a bug report。我怀疑这种情况在短期内是否会得到很大改善 — 充其量,他们可能会修复它,以便 "Clear Data" 可靠地工作。
public class AccessDenied implements View.OnClickListener{
public Dialog dialog;
private LinearLayout contentLayout;
private Activity context;
private EditText password;
private String passwordStr;
private Runnable doOnAccessPermitted;
private int wrongColor = Color.RED, defColor = Color.parseColor("#80000000");
public AccessDenied(Activity con, String pwd) {
passwordStr = pwd;
context = con;
dialog = new Dialog(context, R.style.AnimatedDialog);
setCancelable(false);
//init the dialog with content view/animations etc.
dialog.setContentView(R.layout.access_denied_layout);
contentLayout = dialog.findViewById(R.id.layoutIconDialogLinearLayout);
password = dialog.findViewById(R.id.accessdeniedlayoutpassword);
Button ok = dialog.findViewById(R.id.accessdeniedlayoutok);
ok.setOnClickListener(this);
//now the dialog is ready
}
public void setActionOnAccess(Runnable doOnAccess) {
doOnAccessPermitted = doOnAccess;
}
public void setCancelable(boolean set) {
dialog.setCancelable(set);
}
public void show() {
dialog.show();
}
public void cancel() {
dialog.cancel();
}
public void setPassword(String pwrd) {
passwordStr = pwrd;
}
public void tryPassword(String tryp) {
if(passwordStr.equals(tryp)){
cancel();
if(doOnAccessPermitted != null)
doOnAccessPermitted.run();
}
}
@Override
public void onClick(View view) {
if(passwordStr.equals(password.getText().toString())) {
cancel();
if(doOnAccessPermitted != null)
doOnAccessPermitted.run();
}else{
password.getText().clear();
Animation anim = AnimationUtils.loadAnimation(context, R.anim.edittext_shake);
anim.setDuration(200);
anim.setRepeatCount(5);
decView().startAnimation(anim);
decView().setBackgroundColor(wrongColor);
new android.os.Handler().postDelayed(new Runnable() {
@Override
public void run() {
decView().setBackgroundColor(defColor);
}
}, 1000);
}
}
private View decView() {
return password;
}
}
打开应用程序的权限设置。
如果用户已勾选,则无法显示另一个权限对话框"Don't ask again."
但是,您可以帮助用户并打开应用程序的设置,用户可以在其中手动启用所需的权限。
为此,您需要启动一个 Intent,类似于:
public void openAppSettings() {
Uri packageUri = Uri.fromParts( "package", getApplicationContext().getPackageName(), null );
Intent applicationDetailsSettingsIntent = new Intent();
applicationDetailsSettingsIntent.setAction( Settings.ACTION_APPLICATION_DETAILS_SETTINGS );
applicationDetailsSettingsIntent.setData( packageUri );
applicationDetailsSettingsIntent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
getApplicationContext().startActivity( applicationDetailsSettingsIntent );
}
现在,要知道用户何时勾选了 "Don't ask again" 复选框是另一回事,可以使用
我创建了一种方法,通过使用串联的 if...else if...else 来捕获所有用户操作,它对我来说效果很好。
首先,为了确定是否 两个权限都被拒绝并且不再询问是否也是 'ticked',我结合了权限状态检查和 shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS ).
然后判断是否只有权限被拒绝without 'ticking' 不要再问了,我用权限状态检查。以下片段:
@RequiresApi(api = Build.VERSION_CODES.M) //this is added for API lower than 23
public void myPermissionRationale(){
//This checks both permission status and the Don't ask again check box
if (ContextCompat.checkSelfPermission(this,Manifest.permission.SEND_SMS )
== PackageManager.PERMISSION_DENIED && !shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS)) {
//open app permission settings here for instance
}
//only checks permission status then shows permission request pop up again
else if (ContextCompat.checkSelfPermission(this,Manifest.permission.SEND_SMS )
== PackageManager.PERMISSION_DENIED){
// Request the permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.SEND_SMS},
10);
}
}
我为此找到了一个干净有效的解决方案(但这里没有代码示例,- 阅读并理解它的原因)确保在采取通常要求许可的操作时没有任何场景,不做任何事情.
标志 shouldShowPermission() - 仅此一项,应用程序第一次请求给定权限与“点击不再显示”后没有区别,在这两种情况下它都会 return false。每次都将保持 returning 为真,直到设置了不再询问权限。意思是第二次开始我们请求无限权限或直到用户点击不再询问。
因此,为了区分首次请求权限和请求权限的时间,在用户已经设置“不再询问”后,您可以使用自定义标志。
这是一个干净而简单的解决方法,它将确定是否设置了不再询问选项。 (经过测试并在 2 个制作应用程序中工作)
解决方案:
添加一个名为“rationaleDisplayed”的标志(或任何您想要的,这将指示向用户显示 permissionRationeDialog)- 默认值为 false,将其存储在 prefs 中。至少向用户展示一次基本原理对话框后,将此标志设置为真。
现在你有两个参数,当 shouldShowRationaleDialog = false 和 rationalePermissionDisplayed = true 时,它们的组合有效地设置了“不再显示”的指示。
为什么这有效? 它之所以有效,是因为 shouldShowRationale, will return false 当第一次请求许可时并且 rationaleDisplayedFlag 都是 false,所以弹出窗口会正确显示。 (2 false) - 这是第一次请求权限的情况。
然后,如果您第一次拒绝,sshouldShowRationale 将为 true,rationaleDisplayed 将为 true - (2 trues),直到使用 dont set again 选项之前都是如此。 - 这是在第一次请求被拒绝后第二次请求许可的情况。
最后,如果您设置不再询问 - 或 Android api 30 并拒绝许可 2 次,下次调用 shouldShowRationale 标志时将 return 为 false。
这里有一个 shouldShowRationale = false 的情况,并且您自己的标志 rationaleDisplayed = true,它告诉您已设置不再询问。 (否则,shouldShowRationale 仍然是错误的)。 - 当用户拒绝权限两次 (api 30) 或在拒绝时设置“不再显示”选项时就是这种情况。
有了这个逻辑案例,您现在可以添加一个自定义权限对话框,其中包含有关如何手动启用权限的说明,并使用确定按钮打开应用程序设置。 (意图在对话积极听众中打开设置)。
基本原理 rationaleDisplayed 标志基本上是为了确保应用第一次请求权限时它会正确显示,但它的值允许确定用户设置为不再询问时的状态。
很有魅力。