1. 程式人生 > >Android 跳轉應用許可權設定頁面 適配小米系統

Android 跳轉應用許可權設定頁面 適配小米系統

跳轉應用設定頁面方便使用者修改已拒絕的許可權,是經常遇到的需求,但是MIUI 8 系統上測試發現有坑,寫一篇文章記錄一下。

通常的跳轉應用設定頁面方法

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, CODE_REQUEST);

就是通過系統封裝的隱式意圖直接開啟設定頁面的詳情而已,intent 中提供了包名告訴系統需要調取哪個應用的資訊。別忘了通過 startActivityForResult

方式開啟,畢竟從設定頁面返回之後你還要重走一遍許可權檢查和後續方法是吧。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CODE_REQUEST) {
        //TODO something;
    }
}

Settings 這個類中封裝了很多有用的系統屬性,看一下 Settings.ACTION_APPLICATION_DETAILS_SETTINGS

這一條的註釋:

/**
     * Activity Action: Show screen of details about a particular application.
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * <p>
     * Input: The Intent's data URI specifies the application package name
     * to be shown, with the "package" scheme.  That is "package:com.my.app".
     * <p>
     * Output: Nothing.
     */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";

MIUI 8 系統上遇到的問題

場景是這樣的,我需要請求的是開啟照相機許可權,模擬檢測到使用者禁用該許可權後提示去系統設定頁面開啟許可權的情況。

在系統許可權設定頁授予許可權後回撥可以檢測到許可權已獲取,但是小米 MIX 的測試機開啟照相機後是黑屏,並提示我許可權被禁用,需要在安全中心開啟。

原來小米系統在安全中心另外做了一套許可權管理頁面,並且直接無視了 Android 本身的許可權設定頁面的操作結果。明目張膽的架空啊。但是使用者是不管的,所以我們在 MIUI 系統上就只能提示使用者去安全中心的許可權管理頁面進行修改了。

上程式碼:

public static void settingPermissionActivity(Activity activity) {
    //判斷是否為小米系統
    if (TextUtils.equals(BrandUtils.getSystemInfo().getOs(), BrandUtils.SYS_MIUI)) {
        Intent miuiIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        miuiIntent.putExtra("extra_pkgname", activity.getPackageName());
        //檢測是否有能接受該Intent的Activity存在
        List<ResolveInfo> resolveInfos = activity.getPackageManager().queryIntentActivities(miuiIntent, PackageManager.MATCH_DEFAULT_ONLY);
        if (resolveInfos.size() > 0) {
            activity.startActivityForResult(miuiIntent, CODE_REQUEST_CAMERA_PERMISSIONS);
            return;
        }
    }
    //如果不是小米系統 則開啟Android系統的應用設定頁
    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
    intent.setData(uri);
    activity.startActivityForResult(intent, CODE_REQUEST_CAMERA_PERMISSIONS);
}

判斷系統的程式碼如下:


/**
 * Created by Yomii on 2017/4/12.
 */

public class BrandUtils {

    public static final String SYS_EMUI = "sys_emui";
    public static final String SYS_MIUI = "sys_miui";
    public static final String SYS_FLYME = "sys_flyme";
    private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
    private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
    private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
    private static final String KEY_EMUI_API_LEVEL = "ro.build.hw_emui_api_level";
    private static final String KEY_EMUI_VERSION = "ro.build.version.emui";
    private static final String KEY_EMUI_CONFIG_HW_SYS_VERSION = "ro.confg.hw_systemversion";

    private static SystemInfo systemInfoInstance;

    public static SystemInfo getSystemInfo() {
        if (systemInfoInstance == null) {
            synchronized (BrandUtils.class) {
                if (systemInfoInstance == null) {
                    systemInfoInstance = new SystemInfo();
                    getSystem(systemInfoInstance);
                }
            }
        }
        return systemInfoInstance;
    }

    private static void getSystem(SystemInfo info) {
        try {
            Properties prop = new Properties();
            prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
            if (prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null
                    || prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null
                    || prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null) {
                info.os = SYS_MIUI;//小米
                info.versionCode = Integer.valueOf(prop.getProperty(KEY_MIUI_VERSION_CODE, "0"));
                info.versionName = prop.getProperty(KEY_MIUI_VERSION_NAME, "V0");
            } else if (prop.getProperty(KEY_EMUI_API_LEVEL, null) != null
                    || prop.getProperty(KEY_EMUI_VERSION, null) != null
                    || prop.getProperty(KEY_EMUI_CONFIG_HW_SYS_VERSION, null) != null) {
                info.os = SYS_EMUI;//華為
                info.versionCode = Integer.valueOf(prop.getProperty(KEY_EMUI_API_LEVEL, "0"));
                info.versionName = prop.getProperty(KEY_EMUI_VERSION, "unknown");
            } else if (getMeizuFlymeOSFlag().toLowerCase().contains("flyme")) {
                info.os = SYS_FLYME;//魅族
                info.versionCode = 0;
                info.versionName = "unknown";
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String getMeizuFlymeOSFlag() {
        return getSystemProperty("ro.build.display.id", "");
    }

    private static String getSystemProperty(String key, String defaultValue) {
        try {
            Class<?> clz = Class.forName("android.os.SystemProperties");
            Method get = clz.getMethod("get", String.class, String.class);
            return (String) get.invoke(clz, key, defaultValue);
        } catch (Exception e) {
        }
        return defaultValue;
    }

    public static class SystemInfo {
        private String os = "android";
        private String versionName = Build.VERSION.RELEASE;
        private int versionCode = Build.VERSION.SDK_INT;

        public String getOs() {
            return os;
        }

        public String getVersionName() {
            return versionName;
        }

        public int getVersionCode() {
            return versionCode;
        }

        @Override
        public String toString() {
            return "SystemInfo{" +
                    "os='" + os + '\'' +
                    ", versionName='" + versionName + '\'' +
                    ", versionCode=" + versionCode +
                    '}';
        }
    }
}