【问题标题】:Android Marshmallow: Changing permissions at run time crashes appAndroid Marshmallow:在运行时更改权限会使应用程序崩溃
【发布时间】:2016-09-06 17:26:19
【问题描述】:

Marshmallow 重新设计了获取权限。所以在调用需要权限的方法之前处理权限并且它工作正常,但它在以下情况下崩溃:

第 1 步:打开应用并授予所有必要的权限

第 2 步:单击主页按钮(因此应用程序在后台)

第 3 步:在设置中手动更改权限

第 4 步:从多任务启动应用程序,现在由于应用程序上下文无效而崩溃

观察到应用程序再次创建,不明白为什么会发生这种情况。欢迎提出任何纠正此问题的建议!

【问题讨论】:

  • 有异常吗??如果是,你应该在 try catch 块中处理它
  • 发现了这个问题,因为当我们通过保持应用程序在后台运行来动态更改权限时,应用程序被重新创建,我用来访问共享首选项的上下文变为空

标签: android android-6.0-marshmallow android-permissions


【解决方案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
      }
      

      在此之后,在您的FragmentActivity 中输入此代码-

      @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 : 你的问题解决了吗?恢复应用时如何处理异常。
      猜你喜欢
      • 2016-02-20
      • 2018-05-08
      • 1970-01-01
      • 2016-10-11
      • 2016-02-02
      • 1970-01-01
      • 2017-10-13
      • 1970-01-01
      • 2018-09-15
      相关资源
      最近更新 更多