在Android上优雅的申请权限

简介

对于权限,每个android开发者应该很熟悉了,对于targetSDK大于23的时候需要对某些敏感权限进行动态申请,比如获取通讯录权限、相机权限、定位权限等。

在android 6.0中也同时添加了权限组的概念,若用户同意组内的某一个权限,那么系统默认app可以使用组内的所有权限,无需再次申请。

这里贴一张权限组的图片:

android权限组

申请权限API

先介绍一下android 6.0以上动态申请权限的流程,申请权限,用户可以点击拒绝,再次申请的时候可以选择不再提醒。

下面说介绍一下运行时申请权限需要用到的API,代码示例使用kotlin实现

  • 在Manifest中注册
	<uses-permission android:name="android.permission.XXX"/>
  • 检查用户是否同意了某个权限
	// (API) int checkSelfPermission (Context context, String permission)
	ContextCompat.checkSelfPermission(context, Manifest.permission.XXX) != PackageManager.PERMISSION_GRANTED
  • 申请权限
	// (API) void requestPermissions (Activity activity, String[] permissions, int requestCode)
   requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), REQUEST_CODE_CALL_PHONE)

  • 请求结果回调
	// (API) void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)
	override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
   

    }
  • 是否需要向用户解释请求权限的目的
	// (API) boolean shouldShowRequestPermissionRationale (Activity activity, String permission)
	ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)
情况 返回值
第一次打开App时 false
上次弹出权限点击了禁止(但没有勾选“下次不在询问”) true
上次选择禁止并勾选“下次不在询问 ” false

注:如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don’t ask again 选项,此方法将返回 false。如果设备规范禁止应用具有该权限,此方法也会返回 false。

单一权限申请交互流程

我们做移动端需要直接与用户交互,需要多考虑如何根用户交互才能达到最好的体验。下面我结合google samples中动态申请权限示例android-RuntimePermissions

https://github.com/googlesamples/android-RuntimePermissions/#readme

以及动态申请权限框架easypermissions

https://github.com/googlesamples/easypermissions

来对交互上做一个总结。

首先说明,Android不建议App直接进行拨打电话这种敏感操作,建议跳转至拨号界面,并将电话号码传入拨号界面中,这里仅作参考案例,下面每中情况都是用户从用户第一次申请权限开始(权限询问状态)

  • 直接允许权限。

    直接允许权限

  • 拒绝之后再次申请允许

    拒绝之后再次申请允许

  • 不再提醒之后引导至设置界面面

    不再提醒之后引导至设置界面面

话不多说,上代码。

    /**
     * 创建伴生对象,提供静态变量
     */
    companion object {
   
        const val TAG = "MainActivity"
        const val REQUEST_CODE_CALL_PHONE = 1
    }
    
    ...
    // 这里进行调用requestPermmission()进行拨号前的权限请求
    ...
    
    private fun callPhone() {
   
        val intent = Intent(Intent.ACTION_CALL)
        val data = Uri.parse("tel:9898123456789")
        intent.data = data
        startActivity(intent)
    }

    /**
     * 提示用户申请权限说明
     */
    @TargetApi(Build.VERSION_CODES.M)
    fun showPermissionRationale(rationale: String) {
   
        Snackbar.make(view, rationale,
                Snackbar.LENGTH_INDEFINITE)
                .setAction("确定") {
   
                    requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), REQUEST_PERMISSION_CODE_CALL_PHONE)
                }.setDuration(3000)
                .show()
    }


    /**
     * 用户点击拨打电话按钮,先进行申请权限
     */
    private fun requestPermmission(context: Context) {
   

        // 判断是否需要运行时申请权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
   
            // 判断是否需要对用户进行提醒,用户点击过拒绝&&没有勾选不再提醒时进行提示
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) {
   
                // 给用于予以权限解释, 对于已经拒绝过的情况,先提示申请理由,再进行申请
                showPermissionRationale("需要打开电话权限直接进行拨打电话,方便您的操作")
            } else {
   
                // 无需说明理由的情况下,直接进行申请。如第一次使用该功能(第一次申请权限),用户拒绝权限并勾选了不再提醒
                // 将引导跳转设置操作放在请求结果回调中处理
                requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), REQUEST_PERMISSION_CODE_CALL_PHONE)
            }
        } else {
   
            // 拥有权限直接进行功能调用
            callPhone()
        }
    }

    /**
     * 权限申请回调
     */
    @TargetApi(Build.VERSION_CODES.M)
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
   
        // 根据requestCode判断是那个权限请求的回调
        if (requestCode == REQUEST_PERMISSION_CODE_CALL_PHONE) {
   
            // 判断用户是否同意了请求
            if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
   
                callPhone(
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值