加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Android:运行时权限的简单使用——以拨打电话为例

(2023-06-16 22:10:10)
分类: androidios
什么是运行时权限?
所谓运行时权限也就是说在应用程序使用的过程中需要手动进行授权的权限。Android 6.0 以后,Android官方就添加了这项功能,不同于只需要在 AndroidManifest.xml 文件中声明的普通权限,运行时权限都是一些涉及用户隐私的权限。
在本教程中,我们以申请拨打电话权限 CALL_PHONE 为例。在 Android 中,还有一个与拨打电话权限类似的权限:打开拨号盘 DIAL。这两者的区别主要是前者是直接拨打电话,而后者只是打开拨号盘自动填充电话号码,并不拨打出去,在使用时注意区别。
须知

    运行时权限其实并不囊括所有的权限;
    事实上,Android中的权限大致分为三类:
        普通权限:联网、打开拨号盘等;
        **危险权限:**触及用户的安全和隐私的权限,例如:直接拨号(涉及资费)、读取通讯录等(涉及隐私)。
        正因为危险,所以这才是运行时权限的范畴;至于有哪些,可以自行上网搜索。
        特殊权限:使用较少,不做讨论。
    运行时权限也需要在 AndroidManifest.xml 文件中注册声明。

流程

在这里插入图片描述
‍ 步骤
1.在AndroidManifest.xml文件中注册权限

这没什么好说的,不注册会导致程序出错。在application同级标签添加如下代码:




    1
    2

2.检查拨打电话权限是否授权

接下来就是要检查申请的运行时权限用户是否授权过,这么做的原因是:直接使用某个运行时权限而不经过判断的话,程序是会出错闪退的(*用户之后随时可以在设置里取消某项运行时权限也会导致程序出错),这会严重影响用户体验,这一步也是最重要的。

//    用户未授权过申请
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED){
        // 那就向系统申请权限...
}
//    用户已经授权过申请
else {
      // 发起拨号
      val intent = Intent(Intent.ACTION_CALL)
    intent.data = Uri.parse("tel://10086")
    startActivity(intent)
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

这里的重点是ContextCompat.checkSelfPermission()方法,通过方法检查到某项权限是否申请,然后与成功授权的常量PackageManager.PERMISSION_GRANTED(同意为0,拒绝为-1)进行比对就行了,不相等说明未经过授权。

这里需要两个参数:
参数名称    参数类型    参数说明
context    Context    上下文
权限名称    String    权限名称
3.发送权限申请

假如权限没有授权过,我们就发送权限申请,在未授权的逻辑分支里添加代码如下:

ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.CALL_PHONE),
                123
)

    1
    2
    3
    4
    5

方法:ActivityCompat.requestPermissions()

需要三个参数:
参数名称    参数类型    参数说明
context    Context    上下文
权限数组    String[]    把权限名称放入即可
requestCode    Int    请求码,便于识别和保证唯一就行了
4.进入回调

发送权限申请后,无论用户是否同意,都会进入到onRequestPermissionsResult回调方法里来,而授权的结果就封装在grantResults参数中。回调方法如下:

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array,
    grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

    1
    2
    3
    4
    5
    6

重写该回调方法后,在方法里加入判断:

//    用户同意了申请
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // 立即拨号
      val intent = Intent(Intent.ACTION_CALL)
    intent.data = Uri.parse("tel:10086")
    startActivity(intent)
}
//    用户不想同意
else {
  //    提示
    Toast.makeText(this,"您拒绝了拨打电话的权限申请",Toast.LENGTH_LONG).show()
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

说说这里的大致过程:

    首先我们判断时要保证参数 grantResults 是不为空的;
    接着再与成功授权的常量进行比对,这里的常量我们继续引入 PackageManager.PERMISSION_GRANTED ,相等则为用户同意,不相等则为用户拒绝。
    如果用户同意,我们就立即拨号;不同意就提示用户,一般弹对话框,由于我仅做演示,这里偷懒就用个吐司弹窗。

最终代码

由于本教程主要是教思路,并未系统性地把代码组织起来。以下是我实际开发中写的代码,将教程中的代码组织起来并优化了,仅供参考:

class CallActivity : AppCompatActivity() {
        
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cart)
        
          
        btn_call.setOnClickListener {
              //    用户未授权过申请
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED) {
                  //    向系统发送权限申请
                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), 123)
            }
              //    用户已授权过申请
              else {
                instantCall()
            }
        }
    }

      //    发送权限申请回调
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        //    用户同意了申请
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            instantCall()
        }
        //    用户不想同意
        else {
            Toast.makeText(this, "您拒绝了拨打电话的权限申请", Toast.LENGTH_LONG).show()
        }
    }
 
   // 封装立即拨号代码
    private fun instantCall() {
        val intent = Intent(Intent.ACTION_CALL)
        intent.data = Uri.parse("tel:10086")
        startActivity(intent)
    }
 
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

效果图

在这里插入图片描述
2020年6月24日
————————————————
版权声明:本文为CSDN博主「FutureIsHereX」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47436105/article/details/114177696

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有