写在前面的话
最近学习 Android 开发学到了运行时权限这部分,为了更好的理解与熟悉运行时权限的申请方法,我查找了一些资料做了如下总结。为了方便后期查看,同时也分享出来供大家一起学习。
文章中若有描述不严谨或错误的地方,还请指出。
方法一:一般写法
这个方法中的内容主要参考的是 郭霖 大神的作品《第一行代码(第三版)》。
自 Android 6.0 系统后,Android 引入了运行时权限功能以加强对用户安全与隐私的保护。
申请运行时权限的一般写法如下。
- 通过
ContextCompat.checkSelfPermission()
方法判断是否已有用户授权,该方法需要接受两个参数:第一个参数是一般为上下文Context;第二个参数是需要申请的权限名。 -
ContextCompat.checkSelfPermission()
方法会返回PERMISSION_GRANTED
或PERMISSION_DENIED
,分别代表有授权和无授权。如果有授权,那么直接执行操作逻辑即可;若无授权,则需要调用ActivityCompat.requestPermissions
方法申请授权,这个方法需要接受三个参数:第一个参数是 Activity 实例;第二个参数是一个用来存放待申请的权限名称的 String 数组,第三个参数是请求码,请求码需要是唯一值。 - 在调用了
requestPermissions
方法后系统会弹出权限申请对话框,如论用户如何选择,最终都要回调到onResultPermissionsResult
方法中,而授权结果则会封装在grantResults
参数当中。 - 于是我们需要判断最后的授权结果,如果用户同意,就可以执行操作逻辑了;若用户拒绝授权的话,那么就只能放弃操作,并弹出相应的提示。
示例代码如下:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.makeCall.setOnClickListener {
//判断是否已有用户授权
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.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 {
Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun call() {
try {
val intent = Intent(Intent.ACTION_CALL)
intent.data = Uri.parse("tel:10000")
startActivity(intent)
} catch (e: SecurityException) {
e.printStackTrace()
}
}
}
方法二:使用第三方库
正所谓“前人种树后人乘凉”,互联网上有大量的第三方库供我们使用来简化运行时权限的处理。
第三方库推荐
简单用法介绍
PremissionX
首先将 PermissionX 引入到项目当中
dependencies {
...
implementation 'com.permissionx.guolindev:permissionx:1.1.1'
}
运行时权限申请的示例代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
makeCallBtn.setOnClickListener {
PermissionX.init(this)
.permissions(Manifest.permission.CALL_PHONE)
.request { allGranted, grantedList, deniedList ->
if (allGranted) {
call()
} else {
Toast.makeText(this, "您拒绝了拨打电话权限", Toast.LENGTH_SHORT).show()
}
}
}
}
...
}
方法三:规避运行时权限
把 targetSdkVersion
控制在 23 以下,系统会继续使用 Android 6.0 之前的权限机制来兼容低版本的客户端,权限申请方式会全部保持为安装时(install time)而非运行时(runtime),如此一来就绕过了运行时权限。
参考资料
Android Dev Doc: Request app permissions
Android 6.0 Marshmallow 中的实时权限( Android 开发模式 Ep 3)
Android Dev Doc: PackageManager