关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android 适配多种 ROM 的快捷方式

    Android 适配多种 ROM 的快捷方式

    2015-12-02 00:00:00 出处:segmentfault
    分享

    快捷方式 应该来说 很多人都做过,我们就来看一下基本的快捷方式 是怎么实现的,会有什么问题?

    首先 肯定要获取权限:

    <!-- 添加快捷方式 -->
        <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
        <!-- 移除快捷方式 -->
        <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
        <!-- 查询快捷方式 -->
        <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />

    然后定义一下大家要发起的action:

    //删除快捷方式的action
    public static final String ACTION_REMOVE_SHORTCUT = "com.android.launcher.action.UNINSTALL_SHORTCUT";
    //添加快捷方式的action
    public static final String ACTION_ADD_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";

    然后写2个方法即可:

    //删除快捷方式
      public static void removeShortcut(Context context, Intent actionIntent, String name) {
            Intent intent = new Intent(ACTION_REMOVE_SHORTCUT);
            intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
            intent.putExtra("duplicate", false);
            intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
            context.sendBroadcast(intent);
     }
    //增加快捷方式  
    public static void addShortcut(Context context, Intent actionIntent, String name,
                                       boolean allowRepeat, Bitmap iconBitmap) {
            Intent addShortcutIntent = new Intent(ACTION_ADD_SHORTCUT);
            // 是否允许重复创建
            addShortcutIntent.putExtra("duplicate", allowRepeat);
            // 快捷方式的标题
            addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
            // 快捷方式的图标
            addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);
            // 快捷方式的动作
            addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
            context.sendBroadcast(addShortcutIntent);
    }

    这种方法,大部分的手机都能正常使用。但是在某些国产手机上会有各种各样的问题。比如hw的手机这样做就完全无效。

    小米的手机 无法重复创建快捷方式等。那现在看看 有没有什么方法 能解决这些问题。

    首先我们来看一张图:

    这张图很清晰的告诉我们launcher这个应用下面 是有一个数据库的。

    我们可以打开这个数据库 看看到底是什么?

    你看这个就一目了然了,快捷方式 都是存在于这个表里面的!所以 我们除了发送广播 可以创建快捷方式以外,我们直接操作数据库也应该是可以创建快捷方式的。

    但是大家要注意啊,各家的lanucher 都有很大不同的,我上面的截图 是用的模拟器,所以是官方的rom,那路径肯定就是常规的,但是深度定制的android系统,大家都知道各家lanucher都是自己在做,所以favorites 这张表的位置到底在哪里,这就是个问题了。我们需要先查找出来这张表到底在哪个位置才能好操作这个表,要想知道这个表在哪个位置,我们首先要知道 对于这个rom来说,是哪个lanucher在启作用?包名是什么?

    //此函数返回当前rom下的lanucher的包名
        private String getCurrentLanucherPackageName(Context context)
        {
            //这个intent很好理解 就是启动lanucher的intent
            Intent intent=new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_HOME);
            //getPackageManager().resolveActivity 这个函数就是查询是否有符合条件的activity的
            ResolveInfo res=context.getPackageManager().resolveActivity(intent,0);
            //为避免空指针 大家要判定下空,虽然你我都知道这种情况不会发生
            if(res==null||res.activityInfo==null)
            {
                return "";
            }
            return res.activityInfo.packageName;
        }

    有些人可能对于4-5行还是理解不了,为什么这个相当于是启动lanucher的intent 其实很简单,我们在android studio里 run一个app的时候,我们通常都能看到下面这个界面:

    你看android studio 实际上安装完我们的应用以后 也是通过 这个intent来启动手机里的lanucher 然后让lanucher来运行我们的app,因为studio也不知道你手机里的lanucher到底是哪个,所以只能用intent来完成,这也就是上述代码能必定成功运行的原因!否则的话 android studio 就无法把你的app run进去了~~

    当然了你也可以进入shell ,打ps 命令看看到底是不是有这个 包名的 进程在 运行中~~

    好 拿到了我们的lanucher的包名,下面一步就是去我们的包名下 操作那个数据库即可了。那显然这个步骤 最合适的就是contentprovider来操作了。

    //此函数返回 要查找的permission的 provider的 authority
        private String getAuthorityFromPermission(Context context, String permission) {
            //返回安装的app的 provider的信息
            List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);
            //遍历获取到的安装包的信息
            for (PackageInfo pack : packs) {
                //每个安装包提供的provider 都在这个数组里面
                ProviderInfo[] providers = pack.providers;
                if (providers != null) {
                    //遍历每个provider 看需要的权限是否与我们传进来的权限参数相等
                    for (ProviderInfo providerInfo : providers) {
                        if (permission.equals(providerInfo.readPermission) || permission.equals(providerInfo.writePermission)) {
                            return providerInfo.authority;
                        }
                    }
                }
            }
            return "";
        }
    private String getAuthorityFromPermissionDefault(Context context) {
    return getAuthorityFromPermission(context, "com.android.launcher.permission.READ_SETTINGS");
    }
    private  Uri getUriFromLauncher(Context context) {
            StringBuilder uriStrBuilder = new StringBuilder();
            //为了速度考虑,这里我们先查找默认的 看是否能查找到 因为多数手机的rom还是用的默认的lanucher
            String authority = getAuthorityFromPermissionDefault(context);
            //假如找不到的话 就说明这个rom一定是用的其他的自定义的lanucher。那就拼一下 这个自定义的lanucher的permission再去查找一次
            if (authority == null || authority.trim().equals("")) {
                authority = getAuthorityFromPermission(context,getCurrentLanucherPackageName(context) + ".permission.READ_SETTINGS");
            }
            uriStrBuilder.append("content://");
            //假如连上面的方法都查找不到这个authority的话 那下面的方法 就肯定查找到了 但是很少有情况会是如下这种
            //多数都是else里面的逻辑
            if (TextUtils.isEmpty(authority)) {
                int sdkInt = android.os.Build.VERSION.SDK_INT;
                if (sdkInt < 8) { // Android 2.1.x(API 7)以及以下的
                    uriStrBuilder.append("com.android.launcher.settings");
                } else if (sdkInt < 19) {// Android 4.4以下
                    uriStrBuilder.append("com.android.launcher2.settings");
                } else {// 4.4以及以上
                    uriStrBuilder.append("com.android.launcher3.settings");
                }
            } else {
                uriStrBuilder.append(authority);
            }
            uriStrBuilder.append("/favorites notify=true");
            return Uri.parse(uriStrBuilder.toString());
        }

    好,到这里 我们就能拿到所有rom 任意一款手机的 快捷方式 那张数据库表对应的uri了。

    那到这里应该来说问题就基本解决了,你所有对快捷方式的操作 都可以直接通过这个uri来进行,无非就是一些crud的拼装。

    再也不需要经过广播 那一道程序了,但是这里要注意的是 这种方法通常耗时都比较久,根据手机的性能的不同 200ms-600ms 才能完成uri的查找。所以记得做一下异步处理。

    并且所有你对lanucher的 需求 都可以这么来做,比方说有些功能 在使用原生lanucher的手机上使用正常,在小米 华为 oppo使用不正常了,你就去找出来那个不正常的rom的lanucher的 包名,然后找出他provider需要的权限,然后在你的manifest里 直接加权限 应该就可以正常使用了。第三方lanucher 引起的bug 基本上都可以通过这个方案来解决。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。