您的位置:首页 > 移动开发 > Android开发

Android6.0权限适配

2017-03-14 16:19 260 查看
Google在Android 6.0 上开始原生支持应用权限管理,再不是安装应用时的一刀切,很多权限需要在需要时实时请求,如果你的应用还没有做好6.0以上权限的适配,那么需要先限制targetSdkVersion在22及以下

当你做好处理, 就可以设置到22以上了,那么需要做哪些处理呢,首先我们得知道,哪些权限需要实时请求

Android的权限分为三类:
普通权限(Normal Permissions)
危险权限(Dangerous Permissions)
特殊权限(Special Permissions)
普通权限

普通权限不会对用户的隐私和安全产生太大的风险,所以只需要在AndroidManifest.xml中声明即可.

危险权限

权限组权限
android.permission-group.CALENDAR(日历数据)
android.permission.READ_CALENDAR


android.permission.WRITE_CALENDAR

android.permission-group.CAMERA(相机)
android.permission.CAMERA

android.permission-group.CONTACTS(联系人)
android.permission.READ_CONTACTS


android.permission.WRITE_CONTACTS


android.permission.GET_ACCOUNTS

android.permission-group.LOCATION(位置)
android.permission.ACCESS_FINE_LOCATION


android.permission.ACCESS_COARSE_LOCATION

android.permission-group.MICROPHONE(麦克风)
android.permission.RECORD_AUDIO

android.permission-group.PHONE(电话)
android.permission.READ_PHONE_STATE


android.permission.CALL_PHONE


android.permission.READ_CALL_LOG


android.permission.WRITE_CALL_LOG


com.android.voicemail.permission.ADD_VOICEMAIL


android.permission.USE_SIP


android.permission.PROCESS_OUTGOING_CALLS

android.permission-group.SENSORS(传感器)
android.permission.BODY_SENSORS

android.permission-group.SMS(短信)
android.permission.SEND_SMS


android.permission.RECEIVE_SMS


android.permission.READ_SMS


android.permission.RECEIVE_WAP_PUSH


android.permission.RECEIVE_MMS


android.permission.READ_CELL_BROADCASTS

android.permission-group.STORAGE(存储)
android.permission.READ_EXTERNAL_STORAGE


android.permission.WRITE_EXTERNAL_STORAGE

获取分组中某个权限的同时也就获取了同组中的其他权限。

比如,在应用中申请
READ_EXTERNAL_STORAGE
权限,用户同意授权后,则应用同时具有
READ_EXTERNAL_STORAGE
 和 
WRITE_EXTERNAL_STORAGE
 权限

切记,危险权限除了需要动态申请,也还是需要在Manifest中声明的

特殊权限

Special Permissions
SYSTEM_ALERT_WINDOW 设置悬浮窗
WRITE_SETTINGS 修改系统设置
看权限名就知道特殊权限比危险权限更危险,
特殊权限
需要在manifest中申请并且通过发送Intent让用户在设置界面进行勾选.

特殊权限申请方式:

SYSTEM_ALERT_WINDOW

12345678910111213141516
private static final int REQUEST_CODE = 1;private  void requestAlertWindowPermission() {    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);    intent.setData(Uri.parse("package:" + getPackageName()));    startActivityForResult(intent, REQUEST_CODE);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (requestCode == REQUEST_CODE) {        if (Settings.canDrawOverlays(this)) {            Log.i(LOGTAG, "onActivityResult granted");        }    }}
WRITE_SETTINGS 

12345678910111213141516
private static final int REQUEST_CODE_WRITE_SETTINGS = 2;private void requestWriteSettings() {    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);    intent.setData(Uri.parse("package:" + getPackageName()));    startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (requestCode == REQUEST_CODE_WRITE_SETTINGS) {        if (Settings.System.canWrite(this)) {            Log.i(LOGTAG, "onActivityResult write settings granted" );        }    }}
如果永远不将targetSdkVersion设置到22以上是不是就没事了?错,如果用户去权限中心禁用了(当然一般用户不会去这么做),他会让你运行到对应代码时直接崩溃
更何况有很多手机会在应用运行时一个个权限弹出来帮你申请,用户手一滑或者无法理解时一禁用,你就杯具了,所以还是得处理

如何开始动态申请权限
首先我们得知道有哪些方法
ContextCompat.checkSelfPermission(Context context,String permission) //判断权限是否具有某项权限
ActivityCompat.requestPermissions(Activity
activity,String[] permissions,int requestCode)//申请权限

onRequestPermissionsResult(int
requestCode, String[] permissions, int[] grantResults)//申请权限回调方法,在Activity或Fragment重写

ActivityCompat.shouldShowRequestPermissionRationale(Activity
activity, String permission)//是否要提示用户申请该权限的缘由

有了这几个方法之后,我们需要整理一下我们对权限申请的流程是个什么样子的安排



你说请求权限时的不再提示是否要处理?不用了,用户第一次拒绝了之后就可以给用户提示了,为什么要等第二次
那么流程有了之后就是代码了
首先是对权限检查以及申请的工具类
PermissionUtil

/**
* Created by yangjh on 2017/3/10.
* 这个类用于6.0以上权限的处理
*/

public class PermissionUtil {

private final String TAG = "PermissionUtil";
private int REQUEST_CODE_PERMISSION = 0x00099;

/**
* 请求权限
*
* @param permissions 请求的权限
* @param requestCode 请求权限的请求码
*/
public boolean requestPermission(String[] permissions, int requestCode,Activity activity) {
this.REQUEST_CODE_PERMISSION = requestCode;
//检查是否具有一些权限
if (checkPermissions(permissions,activity)) {
permissionSuccess(REQUEST_CODE_PERMISSION);
return true;
} else {//发现有权限未申请到,则准备发出申请
//获取未申请到的权限列表
List<String> needPermissions = getDeniedPermissions(permissions,activity);
//发出权限申请
ActivityCompat.requestPermissions(activity, needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION);
return false;
}
}

/**
* 系统请求权限回调,返回TRUE表示权限都通过了不需要处理
* 返回FALSE表示有未通过的需要提示处理
*
* @param requestCode
* @param permissions
* @param grantResults
*/
public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE_PERMISSION) {
//确认所有权限是否都已授权
if (verifyPermissions(grantResults)) {
permissionSuccess(REQUEST_CODE_PERMISSION);
return true;
} else {//发现有没有授权的
permissionFail(REQUEST_CODE_PERMISSION);
// showTipsDialog();
return false;
}
}
return true;
}

/**
* 检测所有的权限是否都已授权
*
* @param permissions
* @return
*/
private boolean checkPermissions(String[] permissions,Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(activity, permission) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

/**
* 确认所有的权限是否都已授权
*
* @param grantResults
* @return
*/
private boolean verifyPermissions(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

/**
* 获取需要申请权限的列表
*
* @param permissions
* @return
*/
private List<String> getDeniedPermissions(String[] permissions,Activity activity) {
List<String> needRequestPermissionList = new ArrayList<>();
for (String permission : permissions) {
//发现这条权限没有获取到权限,或者系统认为需要提示用户申请该权限的缘由时
if (ContextCompat.checkSelfPermission(activity, permission) !=
PackageManager.PERMISSION_GRANTED ||
ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
//添加需要提示的权限进集合
needRequestPermissionList.add(permission);
}
}
return needRequestPermissionList;
}

/**
* 获取权限成功
*
* @param requestCode
*/
public void permissionSuccess(int requestCode) {
Log.d(TAG, "获取权限成功=" + requestCode);
}

/**
* 权限获取失败
* @param requestCode
*/
public void permissionFail(int requestCode) {
Log.d(TAG, "获取权限失败=" + requestCode);
}

}

然后是对权限申请的逻辑的组织类:
PermissionApply

/**
* Created by yangjh on 2017/3/10.
* 权限申请的入口类,负责申请对应的权限以及权限申请成功时候后的处理
* 这里有一种情况目前没有处理,就是比如:
* 先申请电话权限,然后在还没得到结果时又申请SD卡权限,此时会导致检查权限申请状况时,电话权限检查不到,所以不要这样申请
*/
public class PermissionApply {

private PermissionUtil permissionUtil;
private Activity mActivity;
HashMap<Integer,OnPermissResponse> permissionResponses = new HashMap<Integer,OnPermissResponse>();

public PermissionApply(Activity activity){
mActivity = activity;
permissionUtil = new PermissionUtil();
}

/**
* 请求电话权限
*/
public void requestPhonePermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_CALL_PHONE,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_CALL_PHONE}, REQUEST_CALL_PHONE,mActivity)){
callBack(REQUEST_CALL_PHONE);
}
}

/**
* 请求SD卡权限
*/
public void requestSDCardPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_WRITE_EXTERNAL_STORAGE,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE,mActivity)){
callBack(REQUEST_WRITE_EXTERNAL_STORAGE);
}
}

/**
* 请求相机权限
*/
public void requestCameraPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_CAMERA,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_CAMERA}, REQUEST_CAMERA,mActivity)){
callBack(REQUEST_CAMERA);
}
}

/**
* 请求联系人权限
*/
public void requestContactsPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_CONTACTS,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_CONTACTS}, REQUEST_CONTACTS,mActivity)){
callBack(REQUEST_CONTACTS);
}
}

/**
* 请求日历权限
*/
public void requestCalendarPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_CALENDAR,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_CALENDAR}, REQUEST_CALENDAR,mActivity)){
callBack(REQUEST_CALENDAR);
}
}

/**
* 请求地理(GPS)权限
*/
public void requestLocationPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_LOCATION,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_LOCATION}, REQUEST_LOCATION,mActivity)){
callBack(REQUEST_LOCATION);
}
}

/**
* 请求麦克风权限
*/
public void requestMicrophonePermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_MICROPHONE,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_MICROPHONE}, REQUEST_MICROPHONE,mActivity)){
callBack(REQUEST_MICROPHONE);
}
}

/**
* 请求传感器权限
*/
public void requestSensorsPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_SENSORS,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_SENSORS}, REQUEST_SENSORS,mActivity)){
callBack(REQUEST_SENSORS);
}
}

/**
* 请求短信权限
*/
public void requestSmsPermission(OnPermissResponse permissionRes){
permissionResponses.put(REQUEST_SMS,permissionRes);
if(permissionUtil.requestPermission(new String[]{PERMISSION_SMS}, REQUEST_SMS,mActivity)){
callBack(REQUEST_SMS);
}
}

/**
* 接收权限请求的结果
* @param requestCode
* @param permissions
* @param grantResults
*/
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
boolean success = permissionUtil.onRequestPermissionsResult(requestCode,permissions,grantResults);
if(!success){//没有成功就打开设置页面
showTipsDialog();
}else{
callBack(requestCode);
}
}

private void callBack(int requestCode){
OnPermissResponse response = permissionResponses.get(requestCode);
if(null != response){
response.onPermissionSuccess();
}
}

/**
* 显示提示对话框
*/
private void showTipsDialog() {
new AlertDialog.Builder(mActivity)
.setTitle("提示信息")
.setMessage("当前应用缺少必要权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
}).show();
}

/**
* 启动当前应用设置页面
*/
private void startAppSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + mActivity.getPackageName()));
mActivity.startActivity(intent);
}

public interface OnPermissResponse{
public abstract void onPermissionSuccess();
}

//请求电话方面的权限
private static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE;
private static final int REQUEST_CALL_PHONE = 0x0001;

//SD卡读取写入权限
private static final String PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
private static final int REQUEST_WRITE_EXTERNAL_STORAGE = 0x0002;

//相机
private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
private static final int REQUEST_CAMERA = 0x0003;

//读取联系人
private static final String PERMISSION_CONTACTS = Manifest.permission.READ_CONTACTS;
private static final int REQUEST_CONTACTS = 0x0004;

//日历
private static final String PERMISSION_CALENDAR = Manifest.permission.READ_CALENDAR;
private static final int REQUEST_CALENDAR = 0x0005;

//GPS
private static final String PERMISSION_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private static final int REQUEST_LOCATION = 0x0006;

//麦克风
private static final String PERMISSION_MICROPHONE = Manifest.permission.RECORD_AUDIO;
private static final int REQUEST_MICROPHONE = 0x0007;

//传感器
private static final String PERMISSION_SENSORS = Manifest.permission.BODY_SENSORS;
private static final int REQUEST_SENSORS = 0x0008;

//短信
private static final String PERMISSION_SMS = Manifest.permission.READ_SMS;
private static final int REQUEST_SMS = 0x0009;

}

这两个类就足够了,然后是调用的示例:
/**
* Created by yangjh on 2017/3/9.
*/

public class ActivityS extends Activity {

PermissionApply apply;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main2);
apply = new PermissionApply(this);
ImageView img1 = (ImageView)findViewById(R.id.img1);
img1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
apply.requestPhonePermission(new PermissionApply.OnPermissResponse() {
@Override
public void onPermissionSuccess() {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:10086"));
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(callIntent);
}
});
}
});
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
apply.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}

至此,权限的封装就结束了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: