Android 的权限机制,从系统的第一个版本开始就已经存在了。但其实之前 Android 的权限机制在保护用户安全和隐私等方面起到的作用比较有限,尤其是一些大家都离不开的常用软件,非常容易“店大欺客”。为此,Android 开发团队在Android 6.0 系统中引入了运行时权限这个功能
权限机制
们在AndroidManifest.xml 文件中 添加了权限声明:
<uses-permission android:name="android.permission.CALL_PHONE" />
加入了这句权限声明后,用户主要在两个方面得到了保护。
一方面,如果用户在低于Android 6.0 系统的设备上安装该程序,会在安装界面给出提醒。这样用户就可以清楚地知晓该程序一共申请了哪些权限,从而决定是否要安装这个程序。
另一方面,用户可以随时在应用程序管理界面查看任意一个程序的权限申请情况。
这种权限机制的设计思路其实非常简单,就是用户如果认可你所申请的权限,就会安装你的程序,如果不认可你所申请的权限,那么拒绝安装就可以了。 但是理想是美好的,现实却很残酷。很多我们离不开的常用软件普遍存在着滥用权限的情况,不管到底用不用得到,反正先把权限申请了再说。
Android 开发团队当然也意识到了这个问题,于是在Android 6.0 系统中加入了运行时权限功能。也就是说,用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的 使用过程中再对某一项权限申请进行授权。
当然,并不是所有权限都需要在运行时申请,对于用户来说,不停地授权也很烦琐。Android 现 在将常用的权限大致归成了两类,一类是普通权限,一类是危险权限。准确地讲,其实还有一些特殊权限,不过这些权限使用得相对较少。普通权限指的是那些不会直接威胁到用户的安全和隐私的权限,对于这部分权限申请,系统会自动帮我们进行授权,不需要用户手动操作。危险权限则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信 息、定位设备的地理位置等,对于这部分权限申请,必须由用户手动授权才可以,否则程序就 无法使用相应的功能。
到Android 10 系统为止所有的危险权限
注意,表格中每个危险权限都属于一个权限组,我们在进行运行时权限处理时使用的是权限名。原则上,用户一旦同意了某个权限申请之后,同组的其他权限也会被系统自动授权。但是请谨记,不要基于此规则来实现任何功能逻辑,因为Android 系统随时有可能调整权限的分组。
在程序运行时申请权限
CALL_PHONE这个权限是编写拨打电话功能的时候需要声明的,因为拨打电话会涉及用户手机的资费问题,因而被列为了危险权限。
修改activity_main.xml 布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/makeCall" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Make Call" /> </LinearLayout>
接着修改 MainActivity 中的代码:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) makeCall.setOnClickListener { // 判断用户是不是已经给过我们授权了,借助的是ContextCompat.checkSelfPermission()方法。 // checkSelfPermission()方法接收两个参数: // 第一个参数是Context,这个没什么好说的; // 第二个参数是具体的权限名,比如打电话的权限名就是Manifest.permission.CALL_PHONE。 // 然后我们使用方法的返回值和PackageManager.PERMISSION_GRANTED做比较,相等就说明用户已经授权,不等就表示用户没有授权。 if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ) { // 调用ActivityCompat.requestPermissions()方法向用户申请授权。 // requestPermissions()方法接收3个参数: // 第一个参数要求是Activity 的实例; // 第二个参数是一个String数组,我们把要申请的权限名放在数组中即可; // 第三个参数是请求码,只要是唯一值就可以了,这里传入了1。 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), 1) } else { call() } } } // 调用完requestPermissions()方法之后,系统会弹出一个权限申请的对话框,用户可以选择同意或拒绝我们的权限申请。 // 不论是哪种结果,最终都会回调到onRequestPermissionsResult()方法中,而授权的结果则会封装在grantResults参数当中。 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { 1 -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { call() } else { Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show() } } } } private fun call() { try { // 在按钮的点击事件中,我们构建了一个隐式Intent ,Intent 的action 指定为Intent.ACTION_CALL,这是一个系统内置的打电话的动作, val intent = Intent(Intent.ACTION_CALL) intent.data = Uri.parse("tel:10086")//在data 部分指定了协议是tel ,号码是10086 startActivity(intent) } catch (e: SecurityException) { e.printStackTrace() } } }
接下来修改AndroidManifest.xml 文件,在其中声明如下权限:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.CALL_PHONE" />
标签:申请,用户,CALL,授权,Android,权限,运行 From: https://www.cnblogs.com/ooo0/p/17059196.html