经查,android6.0授予权限的过程有所变化。引入了一个新的应用权限模型,期望对用户更容易理解,更易用和更安全。该模型将标记为危险的权限从安装时权限(Install Time Permission)模型 移动到 运行时权限模型(Runtime Permissions)。
查询受影响的权限:adb shell pm list permissions -g -d
- 安装时权限模型(Android5.1以及更早)。用户在应用安装和更新时,对危险权限授权。但是OEM和运行商预装的应用将自动预授权。
- 运行时权限(Android6.0及以后)。用户在应用运行时,对应用授予危险权限。由应用决定何时去申请权限(例如,在应用启动时或者用户访问某个特性时),但必须容许用户来授予或者拒绝应用对特定权限组的访问。OEM和运营商 可以预装应用,但是不能对权限进行预授权
运行时权限好处:
运行时权限提供给用户关于应用所需权限更多的相关上下文和可视性,这也让开发者帮助用户更好的理解:为什么应用需要所请求的权限,授权将有什么样的好处,拒绝将有何种不便。用户可以通过设置中的菜单来撤销应用的权限。
版本升级对于权限的影响:
在设备从Android5.x升级到Android6.0之后,授予应用的权限仍然有效。但是用户可以在任何时候撤销这些权限。
以下就是针对新版本权限模式做相应处理的方案
实现思路:
1.检测权限是否授予。如果已授予,继续执行原有程序;
2.如果未授予,需要手动调用系统的权限弹框,再接收用户在系统弹框中选择的‘允许’或‘不允许’的结果来处理;
以下是封装的检测权限的部分代码,仅供参考。
这是公共的检测权限的工具类,可供项目中任何一个activity页面使用
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import java.util.ArrayList;
import java.util.List;
/**
* 检查权限
* Created by x2 on 16/11/24.
*/
public class CheckPermission {
/** 自定义相机页面请求获取权限的标识*/
public static final int REQUEST_CUSTOM_CAMERA_CODE = 101;
/**
* 检查某项权限
* @param context 上下文
* @param activity 页面
* @param mftPermission 权限数组(例如{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE})
* @param REQUEST_CODE 请求授予权限的请求标识
*/
public static boolean check(Context context, Activity activity, String[] mftPermission, final int REQUEST_CODE) {
boolean isGranted = true;
if(Build.VERSION.SDK_INT >= 23) {
//所有未获取的权限数据
List<String> notGrantedList = new ArrayList<>();
//获取系统是否授予该种权限
for(String permission : mftPermission) {
int checkPermission = ContextCompat.checkSelfPermission(context, permission);
if(checkPermission != PackageManager.PERMISSION_GRANTED) {
notGrantedList.add(permission);
}
}
//如果没有被授予
if(notGrantedList.size() > 0) {
isGranted = false;
String notGrantedStr[] = new String[notGrantedList.size()];
for(int i = 0; i < notGrantedList.size(); i ++) {
notGrantedStr[i] = notGrantedList.get(i);
}
//请求获取权限
ActivityCompat.requestPermissions(activity, notGrantedStr, REQUEST_CODE);
}
}
return isGranted;
}
}
以下是处理‘获取权限授予结果’的方法,要在请求权限的activity类中实现
/**
* 请求权限后的接收函数
* @param requestCode 请求标识
* @param permissions 权限
* @param grantResults 结果
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case CheckPermission.REQUEST_CUSTOM_CAMERA_CODE:
boolean isGranted = true;
for(int result : grantResults) {
if(result != PackageManager.PERMISSION_GRANTED) isGranted = false;
}
if(isGranted) {
//继续执行原有程序,例如跳转到某个页面
Intent intent = new Intent(context, CustomCameraActivity.class);
startActivity(intent);
} else {
Toast.makeText(context, "获取权限失败,请尝试手动开启权限后再试.", Toast.LENGTH_LONG).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
这样就完成了对于6.0系统权限的特殊处理,其实里面还有一些坑,待大家去填,比如某些权限不能在使用它的页面再请求获取等。