Android 跳转权限设置界面的终极适配(适配各大定制 ROM)

前言

在我们请求用户权限时,很有可能会被用户有意无意地点了拒绝,而这个权限恰恰又是当前操作所以必须的,所以一般我们都会希望用户能手动去打开权限,以便我们能顺利的执行业务逻辑。

那么问题来了,我们要怎么快速地引导用户打开我们需要的权限呢。直接跟用户说我们需要这个权限,你给我去打开?别开玩笑了,有太多的用户根本找不到权限的开关,折腾了半天一无所获,然后放弃了这个操作,甚至放弃了这个应用。

还有没有更好的办法?目前很多一些应用都是采用提示法,告诉用户应该去『设置 - 应用列表 - 本应用 - 权限管理』中打开某某权限,还有一些会辅助跳转『应用信息』或者『应用列表』,再让用户自己找。

这些方法确实在一定程度上帮助了用户找到相应的权限开关,但是我觉得这还不够。为什么呢?因为在目前国内一些 ROM 中,权限开关根本不在『应用信息』或者『应用列表』里,他们另起炉灶,把权限管理放在了『安全中心』、『手机管家』、『权限管理』等一些系统应用入口中管理。虽然这样的定制方便了用户对权限的管理,却让开发者深感头疼,它们的权限管理界面既没有统一的名称,也没有统一的 API 来跳转。所以必须根据不同的国产 ROM (甚至是同一种 ROM 的不同版本)来定制不同的权限跳转或者提示方案。

关于识别 ROM 并获取其版本号的方案,可见 国产定制 ROM 的终极适配,识别 ROM 并获取版本号

权限界面的跳转

关于权限的界面跳转方面,我一开始的思路是参考了 『Android各大手机品牌手机跳转到权限管理界面』这篇文章。

通过 『ActivityTracker』来获取不同 ROM (甚至需要适配 ROM 版本)的权限界面组件名并进行跳转。部分 ROM 无法进行跳转的,和根据情况跳转到最方便用户操作的界面,比如可以通过『应用信息』界面进去的,可以跳转至『应用信息』在做进一步的提示即可。

public static boolean gotoPermissionSetting() {
    boolean success = true;
    Intent intent = new Intent();
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    String packageName = LshAppUtils.getPackageName();

    LshOSUtils.ROM romType = LshOSUtils.getRomType();
    switch (romType) {
        case EMUI: // 华为
            intent.putExtra("packageName", packageName);
            intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"));
            break;
        case Flyme: // 魅族
            intent.setAction("com.meizu.safe.security.SHOW_APPSEC");
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            intent.putExtra("packageName", packageName);
            break;
        case MIUI: // 小米
            String rom = getMiuiVersion();
            if ("V6".equals(rom) || "V7".equals(rom)) {
                intent.setAction("miui.intent.action.APP_PERM_EDITOR");
                intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
                intent.putExtra("extra_pkgname", packageName);
            } else if ("V8".equals(rom) || "V9".equals(rom)) {
                intent.setAction("miui.intent.action.APP_PERM_EDITOR");
                intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
                intent.putExtra("extra_pkgname", packageName);
            } else {
                intent = getAppDetailsSettingsIntent(packageName);
            }
            break;
        case Sony: // 索尼
            intent.putExtra("packageName", packageName);
            intent.setComponent(new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity"));
            break;
        case ColorOS: // OPPO
            intent.putExtra("packageName", packageName);
            intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.PermissionManagerActivity"));
            break;
        case EUI: // 乐视
            intent.putExtra("packageName", packageName);
            intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps"));
            break;
        case LG: // LG
            intent.setAction("android.intent.action.MAIN");
            intent.putExtra("packageName", packageName);
            ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");
            intent.setComponent(comp);
            break;
        case SamSung: // 三星
        case SmartisanOS: // 锤子
            gotoAppDetailSetting(packageName);
            break;
        default:
            intent.setAction(Settings.ACTION_SETTINGS);
            LshLogUtils.i("没有适配该机型, 跳转普通设置界面");
            success = false;
            break;
    }
    try {
        LshContextUtils.startActivity(intent);
    } catch (Exception e) {
        e.printStackTrace();
        // 跳转失败, 前往普通设置界面
        LshIntentUtils.gotoSetting();
        success = false;
        LshLogUtils.i("无法跳转权限界面, 开始跳转普通设置界面");
    }
    return success;
}

private static String getMiuiVersion() {
    String propName = "ro.miui.ui.version.name";
    String line;
    BufferedReader input = null;
    try {
        Process p = Runtime.getRuntime().exec("getprop " + propName);
        input = new BufferedReader(
                new InputStreamReader(p.getInputStream()), 1024);
        line = input.readLine();
        input.close();
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    } finally {
        LshIOUtils.close(input);
    }
    LshLogUtils.i("MiuiVersion = " + line);
    return line;
}

致歉

由于公司测试设备和个人时间问题,在权限跳转方面目前只测试成功了小米(V7 V8 V9)、华为、三星、锤子、魅族等机型,OPPO 机型目前没有成功跳转。所以在代码和适配方面仍需要继续进行开发和维护。由于目前的公司业务在适配方面的要求并不严格,所以近期内可能没有继续研究适配下去的希望。希望小伙伴们能给一些点赞和支持,如果发现自己的研究能被人所有还是很有动力的。

目前暂定喜欢数超过 10 算是得到大家肯定,继续把跳转步骤进行完整的封装,并适配主流 ROM 系统。希望觉得这篇文章有用的朋友不要吝啬点个喜欢就行,这也算是自己在开源项目的开发上得到的巨大鼓舞了吧。

关于权限跳转的详细代码已经抽取到个人工具类并上传到 GitHub,如有建议或问题,欢迎提 Issues 或 Pull requests。

本篇文章代码所在工具类:IntentUtils

随便提一下自己花了大量心血收集整理的工具类,本篇文章提到的 LshOSUtils 已经收集到该工具类,其中还包括许多其他日常经常使用到的工具类。在此不多赘述,感兴趣的可以点击下面链接查看。

个人收集的常用工具类:Utils-Everywhere



作者:渊祥
链接:https://www.jianshu.com/p/58c6ca8173c4
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/findsafety/article/details/80495997
ROM
今日推荐