美文网首页程序员
android 6.0以上版本动态权限处理

android 6.0以上版本动态权限处理

作者: flywfk | 来源:发表于2017-03-09 22:44 被阅读1015次

    目前搭载android6.0以上版本系统手机占有量将近三分之一,具体如下图所示:


    android各系统版本占有量

    所以有必要将升级app的targetSdkVersion,但从Android6.0 以上开始,系统引入了一个新的应用权限模型,运行时权限模型(Runtime Permissions)。

    运行时权限:用户在应用运行时,对应用授予危险权限。由应用决定何时去申请权限(例如,在应用打开摄像机时或访问通讯录时),但必须容许用户来授予或者拒绝应用对特定权限的访问。

    权限分为两种:

    • 正常权限:不涉及用户的隐私,不需要在运行时向其授权。主要是震动,蓝牙,访问网络等权限。 查看所有正常权限
    • 危险权限:涉及用户的隐私,需要在运行时向其授权。主要是使用相机,拨打电话,收发短信,获取位置信息,读写sd卡等权限。 查看所有危险权限及分组。系统将危险权限进行了分组,当用户对组内的某一个权限进行了授权,下次请求组内其他权限时系统会默认直接授予。

    目前在开发上最简单的做法就是将targetSdkVersion一直设置在23以下,这样的话就不需要考虑动态授权的问题,在AndroidManifest.xml中申请你需要的权限就可以了。

    我们现在处理targetSdkVersion = 23及以上的情况:

    1. 声明权限

    普通权限和危险权限都要在此声明。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxx.xxx.xxx">
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <application android:allowBackup="true"
    android:supportsRtl="true">
    </application>
    </manifest>

    2. 检查并请求权限

    /**
    * 检查权限,如果未授权,则请求
    *
    * @param activity
    * @param requestCode 请求码,例如:如果你需要请求打电话的权限,参数值就是Manifest.permission.CALL_PHONE
    */
    public static void requestPermission(final Activity activity, final int requestCode, PermissionGrant permissionGrant) {
    if (activity == null) {
    return;
    }
    if (requestCode < 0 || requestCode >= requestPermissions.length) {
    return;
    }
    final String requestPermission = requestPermissions[requestCode];
    //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,
    // 但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null),
    // 你可以使用try{}catch(){},处理异常,也可以判断系统版本,低于23就不申请权限,直接做你想做的。permissionGrant.onPermissionGranted(requestCode);
    if (Build.VERSION.SDK_INT < 23) {
    permissionGrant.onPermissionGranted(requestCode);
    return;
    }
    int checkSelfPermission;
    try {
    checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
    } catch (RuntimeException e) {
    Toast.makeText(activity, "please open this permission", Toast.LENGTH_SHORT)
    .show();
    return;
    }
    if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
    if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
    shouldShowRationale(activity, requestCode, requestPermission);
    } else {
    ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode);
    }
    } else {
    Toast.makeText(activity, "opened:" + requestPermissions[requestCode], Toast.LENGTH_SHORT).show();
    permissionGrant.onPermissionGranted(requestCode);
    }
    }

    3. 回调处理申请结果

    /**
    * @param activity
    * @param requestCode
    * @param permissions
    * @param grantResults
    */
    public static void requestPermissionsResult(final Activity activity, final int requestCode, @NonNull String[] permissions,
    @NonNull int[] grantResults, PermissionGrant permissionGrant) {
    if (activity == null) {
    return;
    }
    if (requestCode == CODE_MULTI_PERMISSION) {
    requestMultiResult(activity, permissions, grantResults, permissionGrant);
    return;
    }
    if (requestCode < 0 || requestCode >= requestPermissions.length) {
    Toast.makeText(activity, "illegal requestCode:" + requestCode, Toast.LENGTH_SHORT).show();
    return;
    }
    if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    permissionGrant.onPermissionGranted(requestCode);
    } else {
    String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions);
    openSettingActivity(activity, "Result" + permissionsHint[requestCode]);
    }
    }

    以上涉及到的一些函数方法,我在下面一并写出来:

    /**
    提示用户为什么要开启该权限
    * @param activity
    * @param requestCode
    * @param requestPermission
    /
    private static void shouldShowRationale(final Activity activity, final int requestCode, final String requestPermission) {
    String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions);
    showMessageOKCancel(activity, "Rationale: " + permissionsHint[requestCode], new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    ActivityCompat.requestPermissions(activity,
    new String[]{requestPermission},
    requestCode);
    }
    });
    }
    /

    * 提示框
    * @param context
    * @param message
    * @param okListener
    /
    private static void showMessageOKCancel(final Activity context, String message, DialogInterface.OnClickListener okListener) {
    new AlertDialog.Builder(context)
    .setMessage(message)
    .setPositiveButton("OK", okListener)
    .setNegativeButton("Cancel", null)
    .create()
    .show();
    }
    /
    *
    * 打开权限设置界面
    * @param activity
    * @param message
    /
    private static void openSettingActivity(final Activity activity, String message) {
    showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    Intent intent = new Intent();
    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
    intent.setData(uri);
    activity.startActivity(intent);
    }
    });
    }
    /
    *
    * 一次申请多个权限
    /
    public static void requestMultiPermissions(final Activity activity, PermissionGrant grant) {
    final List<String> permissionsList = getNoGrantedPermission(activity, false);
    final List<String> shouldRationalePermissionsList = getNoGrantedPermission(activity, true);
    if (permissionsList == null || shouldRationalePermissionsList == null) {
    return;
    }
    if (permissionsList.size() > 0) {
    ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]),
    CODE_MULTI_PERMISSION);
    } else if (shouldRationalePermissionsList.size() > 0) {
    showMessageOKCancel(activity, "should open those permission",
    new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    ActivityCompat.requestPermissions(activity, shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]),
    CODE_MULTI_PERMISSION);
    }
    });
    } else {
    grant.onPermissionGranted(CODE_MULTI_PERMISSION);
    }
    }
    /
    *
    * 一次请求多个权限结果回调
    * @param activity
    * @param permissions
    * @param grantResults
    * @param permissionGrant
    /
    private static void requestMultiResult(Activity activity, String[] permissions, int[] grantResults, PermissionGrant permissionGrant) {
    if (activity == null) {
    return;
    }
    Map<String, Integer> perms = new HashMap<>();
    ArrayList<String> notGranted = new ArrayList<>();
    for (int i = 0; i < permissions.length; i++) {
    perms.put(permissions[i], grantResults[i]);
    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
    notGranted.add(permissions[i]);
    }
    }
    if (notGranted.size() == 0) {
    Toast.makeText(activity, "all permission success" + notGranted, Toast.LENGTH_SHORT)
    .show();
    permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION);
    } else {
    openSettingActivity(activity, "those permission need granted!");
    }
    }
    /
    *
    * 授予权限接口回调
    */
    public interface PermissionGrant {
    void onPermissionGranted(int requestCode);
    }

    4. 在Activity或Fragment中调用

    /**
    *
    /btnCall.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    PermissionUtils.requestPermission(xxx.this, PermissionUtils.CODE_CALL_PHONE, mPermissionGrant);
    }
    });
    /
    *
    * 打电话
    /
    public void callPhone() {
    Intent intent = new Intent(Intent.ACTION_CALL);
    Uri data = Uri.parse("tel:" + "13918396199");
    intent.setData(data);
    startActivity(intent);
    }
    /
    *
    * Callback received when a permissions request has been completed.
    /
    private PermissionUtils.PermissionGrant mPermissionGrant = new PermissionUtils.PermissionGrant() {
    @Override
    public void onPermissionGranted(int requestCode) {
    switch (requestCode) {
    case PermissionUtils.CODE_CALL_PHONE:
    callPhone();
    break;
    default:
    break;
    }
    }
    };
    /
    *
    * Callback received when a permissions request has been completed.
    */
    @Override
    public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions,
    @NonNull int[] grantResults) {
    PermissionUtils.requestPermissionsResult(this, requestCode, permissions, grantResults, mPermissionGrant);
    }

    最后感谢Google提供的demo Google demo 下载地址

    相关文章

      网友评论

        本文标题:android 6.0以上版本动态权限处理

        本文链接:https://www.haomeiwen.com/subject/hgpwgttx.html