Android Marshmallow:在运行时更改权限会使应用程序崩溃
Posted
技术标签:
【中文标题】Android Marshmallow:在运行时更改权限会使应用程序崩溃【英文标题】:Android Marshmallow: Changing permissions at run time crashes app 【发布时间】:2016-09-06 17:26:19 【问题描述】:Marshmallow 重新设计了获取权限。所以在调用需要权限的方法之前处理权限并且它工作正常,但它在以下情况下崩溃:
第 1 步:打开应用并授予所有必要的权限
第 2 步:单击主页按钮(因此应用程序在后台)
第 3 步:在设置中手动更改权限
第 4 步:从多任务启动应用程序,现在由于应用程序上下文无效而崩溃
观察到应用程序再次创建,不明白为什么会发生这种情况。欢迎提出任何纠正此问题的建议!
【问题讨论】:
有异常吗??如果是,你应该在 try catch 块中处理它 检查这个....***.com/questions/33488589/… 发现了这个问题,因为当我们通过保持应用程序在后台运行来动态更改权限时,应用程序被重新创建,我用来访问共享首选项的上下文变为空 【参考方案1】:首先定义一个布尔值
private boolean isPermissionGranted = false;
然后检查是否授予权限:
if (!isPermissionGranted)
checkPermission();
运行时权限检查的实际代码如下:
private void checkPermission()
int hasPermission = ContextCompat.checkSelfPermission(UserProfile.this, Manifest.permission.CAMERA);
int hasWritePermission = ContextCompat.checkSelfPermission(UserProfile.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasPermission != PackageManager.PERMISSION_GRANTED && hasWritePermission != PackageManager.PERMISSION_GRANTED)
if (!ActivityCompat.shouldShowRequestPermissionRationale(UserProfile.this, Manifest.permission.CAMERA) && !ActivityCompat.shouldShowRequestPermissionRationale(UserProfile.this, Manifest.permission.WRITE_EXTERNAL_STORAGE))
showMessage(getString(R.string.allow_access_to_camera_external_storage),
new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
ActivityCompat.requestPermissions(UserProfile.this, new String[]Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE,
REQUEST_CODE_ASK_PERMISSIONS);
);
return;
ActivityCompat.requestPermissions(UserProfile.this, new String[]Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE,
REQUEST_CODE_ASK_PERMISSIONS);
return;
else
isPermissionGranted = true;
private void showMessage(String message, DialogInterface.OnClickListener listener)
new AlertDialog.Builder(UserProfile.this)
.setMessage(message)
.setPositiveButton(R.string.ok, listener)
.setNegativeButton(R.string.cancel, null)
.create()
.show();
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
switch (requestCode)
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
isPermissionGranted = true;
else
isPermissionGranted = false;
Toast.makeText(UserProfile.this, R.string.permission_denied, Toast.LENGTH_SHORT)
.show();
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
您可以参考上面的代码并在您的应用程序中实现它。
【讨论】:
【参考方案2】:观察到应用再次创建,不明白为什么会这样 发生。欢迎提出任何纠正此问题的建议!
因为当权限改变时,应用“状态”应该失效。正确的做法是销毁根上下文,即应用程序本身。
每次查询需要这些权限的 API 方法时,都必须检查权限授予状态。您不能依赖某些 SharedPreferences
标志来表示“用户授予了入职权限,好的,让我们玩得开心”。在这方面使您的应用程序无状态。
例如,您可以创建一些 BaseActivity/BaseFragment 或 Utility 并将所有检查逻辑移入其中。
【讨论】:
【参考方案3】:这是因为 Marshmallow 添加了其他功能。您需要在运行时向用户请求。为此,请使用我制作的此类。然后在需要的地方使用它
public class AppPermission
public static boolean isMarshmallowPlusDevice()
return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
@TargetApi(Build.VERSION_CODES.M)
public static boolean isPermissionRequestRequired(Activity activity, @NonNull String[] permissions, int requestCode)
if (isMarshmallowPlusDevice() && permissions.length > 0)
List<String> newPermissionList = new ArrayList<>();
for (String permission : permissions)
if (PackageManager.PERMISSION_GRANTED != activity.checkSelfPermission(permission))
newPermissionList.add(permission);
if (newPermissionList.size() > 0)
activity.requestPermissions(newPermissionList.toArray(new String[newPermissionList.size()]), requestCode);
return true;
return false;
然后将此代码放在需要用户许可的地方。
if (!AppPermission.isPermissionRequestRequired(SignInActivity.this, new String[]"android.permission.GET_ACCOUNTS",
REQUEST_APP_PERMISSION))
// Your code if permission available
在此之后,在您的Fragment
或Activity
中输入此代码-
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
case REQUEST_APP_PERMISSION:
for (int i = 0; i < permissions.length; i++)
String permission = permissions[i];
int grantResult = grantResults[i];
switch (permission)
case "android.permission.GET_ACCOUNTS":
if (PackageManager.PERMISSION_GRANTED == grantResult)
// Your code
break;
break;
以上代码用于GET_ACCOUNTS
的请求权限,您可以将其更改为所需的任何内容。
【讨论】:
如果上面的代码还不够,那就放一些代码。上面的代码大部分都错过了 我面临的不是代码级问题,只是想确保在我手动更改设置中的权限时重新创建应用程序(在启动在后台运行的应用程序时,它会崩溃) @ABI : 你的问题解决了吗?恢复应用时如何处理异常。以上是关于Android Marshmallow:在运行时更改权限会使应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
Android Marshmallow:在运行时更改权限会使应用程序崩溃
永远不会结束marshmallow android的后台服务
可以在 Android Marshmallow (API 23) 的运行时权限模型中同步请求权限吗?
如何在 Android 6.0 Marshmallow 中访问相机?