Android 开发技巧 - Android 6.0 以上权限大坑和权限检查基类封装

shihunwudi 8年前
   <h3><strong>简单介绍</strong></h3>    <p>关于运行时权限的说法,早在Google发布android 6.0的时候,大家也听得蛮多的。从用户的角度来讲,用户是受益方,更好的保护用户的意思,而对于开发者来说,无疑增加了工作量。</p>    <p>对于6.0以下的权限在安装时,会根据权限声明产生一个权限列表,用户只有同意才能完成app的安装。而在6.0以后,不需要先对权限授权就可以安装app,对于权限的授权我们可以选择禁止。</p>    <p>在新的权限机制中,Google将权限分为两类:</p>    <p><strong>Normal Permissions(普通权限):</strong>不涉及用户隐私,不需要用户进行授权,比如访问网络等;</p>    <p><strong>Dangerous Permission(危险权限):</strong>涉及到用户隐私,需要用户进行授权,比如相机访问、读取SD卡等。</p>    <p>PS:运行时权限只适合APP运行在Android 6.x以上的机器,对于危险权限Google官方也对其进行了分组,只要一组中的某一权限被授权,同组的权限也同样会被授权。</p>    <h3><strong>操作步骤</strong></h3>    <p>简单的介绍了关于运行时权限的使用方法,操作步骤如下</p>    <ol>     <li> <p>在Androidmanifest.xml文件声明相关权限</p> </li>     <li> <p>通过ContextCompat.checkSelfPermission方法检查某项权限被授予情况</p> </li>     <li> <p>申请授权</p> </li>     <li> <p>权限回调处理</p> </li>    </ol>    <h3><strong>封装调用</strong></h3>    <p>权限的申请我们一般的做法都在Activity被创建的时候,才开始申请危险权限。而每次都得重复上述的操作,想想都觉得烦。为此,笔者将运行时权限的使用进行了进一步的归纳总结。将权限的检查统一封装在基类中,子类继承并实现抽象方法,传入权限数组等即可。</p>    <p>1)通过抽象方法getNeedPermissions( )获取需要进行检测的权限数组,检查相关权限是否授权,如果未授权则开始申请权限</p>    <pre>  <code class="language-java">/**       * 检查所有权限,无权限则开始申请相关权限       */      protected void checkAllNeedPermissions() {          if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;          List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());          if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {              ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(                      new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);          }      }</code></pre>    <p>2)权限授权情况回调处理,这里授权失败默认弹框是否前往设置页面授权</p>    <pre>  <code class="language-java">/**       * 权限授权结果回调       *       * @param requestCode       * @param permissions       * @param paramArrayOfInt       */      @Override      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,                                             @NonNull int[] paramArrayOfInt) {          if (requestCode == REQUEST_CODE_PERMISSON) {              if (!verifyPermissions(paramArrayOfInt)) {                  permissionGrantedFail();                  showTipsDialog();                  isNeedCheckPermission = false;              } else permissionGrantedSuccess();          }      }</code></pre>    <p>PS:其中permissionGrantedSuccess()和permissionGrantedSuccess()为抽象方法,由子类实现。</p>    <p>3)简单调用,子类继承该基类,实现以下抽象方法即可</p>    <pre>  <code class="language-java">@Override      public String[] getNeedPermissions() {          return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};      }        @Override      protected void permissionGrantedSuccess() {        }        @Override      protected void permissionGrantedFail() {      }</code></pre>    <p>有没有觉得酱紫操作清晰了很多,也方便了不少。依然如此,就赶紧mark吧。</p>    <p>封装类的完整代码如下:</p>    <pre>  <code class="language-java">/**   * Created by chenyk on 2016/9/28.   * 检查相关权限基类,适用于android 6.0 运行时权限   * 使用方法:需要运行时权限的activity继承此类   */  public abstract class BaseCheckPermissionActivity extends NeedBackActivity          implements OnRequestPermissionsResultCallback {      private static final int REQUEST_CODE_PERMISSON = 2020; //权限请求码        private boolean isNeedCheckPermission = true; //判断是否需要检测,防止无限弹框申请权限        @Override      protected void onResume() {          super.onResume();          if (isNeedCheckPermission) {              checkAllNeedPermissions();          }      }        /**       * 检查所有权限,无权限则开始申请相关权限       */      protected void checkAllNeedPermissions() {          if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;          List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());          if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {              ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(                      new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);          }      }        /**       * 获取权限集中需要申请权限的列表       *       * @param permissions       * @return       */      private List<String> getDeniedPermissions(String[] permissions) {          List<String> needRequestPermissonList = new ArrayList<>();          for (String permission : permissions) {              if (ContextCompat.checkSelfPermission(this, permission) !=                      PackageManager.PERMISSION_GRANTED ||                      ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {                  needRequestPermissonList.add(permission);              }          }          return needRequestPermissonList;      }        /**       * 所有权限是否都已授权       *       * @return       */      protected boolean isGrantedAllPermission() {          List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());          return needRequestPermissonList.size() == 0;      }        /**       * 权限授权结果回调       *       * @param requestCode       * @param permissions       * @param paramArrayOfInt       */      @Override      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,                                             @NonNull int[] paramArrayOfInt) {          if (requestCode == REQUEST_CODE_PERMISSON) {              if (!verifyPermissions(paramArrayOfInt)) {                  permissionGrantedFail();                  showTipsDialog();                  isNeedCheckPermission = false;              } else permissionGrantedSuccess();          }      }        /**       * 检测所有的权限是否都已授权       *       * @param grantResults       * @return       */      private boolean verifyPermissions(int[] grantResults) {          for (int grantResult : grantResults) {              if (grantResult != PackageManager.PERMISSION_GRANTED) {                  return false;              }          }          return true;      }        /**       * 显示提示对话框       */      protected void showTipsDialog() {          new AlertDialog.Builder(this).setTitle("提示信息").setMessage("当前应用缺少" + getDialogTipsPart()                  + "权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。")                  .setNegativeButton("取消", new DialogInterface.OnClickListener() {                      @Override                      public void onClick(DialogInterface dialog, int which) {                          finish();                      }                  })                  .setPositiveButton("确定", new DialogInterface.OnClickListener() {                      @Override                      public void onClick(DialogInterface dialog, int which) {                          startAppSettings();                      }                  }).show();      }          /**       * 启动当前应用设置页面       */      private void startAppSettings() {          Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);          intent.setData(Uri.parse("package:" + getPackageName()));          startActivity(intent);      }        /**       * 获取弹框提示部分内容       *       * @return       */      protected String getDialogTipsPart() {          return "必要";      }        /**       * 获取需要进行检测的权限数组       */      protected abstract String[] getNeedPermissions();        /**       * 权限授权成功       */      protected abstract void permissionGrantedSuccess();        /**       * 权限授权失败       */      protected abstract void permissionGrantedFail();</code></pre>    <p> </p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/a0ca49f7cb61</p>    <p> </p>