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)
}
}