美文网首页Android组件化
Android组件化架构 - 6. 权限管理

Android组件化架构 - 6. 权限管理

作者: 今阳说 | 来源:发表于2020-12-24 13:37 被阅读0次

    权限的目的

    权限设立的目的是保护安全

    权限机制

    系统权限分三种:

    • Android所有者权限,即Android Rom开发权限;
    • Android Root权限,Linux系统中的最高用户权限;
    • Android 应用程序权限,应用开发者在项目的AndroidManifest中声明,然后由用户授权获取
      (Android 应用程序权限分为两种,普通权限(不涉及用户隐私,系统自动授权)和敏感权限(涉及用户隐私,需要用户手动授权))

    1. 原生运行时权限请求

    工具类封装
    
    /**
     * @Author: LiuJinYang
     * 运行时权限工具类
     */
    public class LjyPermissionUtil {
        private PermissionResultListener permissionResultListener;
    
        private LjyPermissionUtil() {
        }
    
        public static LjyPermissionUtil getInstance() {
            return PermissionUtilHolder.instancePermissionUtil;
        }
    
        private static class PermissionUtilHolder {
            private static final LjyPermissionUtil instancePermissionUtil 
                  = new LjyPermissionUtil();
        }
    
        /**
         * 判断当前应用是否有指定权限,运行时权限的检测
         */
        public boolean hasPermissions(Context context, String[] permissions) {
            if (permissions == null || permissions.length == 0) {
                return true;
            }
            boolean ifSdk = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
            for (String permission : permissions) {
                if (ifSdk && !hasPermission(context, permission)) {
                    return false;
                }
            }
            return true;
        }
    
        private boolean hasPermission(Context context, String permission) {
            return ActivityCompat.checkSelfPermission(context, permission)
                   == PackageManager.PERMISSION_GRANTED;
        }
    
        /**
         * 动态申请指定权限,配合hasPermission使用,
         * 注意在使用的activity中调用onRequestPermissionsResult权限申请结果的回调
         *
         * @param activity
         * @param permissions
         * @param requestCode
         */
        public void requestPermission(final Activity activity, final String[] permissions, 
              final int requestCode, final PermissionResultListener permissionResultListener) {
            this.permissionResultListener = permissionResultListener;
            ActivityCompat.requestPermissions(activity, permissions, requestCode);
        }
    
        /**
         * 申请权限的结果回调,需要在Activity的onRequestPermissionsResult中调用
         *
         * @param grantResults
         */
        public void onPermissionResult(Activity activity, final int requestCode,
               String[] permissions, int[] grantResults) {
            boolean hasPermission = true;
            List<String> deniedList = new ArrayList<>();
            List<String> cancelList = new ArrayList<>();
            for (int i = 0; i < grantResults.length; i++) {
                boolean isAllow = grantResults[i] == PackageManager.PERMISSION_GRANTED;
                hasPermission &= isAllow;
                if (!isAllow) {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
                     || !activity.shouldShowRequestPermissionRationale(permissions[i])) {
                        deniedList.add(permissions[i]);
                    } else {
                        cancelList.add(permissions[i]);
                    }
                }
            }
            if (permissionResultListener != null) {
                if (hasPermission) {
                    permissionResultListener.onSuccess(requestCode);
                } else {
                    if (deniedList.size() > 0) {
                        permissionResultListener.onDenied(deniedList);
                    }
                    if (cancelList.size() > 0) {
                        permissionResultListener.onCancel(cancelList);
                    }
                }
            }
    
        }
    
        /**
         * 权限申请结果的回调接口
         */
        public interface PermissionResultListener {
            /**
             * 申请成功
             */
            void onSuccess(final int requestCode);
    
            /**
             * 拒绝的权限集合(不在弹框提醒)
             */
            void onDenied(@NonNull List<String> deniedList);
    
            /**
             * 取消的权限集合
             */
            void onCancel(@NonNull List<String> cancelList);
        }
    }
    
    工具类的使用
    //baseActivity的onRequestPermissionsResult中
    open class BaseActivity : AppCompatActivity() {
        override fun onRequestPermissionsResult(requestCode: Int, 
                permissions: Array<out String>, grantResults: IntArray) {
            if (grantResults.isNotEmpty()) {
                LjyPermissionUtil.getInstance().onPermissionResult(this,
                   requestCode, permissions, grantResults)
            }
        }
    }
    
    class PermissionActivity : BaseActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_permission)
    
        }
    
        fun onBtnClick(view: View) {
            when (view.id) {
                //原生获取运行时权限
                R.id.button_perm_1 -> requestPermission()
            }
        }
    
        private fun requestPermission() {
            val permissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, 
                      Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA)
            if (LjyPermissionUtil.getInstance().hasPermissions(this@PermissionActivity, permissions)) {
                printFileName()
            } else {
                val mRequestCode=1002
                LjyPermissionUtil.getInstance().requestPermission(
                        this@PermissionActivity,
                        permissions,
                        mRequestCode,
                        object : LjyPermissionUtil.PermissionResultListener {
                            override fun onSuccess(requestCode: Int) {
                                if (requestCode == mRequestCode) {
                                    printFileName()
                                }
                            }
    
                            override fun onDenied(deniedList: MutableList<String>) {
                                LjyToastUtil.toast(this@PermissionActivity,
                                 "权限被拒绝,将导致APP无法正常使用,请前往设置中修改")
                                for (it in deniedList) {
                                    LjyLogUtil.d("deniedList:$it")
                                }
                            }
    
                            override fun onCancel(cancelList: MutableList<String>) {
                                LjyToastUtil.toast(this@PermissionActivity, "取消了权限申请")
                                for (it in cancelList) {
                                    LjyLogUtil.d("failList:$it")
                                }
                            }
                        }
                )
            }
        }
    
        private fun printFileName() {
            LjyLogUtil.d("操作文件...")
        }
    }
    
    

    2. RxPermission

    还有一些比较常用的权限请求框架,如RxPermission

    //rxPermissionss的使用
    //1. build.gradle中添加依赖
    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
    
    dependencies {
        implementation 'com.github.tbruyelle:rxpermissions:0.12'
    }
    //注意:最新版rxpermission需要配合RxJava3使用
    //rxjava3
    implementation 'io.reactivex.rxjava3:rxjava:3.0.4'
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    
    //2.调用
    //所有权限统一结果
    new RxPermissions(this)
        .request(Manifest.permission.READ_EXTERNAL_STORAGE,
               Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA)
        .subscribe(accept -> {
            if (accept) {
                LjyLogUtil.d("允许了权限申请");
            } else {
                LjyLogUtil.d("拒绝了权限申请");
            }
        });
    //将权限申请结果逐一返回
    new RxPermissions(this)
        .requestEach(Manifest.permission.READ_EXTERNAL_STORAGE, 
          Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA)
        .subscribe(permission -> {
            // will emit 2 Permission objects
            LjyLogUtil.d(permission.toString());
            if (permission.granted) {
                // `permission.name` is granted !
                LjyLogUtil.d("允许了权限申请:" + permission.name);
            } else if (permission.shouldShowRequestPermissionRationale) {
                // Denied permission without ask never again
                LjyLogUtil.d("取消了权限申请:" + permission.name);
            } else {
                // Denied permission with ask never again
                // Need to go to the settings
                LjyLogUtil.d("权限被拒绝,将导致APP无法正常使用,请前往设置中修改:" + permission.name);
            }
        });
    

    3. RxPermissions原理

    新建RxPermissions类的时候,框架会悄悄的新建一个RxPermissionsFragment类,
    也就是说框架在内部封装了一个没有界面的fragment,
    这样做的好处是请求权限的回调可以在Fragment中实现,不需要用户再去调用onRequestPermissionsResult

    我是今阳,如果想要进阶和了解更多的干货,欢迎关注公众号”今阳说“接收我的最新文章

    相关文章

      网友评论

        本文标题:Android组件化架构 - 6. 权限管理

        本文链接:https://www.haomeiwen.com/subject/hxrmnktx.html