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

    上一篇返回首页 下一篇

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

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

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

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

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

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