当用户在运行时权限对话框中单击拒绝时显示 DialogFragment
Show DialogFragment when user clicks deny on Runtime permissions dialog
我试图在用户点击 android 的 "allow/deny permission" 对话框中的 "Deny" 后立即显示一个 DialogFragment 6 但是我收到了这个错误:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1448)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1466)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613)
at android.support.v4.app.DialogFragment.show(DialogFragment.java:139)
at android.support.v4.app.FragmentActivity.onRequestPermissionsResult(FragmentActivity.java:802)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553)
at android.app.Activity.dispatchActivityResult(Activity.java:6432)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
我的对话框代码很标准
protected void showDialog(DialogFragment diag)
{
if (diag != null && !diag.isAdded())
diag.show(getSupportFragmentManager(), "dialog");
}
如何解决这个问题?
因此,有几个解决方案,none 特别漂亮。这意味着您的 Activity 的 FragmentManager 尚未处于以安全方式提交 FragmentTransactions 的有效状态(尽管在这种特殊情况下,它应该始终是。)
1) 使用.commitAllowingStateLoss()
代替.show()
:
这是最简单的修复方法,尽管我不完全清楚不使用 .show()
方法会产生什么差异,这些方法在内部设置了一些标志。似乎工作正常。
getSupportFragmentManager()
.beginTransaction()
.add(diag, "dialog")
.commitAllowingStateLoss();
1) Post .show()
作为 Runnable
on a Handler
:
// Initialize a Handler ahead of time and keep it around
private Handler mHandler = new Handler();
...
// after getting denied:
mHandler.post(new Runnable() {
@Override
public void run() {
// Show your dialog
}
}
...
@Override
protected void onStop() {
super.onStop();
// Clear out the Runnable for an unlikely edge case where your
// Activity goes to stopped state before the Runnable executes
mHandler.removeCallbacksAndMessages(null);
}
2) 设置标志并在 onResume() 中显示对话框
private boolean mPermissionDenied;
@Override
public void onRequestPermissionsResult(...) {
// If denied...
mPermissionDenied = true;
}
@Override
protected void onResume() {
super.onResume();
if (mPermissionDenied) {
mPermissionDenied = false;
// Show your dialog
}
}
我还想补充一些我刚刚发现的东西。如果我用 getSupportFragmentManager().beginTransaction()
在我现有的代码上切换 getSupportFragmentManager()
它工作正常。下面的代码
protected void showDialog(final DialogFragment diag)
{
cancelDialog();
if (diag != null && !diag.isAdded())
diag.show(getSupportFragmentManager().beginTransaction(), "dialog");
}
不知道为什么这会像我想要的那样工作。
在用户点击拒绝后显示一个对话框并不是指南所说的。您应该仅在第二次请求之前显示许可 rational。您可以在这里查看自动管理:Permission library
我试图在用户点击 android 的 "allow/deny permission" 对话框中的 "Deny" 后立即显示一个 DialogFragment 6 但是我收到了这个错误:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1448)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1466)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613)
at android.support.v4.app.DialogFragment.show(DialogFragment.java:139)
at android.support.v4.app.FragmentActivity.onRequestPermissionsResult(FragmentActivity.java:802)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553)
at android.app.Activity.dispatchActivityResult(Activity.java:6432)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
我的对话框代码很标准
protected void showDialog(DialogFragment diag)
{
if (diag != null && !diag.isAdded())
diag.show(getSupportFragmentManager(), "dialog");
}
如何解决这个问题?
因此,有几个解决方案,none 特别漂亮。这意味着您的 Activity 的 FragmentManager 尚未处于以安全方式提交 FragmentTransactions 的有效状态(尽管在这种特殊情况下,它应该始终是。)
1) 使用.commitAllowingStateLoss()
代替.show()
:
这是最简单的修复方法,尽管我不完全清楚不使用 .show()
方法会产生什么差异,这些方法在内部设置了一些标志。似乎工作正常。
getSupportFragmentManager()
.beginTransaction()
.add(diag, "dialog")
.commitAllowingStateLoss();
1) Post .show()
作为 Runnable
on a Handler
:
// Initialize a Handler ahead of time and keep it around
private Handler mHandler = new Handler();
...
// after getting denied:
mHandler.post(new Runnable() {
@Override
public void run() {
// Show your dialog
}
}
...
@Override
protected void onStop() {
super.onStop();
// Clear out the Runnable for an unlikely edge case where your
// Activity goes to stopped state before the Runnable executes
mHandler.removeCallbacksAndMessages(null);
}
2) 设置标志并在 onResume() 中显示对话框
private boolean mPermissionDenied;
@Override
public void onRequestPermissionsResult(...) {
// If denied...
mPermissionDenied = true;
}
@Override
protected void onResume() {
super.onResume();
if (mPermissionDenied) {
mPermissionDenied = false;
// Show your dialog
}
}
我还想补充一些我刚刚发现的东西。如果我用 getSupportFragmentManager().beginTransaction()
在我现有的代码上切换 getSupportFragmentManager()
它工作正常。下面的代码
protected void showDialog(final DialogFragment diag)
{
cancelDialog();
if (diag != null && !diag.isAdded())
diag.show(getSupportFragmentManager().beginTransaction(), "dialog");
}
不知道为什么这会像我想要的那样工作。
在用户点击拒绝后显示一个对话框并不是指南所说的。您应该仅在第二次请求之前显示许可 rational。您可以在这里查看自动管理:Permission library