关闭 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 基本上都可以通过这个方案来解决。

    上一篇返回首页 下一篇

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

    别人在看

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    小米路由器买哪款?Miwifi热门路由器型号对比分析

    IT头条

    Synology 对 Office 套件进行重大 AI 更新,增强私有云的生产力和安全性

    01:43

    StorONE 的高效平台将 Storage Guardian 数据中心占用空间减少 80%

    11:03

    年赚千亿的印度能源巨头Nayara 云服务瘫痪,被微软卡了一下脖子

    12:54

    国产6nm GPU新突破!砺算科技官宣:自研TrueGPU架构7月26日发布

    01:57

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    技术热点

    如何删除自带的不常用应用为windows 7减负

    MySQL中多表删除方法

    改进的二值图像像素标记算法及程序实现

    windows 7 32位系统下手动修改磁盘属性例如M盘修改为F盘

    windows 7中怎么样在家庭组互传文件

    Linux应用集成MySQL数据库访问技巧

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

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