最容易理解的Android6.0动态权限申请教程
1、前⾔
这已经是N年前的知识点了,但是我⼀直以来都有点逃避学习这个,⽽且印象中很⿇烦,后来也不间断有学习过⼀点,但是⼀直没认真去⽤过,所以对这个android6.0的动态权限申请⼀直是不清楚的状态,⽽且项⽬中⽤到动态权限申请的时候我就使⽤RxPermission来实现。今天⼼⾎来潮整了⼀下,发现其实原⽣的动态权限申请也没有想象中的⿇烦,还是很简单的,所以这⾥记录⼀下,以防不⽤的话后⾯⼜忘了。
2、动态权限申请详解
总的来说,动态权限申请分两步:
1. 清单⽂件中声明需要的权限
2. 在代码中动态申请权限
本来感觉在代码中动态申请权限就⾏了,清单⽂件⾥应该就不⽤声明权限了吧?其实是需要的,如果清单⽂件中不声明的话,动态申请权限时是申请不到的,为什么需要在清单⽂件也声明权限呢?答:假如
你的app安装在Android6.0以下的⼿机上,这些⼿机是没有动态权限申请的,则还是⾛清单⽂件申请权限这⼀套旧规则。⽽且就算是在⾼版本的⼿机,应⽤安装好之后,在系统设置中,打开应⽤管理,也能看到你的应⽤申请的所有权限,这些都是系统通过读取清单⽂件来实现的。
这⾥着重讲解代码中如何动态申请权限,先画⼀个流程图,通过流程图可以很简地理解申请权限的流程:
如上流程图写的⽐较详细,看着好似需要写好多代码,其实并不是,代码特别简单,关键代码如下:
1. 判断是否拥有某权限:
ActivityCompat.checkSelfPermission(context, permission)
2. 申请权限:
3. 权限申请结果回调函数:
onRequestPermissionsResult(requestCode, permissions, grantResults)
4. 判断⽤户是否选择了不再提⽰:
ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)
完整⽰例代码如下:
const val PERMISSIONS_CAMERA =0x1
class MainActivity :AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?){
setContentView(R.layout.activity_main)
requestPermission()
}
private fun init(){
// TODO 得到权限后要做的事情
}
private fun requestPermission(){
val hasCameraPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)== PackageManager.PERMISSION_GRANTED if(hasCameraPermission){
init()
}else{
requestCameraPermission()
}
}
private fun requestCameraPermission(){
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray){
if(requestCode == PERMISSIONS_CAMERA){
if(grantResults.isNotEmpty()&& grantResults[0]== PackageManager.PERMISSION_GRANTED){
// 已经授权了,开始使⽤功能吧
init()
return
}
// 权限被拒绝
val shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) if(shouldShowRequestPermissionRationale){
// ⽤户拒绝了摄像头权限,应该解释⼀下为什么需要此权限
AlertDialog.Builder(this)
.setTitle("解释需要此权限的理由")android学习教程
.setMessage("录像时需要⽤到摄像头权限,请允许此权限,否则⽆法录制摄像头")
.setPositiveButton("确定"){ dialog, which ->requestCameraPermission()}
.setNegativeButton("取消",null)
.setCancelable(false)
.create()
.show()
}else{
// ⽤户拒绝了摄像头权限,并且勾选了不再提⽰
AlertDialog.Builder(this)
.setTitle("打开权限步骤提⽰")
.setMessage("您好狠啊,竟然选择拒绝了权限,⽽且选择不再提⽰。好吧,如果你后悔了,可以在设置中到应⽤来开启此权限")
.setPositiveButton("确定",null)
.setCancelable(false)
.create()
.show()
}
}
}
}
第⼀次运⾏时,效果如下:
系统会弹出申请权限对话框:
注:第⼀次申请权限时,没有不再提⽰的选项哦!
如果⽤户选择禁⽌,此时我们就会弹出⾃定义的对话框,以给⽤户解释我们为什么需要这个权限,如下:
此时,如果⽤户点击取消,则我们不做任何操作,如果⽤户选择确定,则我们再⼀次申请权限,此时系统会再次弹出系统的申请权限对话框,如下:
注意,此时是第⼆次申请权限,所以多了⼀个”禁⽌后不再提⽰“的选项。如果⽤户选择“禁⽌”按钮,则还是⾛之前的流程,如果⽤户选择了“禁⽌后不再提⽰”,则弹另⼀个我们⾃定义的对话框,以告诉⽤户如果你还想打开此权限的话只能到设置⾥去打开了,如下:
此时,你再申请权限时不会再弹出系统的申请权限的对话框了,因为⽤户选择了不再提⽰,但是我们⾃定义的这个对话框还是可以弹出来的,以告诉⽤户可以在设置中来打开此权限,如果⽤户到设置中打开了权限,则开开⼼⼼,如果⽤户在设置打开了权限然后想了⼀下⼜关掉了,则此时的权限状态恢复到初始化状态,⽐如你申请权限时,系统会认为你是第⼀次申请,会弹出系统权限申请对话框,问你是否允许权限,跟开头的流程⼀模⼀样的。
3、动态申请权限流程优化
再回顾⼀下动态申请权限的流程:
这⾥最前的⼀步,先判断是否拥有权限,其实可以不判断的,直接申请权限,这样的结果就是,如果有权限,则不弹任何对话框,在获取结果的回调函数中将会得到权限已授权的结果,如果申请权限时该权限没有被授权,则还是⾛原来的流程。虽然先判断没权限再申请权限好像正规⼀点、效率也更⾼⼀点,但是为了简单,这点效率的影响应该微乎其微。
总结⼀下动态申请权限的步骤就更简单了:
1. 申请权限
2. 获取申请权限结果,如果权限已授权,则做该做的事,如果权限没被授权,则判断⽤户是选择了“禁⽌”还是选择了“禁⽌后不再提
⽰”,并据此弹出对应的⾃定义对话框。
优化后的代码如下:
const val PERMISSIONS_CAMERA =0x1
class MainActivity :AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?){
setContentView(R.layout.activity_main)
requestCameraPermission()
}
private fun init(){
// TODO 得到权限后要做的事情
}
private fun requestCameraPermission(){
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray){
if(requestCode == PERMISSIONS_CAMERA){
if(grantResults.isNotEmpty()&& grantResults[0]== PackageManager.PERMISSION_GRANTED){
// 已经授权了,开始使⽤功能吧
init()
return
}
// 权限被拒绝
val shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) if(sho
uldShowRequestPermissionRationale){// 应该解释⼀下为什么需要此权限
// ⽤户拒绝了摄像头权限
AlertDialog.Builder(this)
.setTitle("解释需要此权限的理由")
.setMessage("录像时需要⽤到摄像头权限,请允许此权限,否则⽆法录制摄像头")
.setPositiveButton("确定"){ dialog, which ->requestCameraPermission()}
.setNegativeButton("取消",null)
.setCancelable(false)
.create()
.show()
}else{
/
/ ⽤户拒绝了摄像头权限,并且勾选了不再提⽰
AlertDialog.Builder(this)
.setTitle("打开权限步骤提⽰")
.setMessage("您好狠啊,竟然选择拒绝了权限,⽽且选择不再提⽰。好吧,如果你后悔了,可以在设置中到应⽤来开启此权限")
.setPositiveButton("确定",null)
.setCancelable(false)
.create()
.show()
}
}
}
}
4、RxPermissions的使⽤
了解了动态权限的申请之后,我们就会发现,每次申请权限,要写⼀些模板代码在Activity中,能不能对申请权限的代码进⾏封装呢?答案是可以的,RxPermissions库就实现了这样的功能,它的原理是给当前Activity添加⼀个⽆界⾯的Fragment,在这个Fragment中申请权限,并在这个Fragment中接收申请权限的结果,所以可以在这个Fragment中封装申请权限的逻辑。并且该库使⽤RxJava进⾏封装,使我们更容易的拿到申请权限的结果。
添加RxPermissions依赖
在项⽬的根⽬录下的adle添加如下配置:
allprojects {
repositories {
maven { url 'jitpack.io'}
}
}
在module⽬录下的adle添加如下配置:
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.12'
}
我们知道RxPermissions是⽤到了RxJava的,通过查看依赖传递,我们发现rxpermissions中有依赖RxJava,但是并没有依赖RxAndroid,我们知道在Android中使⽤RxJava必须要依赖RxAndroid的,所以还需要添加RxAndroid依赖,如下:
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.12'
implementation 'java3:rxandroid:3.0.0'
}
使⽤RxPermissions完成前⾯的例⼦
接下来我们使⽤RxPermissions来完成前⾯的例⼦,看看是不是更简洁呢,代码如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论