Android 6.0 动态权限

来源:互联网 发布:2017淘宝查的太严了吧 编辑:程序博客网 时间:2024/05/19 23:01

参考文档:
https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-runtime-permissions
http://blog.csdn.net/caroline_wendy/article/details/50587230

Android 6.0 (API level 23) 之前,android的权限系统一直是 安装时询问一次 ;一旦安装了,app可以在用户毫不知晓的情况下访问相应权限;这是极其危险的事情 。
因此,在Android 6.0 (API level 23 )权限进行了改版,采用动态授予的方式
应用在使用某项危险权限时,应用会弹出是否授予权限的弹窗,供用户选择是否授予。

本案例GitHub 工程地址:
https://github.com/xiaxveliang/Android_PERMISSION_6.0_DEMO

一、使用动态权限

在应用的 build.gradle 中将 targetSdkVersion 设置为 23。应用运行时,对于危险权限的获取,将会采用动态授予的方式。
事例代码如下:

apply plugin: 'com.android.application'android {    compileSdkVersion 23    buildToolsVersion "23.0.1"    defaultConfig {        applicationId "com.permission.test"        minSdkVersion 14        targetSdkVersion 23        versionCode 1        versionName "1.0"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    compile 'com.android.support:appcompat-v7:23.3.0'}

注:
targetSdkVersion设置为22或者更低,应用也可在Android6.0 的手机上面运行,使用的权限机制则为6.0之前的 安装时请求 的模式。

二、普通权限、危险权限

目前所有的危险权限组集合

<!-- 联系人 --><uses-permission android:name="android.permission.WRITE_CONTACTS" /><uses-permission android:name="android.permission.GET_ACCOUNTS" /><uses-permission android:name="android.permission.READ_CONTACTS" /><!-- 录音 --><uses-permission android:name="android.permission.RECORD_AUDIO" /><!-- 电话 --><uses-permission android:name="android.permission.READ_CALL_LOG" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.CALL_PHONE" /><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" /><uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" /><!-- 日历 --><uses-permission android:name="android.permission.READ_CALENDAR" /><uses-permission android:name="android.permission.WRITE_CALENDAR" /><!-- 相机 --><uses-permission android:name="android.permission.CAMERA" /><!-- 传感器 --><uses-permission android:name="android.permission.BODY_SENSORS" /><!-- 定位 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><!-- 存储 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!-- 短信 --><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" /><uses-permission android:name="android.permission.RECEIVE_SMS" /><uses-permission android:name="android.permission.SEND_SMS" />

对应的java code

// 联系人Manifest.permission.WRITE_CONTACTS,Manifest.permission.GET_ACCOUNTS,Manifest.permission.READ_CONTACTS,// 电话Manifest.permission.READ_CALL_LOG,Manifest.permission.READ_PHONE_STATE,Manifest.permission.CALL_PHONE,Manifest.permission.WRITE_CALL_LOG,Manifest.permission.USE_SIP,Manifest.permission.PROCESS_OUTGOING_CALLS,Manifest.permission.ADD_VOICEMAIL,// 日历Manifest.permission.READ_CALENDAR,Manifest.permission.WRITE_CALENDAR,// 相机Manifest.permission.CAMERA,// 传感器Manifest.permission.BODY_SENSORS,// 定位Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION,// 存储Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE,// 录音Manifest.permission.RECORD_AUDIO,// 短信Manifest.permission.READ_SMS,Manifest.permission.RECEIVE_WAP_PUSH,Manifest.permission.RECEIVE_MMS,Manifest.permission.RECEIVE_SMS,Manifest.permission.SEND_SMS,

注:
Normal permissions(普通权限)只需要在AndroidManifest.xml中申请就可以了,与android 6.0之前没什么区别

三、动态权限获取流程

在Api 23中,权限需要动态获取,流程如下:
这里写图片描述
如果用户点击,不再提示,则系统授权弹窗将不会弹出。 流程变为:
这里写图片描述

三、效果

这里写图片描述
这里写图片描述

四、检查权限的工具类PermissionsUtils

/*** 检查权限的工具类*/public class PermissionsUtils {    // 系统权限管理页面的参数    public static final int PERMISSION_REQUEST_CODE = 0;    /**    * @param activity    * @param permissions    * @return true 集合中的权限已全部被授予;false 权限未被授予    */    public static boolean checkPermissions(Activity activity, String... permissions) {        // 版本兼容(6.0以上)        if (Build.VERSION.SDK_INT >= 23                // 判断哪些权限未被授予                && lacksPermissions(activity, permissions)) {            // 请求权限            requestPermissions(activity, permissions);            return false;        }        return true;    }    /**    * @param grantResults 请求权限的返回结果    * @return true 集合中的权限已全部被授予;false 权限未被授予    */    public static boolean checkGrantStatus(@NonNull int[] grantResults) {        for (int grantResult : grantResults) {            if (grantResult == PackageManager.PERMISSION_DENIED) {                return false;            }        }        return true;    }    /**    * 集合中,只要有未被授予的权限,则返回true    *    * @param context    * @param permissions    * @return true 权限未被授予,返回true    */    private static boolean lacksPermissions(Context context, String... permissions) {        for (String permission : permissions) {            if (lacksPermission(context, permission)) {                return true;            }        }        return false;    }    /**    * 指定的权限是否被授予    *    * @param context    * @param permission    * @return 权限未被授予,返回true    */    private static boolean lacksPermission(Context context, String permission) {        return ContextCompat.checkSelfPermission(context, permission) ==                PackageManager.PERMISSION_DENIED;    }    /**    * 请求权限    *    * @param activity    * @param permissions    */    public static void requestPermissions(Activity activity, String... permissions) {        ActivityCompat.requestPermissions(activity, permissions, PERMISSION_REQUEST_CODE);    }    /**    * 启动应用的设置,进入手动配置权限页面    */    public static void startAppSettings(Context context) {        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);        Uri uri = Uri.fromParts("package", context.getPackageName(), null);        intent.setData(uri);        context.startActivity(intent);    }}

五、PermissionsActivity

/*** 权限获取页面*/public class PermissionsActivity extends Activity {    private static final String TAG = PermissionsActivity.class.getSimpleName();    /**    * 要请求的所有权限    */    private static final String[] PERMISSIONS = new String[]{            // 危险权限:录音            Manifest.permission.RECORD_AUDIO,            // 普通权限:允许应用程序修改全局声音设置的权限            Manifest.permission.MODIFY_AUDIO_SETTINGS    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        LogUtils.d(TAG, "---onCreate---");        //        setContentView(R.layout.activity_permissions);        // 检查权限        PermissionsUtils.checkPermissions(PermissionsActivity.this, PERMISSIONS);    }    /**    * 用户权限处理,    * 如果全部获取, 则直接过.    * 如果权限缺失, 则提示Dialog.    *    * @param requestCode  请求码    * @param permissions  权限    * @param grantResults 结果    */    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        LogUtils.d(TAG, "---onRequestPermissionsResult---");        // 权限相关        if (requestCode == PermissionsUtils.PERMISSION_REQUEST_CODE) {            //            if (PermissionsUtils.checkGrantStatus(grantResults)) {                LogUtils.d(TAG, "---权限授予---");                // TODO 权限全部被授予            } else {                // TODO 权限未被授予                LogUtils.d(TAG, "---权限拒绝---");                showMissingPermissionDialog();            }        }    }    /**    * 显示缺失权限提示    */    private void showMissingPermissionDialog() {        //        android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(PermissionsActivity.this);        builder.setMessage(R.string.string_help_text);        builder.setTitle(R.string.help);        builder.setCancelable(false);        builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                dialog.dismiss();                //  引导,进入设置                PermissionsUtils.startAppSettings(PermissionsActivity.this);            }        });        builder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                dialog.dismiss();                // 关闭 当前页面...                PermissionsActivity.this.finish();            }        });        Dialog dialog = builder.create();        dialog.show();    }}
0 0