Android6.0权限适配

来源:互联网 发布:数据挖掘要求英语吗 编辑:程序博客网 时间:2024/05/16 09:09


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 PermissionsSYSTEM_ALERT_WINDOW 设置悬浮窗WRITE_SETTINGS 修改系统设置

看权限名就知道特殊权限危险权限更危险,特殊权限需要在manifest中申请并且通过发送Intent让用户在设置界面进行勾选.

特殊权限申请方式:

SYSTEM_ALERT_WINDOW

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
}
@Override
protected 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 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 );
}
@Override
protected 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);    }}

至此,权限的封装就结束了





0 0
原创粉丝点击