Android 6.0的新特性之一就是动态权限管理.在6.0之前,在应用安装的时候,提示用户所需要用到的权限列表,同意之后安装,该app就被赋予所有的权限,我们暂且称它为安装时权限,安装后,被赋予的权限也无法取消;在6.0之后,google对权限进行了运行时的管理,而不是在安装时候,危险权限需要在运行时申请,我们暂且称它为运行时权限,非危险权限,在安装时由用户授予,这样简化了应用安装过程,因为用户在安装或更新应用时不需要授予权限,也给予了用户对app功能更多的控制.
系统权限主要分为两类,正常权限和危险权限
正常权限不会直接危及用户的隐私,如果你的应用在它的Manifest中列出了正常权限,系统会自动授予权限
危险权限可以让app访问用户的机密数据,如果你的应用在它的Manifest列出了危险权限,用户必须明确批准你的app使用该权限
危险权限分组说明
权限组 | 权限名称 |
---|---|
CALENDAR | android.permission.READ_CALENDAR |
android.permission.WRITE_CALENDAR | |
CAMERA | android.permission.CAMERA |
CONTACTS | android.permission.READ_CONTACTS |
android.permission.WRITE_CONTACTS | |
android.permission.GET_ACCOUNTS | |
LOCATION | android.permission.ACCESS_FINE_LOCATION |
android.permission.ACCESS_COARSE_LOCATION | |
MICROPHONE | android.permission.RECORD_AUDIO |
PHONE | android.permission.READ_PHONE_STATE |
android.permission.CALL_PHONE | |
android.permission.READ_CALL_LOG | |
android.permission.ADD_VOICEMAIL | |
android.permission.WRITE_CALL_LOG | |
android.permission.USE_SIP | |
android.permission.PROCESS_OUTGOING_CALLS | |
SENSORS | android.permission.BODY_SENSORS |
SMS | android.permission.SEND_SMS |
android.permission.RECEIVE_SMS | |
android.permission.READ_SMS | |
android.permission.RECEIVE_WAP_PUSH | |
android.permission.RECEIVE_MMS | |
STORAGE | android.permission.READ_EXTERNAL_STORAGE |
android.permission.WRITE_EXTERNAL_STORAGE |
对应在清单文件中的展示如下:
...
<!--CALENDAR-->
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<!--CAMERA-->
<uses-permission android:name="android.permission.CAMERA"/>
<!--CONTACTS-->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!--LOCATION-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!--MICROPHONE-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--PHONE-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.ADD_VOICEMAIL"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
<uses-permission android:name="android.permission.USE_SIP"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<!--SENSORS-->
<uses-permission android:name="android.permission.BODY_SENSORS"/>
<!--SMS-->
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<!--STORAGE-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
...
实例:
1.先从Activity的使用开始。
...
public class MainActivity extends AppCompatActivity implements PermissionInterface {
private PermissionHelper mPermissionHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化并发起权限申请
mPermissionHelper = new PermissionHelper(this, this);
mPermissionHelper.requestPermissions();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(mPermissionHelper.requestPermissionsResult(requestCode, permissions, grantResults)){
//权限请求结果,并已经处理了该回调
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public int getPermissionsRequestCode() {
//设置权限请求requestCode,只有不跟onRequestPermissionsResult方法中的其他请求码冲突即可。
return 10000;
}
@Override
public String[] getPermissions() {
//设置该界面所需的全部权限
return new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE
};
}
@Override
public void requestPermissionsSuccess() {
//权限请求用户已经全部允许
initViews();
}
@Override
public void requestPermissionsFail() {
//权限请求不被用户允许。可以提示或者弹框提示权限用途或者指引用户去重新授权
Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
}
}
private void initViews(){
//已经拥有所需权限,可以放心操作任何东西了
}
}
...
其中使用到的两个类和一个接口实现:
2.Activity需要实现的接口PermissionInterface.java
...
/**
* 权限请求接口
* Created by dway on 2018/1/10.
*/
public interface PermissionInterface {
/**
* 可设置请求权限请求码
*/
int getPermissionsRequestCode();
/**
* 设置需要请求的权限
*/
String[] getPermissions();
/**
* 请求权限成功回调
*/
void requestPermissionsSuccess();
/**
* 请求权限失败回调
*/
void requestPermissionsFail();
}
...
3.工具类PermissionUtil.java
...
/**
* 动态权限工具类
* Created by dway on 2017/1/13.
*/
public class PermissionUtil {
/**
* 判断是否有某个权限
* @param context
* @param permission
* @return
*/
public static boolean hasPermission(Context context, String permission){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
/**
* 弹出对话框请求权限
* @param activity
* @param permissions
* @param requestCode
*/
public static void requestPermissions(Activity activity, String[] permissions, int requestCode){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.requestPermissions(permissions, requestCode);
}
}
/**
* 返回缺失的权限
* @param context
* @param permissions
* @return 返回缺少的权限,null 意味着没有缺少权限
*/
public static String[] getDeniedPermissions(Context context, String[] permissions){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> deniedPermissionList = new ArrayList<>();
for(String permission : permissions){
if(context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){
deniedPermissionList.add(permission);
}
}
int size = deniedPermissionList.size();
if(size > 0){
return deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
}
}
return null;
}
}
...
4.权限操作帮助类PermissionHelper.java
...
package com.dway.permission;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
/**
* 动态权限帮助类
* Created by dway on 2018/1/10.
*/
public class PermissionHelper {
private Activity mActivity;
private PermissionInterface mPermissionInterface;
public PermissionHelper(@NonNull Activity activity, @NonNull PermissionInterface permissionInterface) {
mActivity = activity;
mPermissionInterface = permissionInterface;
}
/**
* 开始请求权限。
* 方法内部已经对Android M 或以上版本进行了判断,外部使用不再需要重复判断。
* 如果设备还不是M或以上版本,则也会回调到requestPermissionsSuccess方法。
*/
public void requestPermissions(){
String[] deniedPermissions = PermissionUtil.getDeniedPermissions(mActivity, mPermissionInterface.getPermissions());
if(deniedPermissions != null && deniedPermissions.length > 0){
PermissionUtil.requestPermissions(mActivity, deniedPermissions, mPermissionInterface.getPermissionsRequestCode());
}else{
mPermissionInterface.requestPermissionsSuccess();
}
}
/**
* 在Activity中的onRequestPermissionsResult中调用
* @param requestCode
* @param permissions
* @param grantResults
* @return true 代表对该requestCode感兴趣,并已经处理掉了。false 对该requestCode不感兴趣,不处理。
*/
public boolean requestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
if(requestCode == mPermissionInterface.getPermissionsRequestCode()){
boolean isAllGranted = true;//是否全部权限已授权
for(int result : grantResults){
if(result == PackageManager.PERMISSION_DENIED){
isAllGranted = false;
break;
}
}
if(isAllGranted){
//已全部授权
mPermissionInterface.requestPermissionsSuccess();
}else{
//权限有缺失
mPermissionInterface.requestPermissionsFail();
}
return true;
}
return false;
}
}
...
OK,完成。建议在主activity就把需要的权限一次性都申请了。
补充:
在进行适配方案筛选过程中,发现一个开源库相比较下,更加简单易用.推荐一下
Android权限适配的更优解决方案
网友评论