android m
一、概述
在对动态权限申请进行详细说明时,还是先大致介绍下6.0后,Google对权限的一个归类和划分。在Android M之前,再开发应用的时候,程序员只需要在Androidmanifest.xml文件中进行权限配置即可,这种操作确实比较方便,但是也容让有些程序员为了图方便,一股脑儿的申请很多权限,也不管APP是否能用上。另一方面,对用户而言,一般在安装应用的时候,也不会注意申请了哪些权限,很容易造成用户的数据泄露。所以谷歌从Android M之后,将权限进行了分类,分为普通权限,危险权限和特殊权限。普通权限和以前一样,在AndroidManifest.xml文件配置即可,危险权限就需要程序员更加需要进行动态申请(两个特殊权限再次暂不做讨论)。
危险权限共分为9组,每一组只要其中一个权限授权了,那同一组的其他权限也自动取得授权,具体如下:
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.calendar
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
二、动态申请权限的方法步骤
总的来说,动态申请权限分为三大步
第一、检测权限是否已经获取
第二、申请获取权限
第三、根据申请反馈的结果(用户是否同意)进行不同的处理
检测是否已经获取到权限,调用checkSelfPermission(String permission)方法即可
final String[] permissions = {Manifest.permission.CAMERA};
// 第一步 检测权限:返回结果如下
//PackageManager.PERMISSION_GRANTED(有权限)
//PackageManager.PERMISSION_denied(无权限)
int result = checkSelfPermission(permissions[0]);
根据返回检测结果,做不同处理,如果没有获取到权限,调用requestPermissions(@NonNull String[] permissions, int requestcode)方法获取权限。
这里多啰嗦几句,一般在调用该方法之前,需要先调用shouldShowRequestPermissionRationale(@NonNull String permission)这个方法,判断用户是否已经拒绝过该权限。如果用户在第一次申请的时候,拒绝了该权限,再次申请该权限的时候,该方法就会返回true(默认返回false),这个时候为了增加用户友好体验,可以在此处给用户做一些说明,为什么需要这个权限,希望用户同意等等……,不过此处有坑,后面会详细介绍。
if (result == PackageManager.PERMISSION_GRANTED) {
// 已经具有权限,直接打开相机
startCamera();
} else {
// 第二步 申请权限
// 判断是否需要向用户弹出权限需求说明
if (shouldShowRequestPermissionRationale(permissions[0])) {
new alertdialog.builder(MainActivity.this)
.settitle("提示")
.setmessage("应用需要相机权限才能正常使用, 是否授权")
.setNegativeButton("取消", null)
.setpositivebutton("授权", new dialoginterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissions, REQUEST_CODE);
}
})
.show();
return;// 结束执行,防止重复请求权限
}
requestPermissions(permissions, REQUEST_CODE);
}
如果是第一次申请权限,则直接弹出申请对话框:如果是第二次申请权限,则会弹出提示对话框
对申请结果(用户同意与否)进行监听并处理,重写onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)这个方法
if (requestCode == REQUEST_CODE && grantResults.length > 0) { // 判断是否有返回结果
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
toast.maketext(this, "获取到相机权限, 打开相机", Toast.LENGTH_SHORT).show();
startCamera();
} else {
Toast.makeText(this, "获取相机权限失败", Toast.LENGTH_SHORT).show();
}
}
三、使用过程中遇到的一些坑
在此先将个人已经遇到的一些坑分享给大家
1、动态权限同样需要在 AndroidManifest.xml文件中进行配置。不知道是我某些地方出错还是确实是这样,至少我在使用过程中发现,如果没有在AndroidManifest.xml文件中进行权限配置,同样不能够正常申请权限。所以无论是普通权限还是危险权限,全部都需要在清单文件里面进行配置。
2、shouldShowRequestPermissionRationale(@NonNull String permission)的返回值问题。由于国内android手机厂家的系统几乎都是经过自己定制处理过的,有些手机厂家直接将该方法的返回值确定为false。及无论用户第几次拒绝,都不会返回true。解决办法和问题3解决方法相同如下
3、用户选择不再提示后拒绝权限。如果用户在拒绝权限的时候,选择了不再提示,那以后应用都不会在弹出对框去申请权限,最终造成APP无法正常使用。如果用户不知道是因为自己拒绝了权限造成的,就会以为你的APP很烂,造成用户体验差。一般解决问题2和3的方式就是,在用户选择了拒绝权限的时候,就对用户进行提示,如果需要,同时引导用户去重新授权,我的处理方式,如果用户确定拒绝,则退出应用,如果用户选择重新授权,直接跳转到应该管理的界面,让用户重新授权,代码如下(该Demo里面不含此部分处理)
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("权限提醒")
.setMessage("是否要拒绝权限,如果拒绝,应用将无法正常运行")
.setPositiveButton("拒绝", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
MyApplication.getinstance().exit();
}
})
.setNegativeButton("重设", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!settings.System.canWrite(LoginActivity.this)) {
intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.flag_activity_new_task);
startActivity(intent);
}
}
}
})
.show();
4、兼容问题:checkSelfPermission和requestPermissions从API 23才加入,低于23版本,需要在运行时判断 或者使用Support Library v4中提供的方法contextCompat.checkSelfPermission
ActivityCompat.requestPermissions
ActivityCompat.shouldShowRequestPermissionRationale
四、比较好用的动态权限处理第三方库推荐
个人目前感觉比较好用的有两个库
PermissionsDispatcher gitHub地址
PermissionGen gitHub地址
本文Demo的下载地址 https://github.com/victorcatfish/PermissionsM.git
我也是一个初学和摸索者,如果有不对的地方还望大家多多指正。
相关阅读
Java代码 <pre name="code" class="java">ContentResolver cr = getContentResolver();Cursor cursor = cr.query(ContactsContr
Android中Adapter的notifyDataSetInvalidated()和noti
notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容。public void
在拜读和翻译了Android design设计指导后,对比Android 4.0与Android2.3及之前版本的app设计指导,总结了Android 4.0设计的10大改变:1
Android9.0,5.0,6.0,7.0,8.0新特性整理
Android 9.0新特性 1、全面屏支持,Android P加入了对刘海屏的支持,谷歌称之为凹口屏幕(display with a cutout)。借助最新的提
android cts测试方法及步骤 Android gts测试方法与步
CTS 是一个兼容性性测试工具。是Android TV 的必备条件。 CTS 是一个自动化测试工具,其中包括两个主要软件组件: CTS tradefed 自动