方向更改后的重复权限请求
Duplicate permission request after orientation change
因为 Android SDK 23 允许用户拒绝应用程序访问某些功能,所以我想更新我的一个应用程序以请求权限,如下所述:https://developer.android.com/preview/features/runtime-permissions.html。
在其中一项活动中,我嵌入了 SupportMapFragment。要使其工作,您需要拥有 WRITE_EXTERNAL_STORAGE
权限,因此我在启动 activity 时请求它,这会导致创建权限请求对话框。
现在的问题是,当对话框仍然打开并且我旋转设备时,activity 将重新启动并打开一个新的权限请求对话框,而旧的对话框仍然存在。结果是其中两个对话框彼此重叠,只有一个有用。
有没有办法摆脱最先启动的对话框?
我想这是一个系统对话框,您无法控制它。您可以改为防止您的 activity 在您转动设备时重新加载。
正如 CommonsWare 在他的 中所说,最好的解决方案是将一个布尔值放入 savedInstanceState-Bundle 以了解对话框是否仍然打开。
示例:
// true if dialog already open
private boolean alreadyAskedForStoragePermission = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
alreadyAskedForStoragePermission = savedInstanceState.getBoolean(STORAGE_PERMISSION_DIALOG_OPEN_KEY, false);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY, alreadyAskedForStoragePermission);
}
private void checkStoragePermission(){
if(alreadyAskedForStoragePermission){
// don't check again because the dialog is still open
return;
}
if(ActivityCompat.checkSelfPermission(this, STORAGE_PERMISSIONS[0]) != PackageManager.PERMISSION_GRANTED){
// the dialog will be opened so we have to keep that in memory
alreadyAskedForStoragePermission = true;
ActivityCompat.requestPermissions(this, STORAGE_PERMISSIONS, STORAGE_PERMISSION_REQUEST_CODE);
} else {
onStoragePermissionGranted();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case STORAGE_PERMISSION_REQUEST_CODE:
// the request returned a result so the dialog is closed
alreadyAskedForStoragePermission = false;
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
onStoragePermissionGranted();
}
break;
}
}
正如@user1991776 所提到的,实际上有一个未记录的额外内容,其中包含当前是否打开了一个权限对话框,in Activity:
private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY =
"android:hasCurrentPermissionsRequest";
不过还有更好的办法。当您第二次请求权限对话框时(由于旋转),Activity
通过调用您的 onRequestPermissionResult()
with empty arrays:
自动取消旧对话框
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can reqeust only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
或者当然是这种行为 isn't documented 因为这是 Android,谁想要记录复杂的行为?
无论如何,您始终可以在 onCreate()
中请求权限,然后忽略对具有零长度 permissions
数组的 onRequestPermissionsResult()
的调用。
因为 Android SDK 23 允许用户拒绝应用程序访问某些功能,所以我想更新我的一个应用程序以请求权限,如下所述:https://developer.android.com/preview/features/runtime-permissions.html。
在其中一项活动中,我嵌入了 SupportMapFragment。要使其工作,您需要拥有 WRITE_EXTERNAL_STORAGE
权限,因此我在启动 activity 时请求它,这会导致创建权限请求对话框。
现在的问题是,当对话框仍然打开并且我旋转设备时,activity 将重新启动并打开一个新的权限请求对话框,而旧的对话框仍然存在。结果是其中两个对话框彼此重叠,只有一个有用。
有没有办法摆脱最先启动的对话框?
我想这是一个系统对话框,您无法控制它。您可以改为防止您的 activity 在您转动设备时重新加载。
正如 CommonsWare 在他的
示例:
// true if dialog already open
private boolean alreadyAskedForStoragePermission = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
alreadyAskedForStoragePermission = savedInstanceState.getBoolean(STORAGE_PERMISSION_DIALOG_OPEN_KEY, false);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY, alreadyAskedForStoragePermission);
}
private void checkStoragePermission(){
if(alreadyAskedForStoragePermission){
// don't check again because the dialog is still open
return;
}
if(ActivityCompat.checkSelfPermission(this, STORAGE_PERMISSIONS[0]) != PackageManager.PERMISSION_GRANTED){
// the dialog will be opened so we have to keep that in memory
alreadyAskedForStoragePermission = true;
ActivityCompat.requestPermissions(this, STORAGE_PERMISSIONS, STORAGE_PERMISSION_REQUEST_CODE);
} else {
onStoragePermissionGranted();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case STORAGE_PERMISSION_REQUEST_CODE:
// the request returned a result so the dialog is closed
alreadyAskedForStoragePermission = false;
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
onStoragePermissionGranted();
}
break;
}
}
正如@user1991776 所提到的,实际上有一个未记录的额外内容,其中包含当前是否打开了一个权限对话框,in Activity:
private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY =
"android:hasCurrentPermissionsRequest";
不过还有更好的办法。当您第二次请求权限对话框时(由于旋转),Activity
通过调用您的 onRequestPermissionResult()
with empty arrays:
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can reqeust only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
或者当然是这种行为 isn't documented 因为这是 Android,谁想要记录复杂的行为?
无论如何,您始终可以在 onCreate()
中请求权限,然后忽略对具有零长度 permissions
数组的 onRequestPermissionsResult()
的调用。