Android 6.0动态权限及小米(MIUI)权限的特殊处理

来源:互联网 发布:阿里云域名备案多少钱 编辑:程序博客网 时间:2024/06/05 20:09

      • 前言
      • 常规操作权限的页面及流程
      • 权限说明
      • 权限授取流程
      • 小米权限特殊处理
      • 各个android操作系统跳转到设置页面的公共方法
      • 总结

前言

从android6.0之后,android对用户的权限进行相对教严格的管控,针对重要的权限,用户在第一安装并使用的时候,系统以弹框的形式向用户获取,用户的权限授取直接关乎着应用是否能正常使用对应的功能;因此这里对android 6.0之后的动态权限获取进行整理并记录备忘;由于国内的android系统各大手机厂商都有所定制;对于6.0之后权限,小米系统是存在2个地方的权限授取,必须2个地方都启动,才能正常使用;因此带来了一些不必要的坑;这里一起进行整理记录

不多说,先上代码及效果图

  • 源码
    源码下载

  • 效果图

    • 允许授权
    • 二次授权

常规操作权限的页面及流程

为了不影响用户的正使用,我们一般都会在应用的启动页对该应用所用到的所有权限进行授权;避免用户在使用过程中还存在权限授取的动作,具体流程如下:

  • 用户第一次使用并允许授权的流程

  • 如果用户第一次使用的时候,取消了部分关键授权,直接影响到app的使用的二次授权流程

  • 如果用户第一次使用的时候,取消了部分关键授权,针对小米MIUI5以上的系统的授权流程

权限说明

  • 普通权限
    直接在AndroidManifest.xml中获取即可

    • ACCESS_LOCATION_EXTRA_COMMANDS
    • ACCESS_NETWORK_STATE
    • ACCESS_NOTIFICATION_POLICY
    • ACCESS_WIFI_STATE
    • BLUETOOTH
    • BLUETOOTH_ADMIN
    • BROADCAST_STICKY
    • CHANGE_NETWORK_STATE
    • CHANGE_WIFI_MULTICAST_STATE
    • CHANGE_WIFI_STATE
    • DISABLE_KEYGUARD
    • EXPAND_STATUS_BAR
    • GET_PACKAGE_SIZE
    • INSTALL_SHORTCUT
    • INTERNET
    • KILL_BACKGROUND_PROCESSES
    • MODIFY_AUDIO_SETTINGS
    • NFC
    • READ_SYNC_SETTINGS
    • READ_SYNC_STATS
    • RECEIVE_BOOT_COMPLETED
    • REORDER_TASKS
    • REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
    • REQUEST_INSTALL_PACKAGES
    • SET_ALARM
    • SET_TIME_ZONE
    • SET_WALLPAPER
    • SET_WALLPAPER_HINTS
    • TRANSMIT_IR
    • UNINSTALL_SHORTCUT
    • USE_FINGERPRINT
    • VIBRATE
    • WAKE_LOCK
    • WRITE_SYNC_SETTINGS
  • 危险权限,需要动态申请的权限

权限授取流程

  • 检测是否是6.0以上的系统
    Build.VERSION.SDK_INT >= 23
  • 检测权限是否开启

       /**     * 检测权限     *     * @return true 所需权限全部授取  false 存在未授权的权限     */    public boolean isAllGranted() {        /**         * 第 1 步: 检查是否有相应的权限         */        boolean isAllGranted = checkPermissionAllGranted(                new String[]{                        Manifest.permission.READ_PHONE_STATE,                        Manifest.permission.ACCESS_COARSE_LOCATION,                        Manifest.permission.ACCESS_FINE_LOCATION,                        Manifest.permission.CAMERA,                        Manifest.permission.READ_EXTERNAL_STORAGE,                        Manifest.permission.WRITE_EXTERNAL_STORAGE                }        );        return isAllGranted;    }        /**     * 检查是否拥有指定的所有权限     */    private boolean checkPermissionAllGranted(String[] permissions) {        for (String permission : permissions) {            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {                // 只要有一个权限没有被授予, 则直接返回 false                return false;            }        }        return true;    }
  • 授权多个权限

    // 一次请求多个权限, 如果其他有权限是已经授予的将会自动忽略掉ActivityCompat.requestPermissions(    this,    new String[]{        Manifest.permission.READ_PHONE_STATE,        Manifest.permission.ACCESS_COARSE_LOCATION,        Manifest.permission.ACCESS_FINE_LOCATION,        Manifest.permission.CAMERA,        Manifest.permission.READ_EXTERNAL_STORAGE,        Manifest.permission.WRITE_EXTERNAL_STORAGE        },        MY_PERMISSION_REQUEST_CODE    );
  • 所有权限授取之后的回调

        @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        if (requestCode == MY_PERMISSION_REQUEST_CODE) {            boolean isAllGranted = true;            // 判断是否所有的权限都已经授予了            for (int grant : grantResults) {                if (grant != PackageManager.PERMISSION_GRANTED) {                    isAllGranted = false;                    break;                }            }            if (isAllGranted) {                // 如果所有的权限都授予了, 跳转到主页                gotoHomeActivity();            } else {                // 弹出对话框告诉用户需要权限的原因, 并引导用户去应用权限管理中手动打开权限按钮                openAppDetails();            }        }    }

小米权限特殊处理

  • 判断是否是小米系统

        /**     * 检查手机是否是miui系统     *     * @return     */    public boolean isMIUI() {        String device = Build.MANUFACTURER;        System.out.println("Build.MANUFACTURER = " + device);        if (device.equals("Xiaomi")) {            System.out.println("this is a xiaomi device");            Properties prop = new Properties();            try {                prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));            } catch (IOException e) {                e.printStackTrace();                return false;            }            return prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null                    || prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null                    || prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null;        } else {            return false;        }    }
  • 判断授权管理界面中的权限授取
    这里需要注意的是需要对权限进行一个个的判断,无法像上面一样用个集合就进行判断了;具体应用需要那些这里就去判断那些就好了。

        /**     * 判断小米MIUI系统中授权管理中对应的权限授取     *     * @return false 存在核心的未收取的权限   true 核心权限已经全部授权     */    public boolean initMiuiPermission() {        AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);        int locationOp = appOpsManager.checkOp(AppOpsManager.OPSTR_FINE_LOCATION, Binder.getCallingUid(), getPackageName());        if (locationOp == AppOpsManager.MODE_IGNORED) {            return false;        }        int cameraOp = appOpsManager.checkOp(AppOpsManager.OPSTR_CAMERA, Binder.getCallingUid(), getPackageName());        if (cameraOp == AppOpsManager.MODE_IGNORED) {            return false;        }        int phoneStateOp = appOpsManager.checkOp(AppOpsManager.OPSTR_READ_PHONE_STATE, Binder.getCallingUid(), getPackageName());        if (phoneStateOp == AppOpsManager.MODE_IGNORED) {            return false;        }        int readSDOp = appOpsManager.checkOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, Binder.getCallingUid(), getPackageName());        if (readSDOp == AppOpsManager.MODE_IGNORED) {            return false;        }        int writeSDOp = appOpsManager.checkOp(AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE, Binder.getCallingUid(), getPackageName());        if (writeSDOp == AppOpsManager.MODE_IGNORED) {            return false;        }        return true;    }
  • MIUI不听版本,跳帧授权管理界面的方式不一样
    各个不同系统的设置界面跳转请参考博客末尾的帮助类,以下代码摘自其中。

        public static void Xiaomi(Activity activity) {        // 只兼容miui v5/v6 的应用权限设置页面,否则的话跳转应用设置页面(权限设置上一级页面)        String miuiVersion = getMiuiVersion();        Intent intent = null;        if ("V5".equals(miuiVersion)) {            Uri packageURI = Uri.parse("package:" + activity.getApplicationInfo().packageName);            intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);        } else if ("V6".equals(miuiVersion) || "V7".equals(miuiVersion)) {            intent = new Intent("miui.intent.action.APP_PERM_EDITOR");            intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");            intent.putExtra("extra_pkgname", activity.getPackageName());        } else if ("V8".equals(miuiVersion)) {            intent = new Intent("miui.intent.action.APP_PERM_EDITOR");            intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");            intent.putExtra("extra_pkgname", activity.getPackageName());        } else {        }        if (null != intent)            activity.startActivity(intent);    }
  • 小米系统测试效果
    • 初次允许授权
    • 二次授权

各个android操作系统跳转到设置页面的公共方法

以下代码为结合网友提供的再根据情况调整了一下小米相关的跳转

package com.lpf.permission;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.net.Uri;import android.os.Build;import android.provider.Settings;import android.support.v7.appcompat.BuildConfig;import android.util.Log;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;/** */public class JumpPermissionManagement {    /**     * Build.MANUFACTURER     */    private static final String MANUFACTURER_HUAWEI = "Huawei";//华为    private static final String MANUFACTURER_MEIZU = "Meizu";//魅族    private static final String MANUFACTURER_XIAOMI = "Xiaomi";//小米    private static final String MANUFACTURER_SONY = "Sony";//索尼    private static final String MANUFACTURER_OPPO = "OPPO";    private static final String MANUFACTURER_LG = "LG";    private static final String MANUFACTURER_VIVO = "vivo";    private static final String MANUFACTURER_SAMSUNG = "samsung";//三星    private static final String MANUFACTURER_LETV = "Letv";//乐视    private static final String MANUFACTURER_ZTE = "ZTE";//中兴    private static final String MANUFACTURER_YULONG = "YuLong";//酷派    private static final String MANUFACTURER_LENOVO = "LENOVO";//联想    /**     * 此函数可以自己定义     *     * @param activity     */    public static void GoToSetting(Activity activity) {        switch (Build.MANUFACTURER) {            case MANUFACTURER_HUAWEI:                Huawei(activity);                break;            case MANUFACTURER_MEIZU:                Meizu(activity);                break;            case MANUFACTURER_XIAOMI:                Xiaomi(activity);                break;            case MANUFACTURER_SONY:                Sony(activity);                break;            case MANUFACTURER_OPPO:                OPPO(activity);                break;            case MANUFACTURER_LG:                LG(activity);                break;            case MANUFACTURER_LETV:                Letv(activity);                break;            default:                ApplicationInfo(activity);                Log.e("goToSetting", "目前暂不支持此系统");                break;        }    }    public static void Huawei(Activity activity) {        Intent intent = new Intent();        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");        intent.setComponent(comp);        activity.startActivity(intent);    }    public static void Meizu(Activity activity) {        Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");        intent.addCategory(Intent.CATEGORY_DEFAULT);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        activity.startActivity(intent);    }    public static void Xiaomi(Activity activity) {        // 只兼容miui v5/v6 的应用权限设置页面,否则的话跳转应用设置页面(权限设置上一级页面)        String miuiVersion = getMiuiVersion();        Intent intent = null;        if ("V5".equals(miuiVersion)) {            Uri packageURI = Uri.parse("package:" + activity.getApplicationInfo().packageName);            intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);        } else if ("V6".equals(miuiVersion) || "V7".equals(miuiVersion)) {            intent = new Intent("miui.intent.action.APP_PERM_EDITOR");            intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");            intent.putExtra("extra_pkgname", activity.getPackageName());        } else if ("V8".equals(miuiVersion)) {            intent = new Intent("miui.intent.action.APP_PERM_EDITOR");            intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");            intent.putExtra("extra_pkgname", activity.getPackageName());        } else {        }        if (null != intent)            activity.startActivity(intent);    }    public static void Sony(Activity activity) {        Intent intent = new Intent();        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        ComponentName comp = new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity");        intent.setComponent(comp);        activity.startActivity(intent);    }    public static void OPPO(Activity activity) {        Intent intent = new Intent();        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        ComponentName comp = new ComponentName("com.color.safecenter", "com.color.safecenter.permission.PermissionManagerActivity");        intent.setComponent(comp);        activity.startActivity(intent);    }    public static void LG(Activity activity) {        Intent intent = new Intent("android.intent.action.MAIN");        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");        intent.setComponent(comp);        activity.startActivity(intent);    }    public static void Letv(Activity activity) {        Intent intent = new Intent();        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        ComponentName comp = new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps");        intent.setComponent(comp);        activity.startActivity(intent);    }    /**     * 只能打开到自带安全软件     *     * @param activity     */    public static void _360(Activity activity) {        Intent intent = new Intent("android.intent.action.MAIN");        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra("packageName", BuildConfig.APPLICATION_ID);        ComponentName comp = new ComponentName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");        intent.setComponent(comp);        activity.startActivity(intent);    }    /**     * 应用信息界面     *     * @param activity     */    public static void ApplicationInfo(Activity activity) {        Intent localIntent = new Intent();        localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        if (Build.VERSION.SDK_INT >= 9) {            localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");            localIntent.setData(Uri.fromParts("package", activity.getPackageName(), null));        } else if (Build.VERSION.SDK_INT <= 8) {            localIntent.setAction(Intent.ACTION_VIEW);            localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");            localIntent.putExtra("com.android.settings.ApplicationPkgName", activity.getPackageName());        }        activity.startActivity(localIntent);    }    /**     * 系统设置界面     *     * @param activity     */    public static void SystemConfig(Activity activity) {        Intent intent = new Intent(Settings.ACTION_SETTINGS);        activity.startActivity(intent);    }    public static String getMiuiVersion() {        String line;        BufferedReader input = null;        try {            Process p = Runtime.getRuntime().exec("getprop ro.miui.ui.version.name");            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);            line = input.readLine();            input.close();        } catch (IOException ex) {            return null;        } finally {            if (input != null) {                try {                    input.close();                } catch (IOException e) {                }            }        }        return line;    }}

总结

这里只找了部分的手机进行了测试;由于android市场的复杂性,可能存在不兼容的情况,主要的问题也应该是在授权设置哪里;可以根据特定的手机进行调整即可;
源码下载

阅读全文
0 0