Android权限机制
Android系统在第一版就开始有了权限机制,如访问网络、读取联系人等操作都需要声明权限,但之前的权限仅仅在AndroidManifest文件中声明一下就行了,容易造成滥用权限的现象,在用户安全和隐私保护上没起到多大的作用。从Android 6.0(API 21)开始,Android引入运行时权限。将常用的权限分为两类,一类是普通权限,一类是危险权限。普通权限不会对用户的安全和隐私造成威胁,与之前一样,要使用时只需在Manifast文件中声明即可。危险权限除了在AndroidManifest文件中声明以外,还必须由用户手动授权才可以,否则在使用相关功能时系统将会抛出异常。
AndroidManifest文件的声明如下所示。
<uses-permission android:name="android.permission.INTERNET" /> <!-- 声明网络权限 --><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- 声明接收开机广播权限 -->
申请运行时权限
需要注意的是,Android将30个危险权限分为了11组,只要成功申请某一个危险权限,那么该权限组的所有权限都会被系统自动授权。比如SEND_SMS权限和READ_SMS权限同在SMS权限组,只要应用申请了SEND_SMS权限,就自动获取了READ_SMS权限。30个危险权限见Android权限组。
在App没有重装或在设置中更改权限授予的情况下,一个权限申请成功一次后就不需要再次申请了。这里以申请打电话权限为例介绍两种申请权限的方式,一种是直接通过原生代码申请,一种是通过常用的权限框架申请。
原生方式申请
这里用Kotlin代码演示如何申请CALL_PHONE权限。
首先在AndroidManifest中声明CALL_PHONE的权限。
<uses-permission android:name="android.permission.CALL_PHONE" />
然后在Activity中申请权限并重写onRequestPermissionsResult方法,。
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 检查当前是否已经拥有某个权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)== PackageManager.PERMISSION_DENIED){// 申请相关权限ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), 1)} else {// 已经拥有相关权限,直接执行call()}}// 申请权限后会回调这个方法override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<out String>,grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {1 -> {if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {call() // 申请权限成功,执行相关操作} else {Log.d("TAG", "You denied the permisson")}}}}// 拨打电话private fun call() {val intent = Intent(Intent.ACTION_CALL)intent.data = Uri.parse("tel:10086")startActivity(intent)}}
