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

权限的目的

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

权限机制

系统权限分三种:

  • 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 deniedList = new ArrayList<>();
        List 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 deniedList);

        /**
         * 取消的权限集合
         */
        void onCancel(@NonNull List cancelList);
    }
}
工具类的使用
//baseActivity的onRequestPermissionsResult中
open class BaseActivity : AppCompatActivity() {
    override fun onRequestPermissionsResult(requestCode: Int, 
            permissions: Array, 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) {
                            LjyToastUtil.toast(this@PermissionActivity,
                             "权限被拒绝,将导致APP无法正常使用,请前往设置中修改")
                            for (it in deniedList) {
                                LjyLogUtil.d("deniedList:$it")
                            }
                        }

                        override fun onCancel(cancelList: MutableList) {
                            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

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/19690,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?