Android 适配多种ROM的快捷方式

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

首先 肯定要获取权限:

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

然后定义一下我们要发起的action:

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

然后写2个方法即可:

 1  //删除快捷方式
 2   public static void removeShortcut(Context context, Intent actionIntent, String name) {
 3         Intent intent = new Intent(ACTION_REMOVE_SHORTCUT);
 4         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
 5         intent.putExtra("duplicate", false);
 6         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
 7         context.sendBroadcast(intent);
 8  }
 9 //增加快捷方式
10 public static void addShortcut(Context context, Intent actionIntent, String name,
11                                    boolean allowRepeat, Bitmap iconBitmap) {
12         Intent addShortcutIntent = new Intent(ACTION_ADD_SHORTCUT);
13         // 是否允许重复创建
14         addShortcutIntent.putExtra("duplicate", allowRepeat);
15         // 快捷方式的标题
16         addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
17         // 快捷方式的图标
18         addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);
19         // 快捷方式的动作
20         addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
21         context.sendBroadcast(addShortcutIntent);
22 }

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

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

首先我们来看一张图:

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

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

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

但是我们要注意啊,各家的lanucher 都有很大不同的,我上面的截图 是用的模拟器,所以是官方的rom,那路径肯定就是常规的,但是深度定制的android系统

大家都知道各家lanucher都是自己在做,所以favorites 这张表的位置到底在哪里,这就是个问题了。我们需要先查找出来这张表到底在哪个位置才能好操作这个表,

要想知道这个表在哪个位置,我们首先要知道 对于这个rom来说,是哪个lanucher在启作用?包名是什么?

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

有些人可能对于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来操作了。

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

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

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

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

并且所有你对lanucher的 需求 都可以这么来做,比方说有些功能 在使用原生lanucher的手机上使用正常,在小米 华为 oppo使用不正常了,你就去找出来那个不正常的rom

的lanucher的 包名,然后找出他provider需要的权限,然后在你的manifest里 直接加权限 应该就可以正常使用了。第三方lanucher 引起的bug 基本上都可以通过这个方案

来解决。

时间: 2024-10-14 13:23:17

Android 适配多种ROM的快捷方式的相关文章

Android开发中适配多种 ROM 的快捷方式是如何实现的?

在安卓开发中,要提高开发效率,掌握一些快捷方式是必不可少的,特别是对于android入门阶段的童鞋而言,非常重要.今天小编在安卓开发教程网站上,搜罗了一些常用的Android 适配多种 ROM 的快捷方式,分享给大家,一起来看看他们是怎么实现的吧. 首先,需要获取权限: <!-- 添加快捷方式 --> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /&g

Android创建和删除桌面快捷方式

有同学方反馈创建快捷方式后,点击快捷方式后不能启动程序或者提示"未安装程序",貌似是新的rom在快捷方式这块做过修改(由于此文是11年5月所出,估计应该是2.0或2.1的rom),现已修正,HTC G11 2.3.5rom测试通过. 1,判断是否已经创建了快捷方式(在某些机型中需要判断) 1 2 3 4 5 6 7 8 9 10 11 12 13 private boolean hasShortcut() {         boolean isInstallShortcut = fa

Android适配方案小结(三)

在Android适配方案小结(一).(二)中,我们了解了一些基本概念. 那么在具体开发中,我们应该注意什么呢. 首先,我们必须要知道,其实适配的关键在于两点: (1)不同分辨率设备的适配,这点在单位的使用上用dp.sp以及图片资源存放于不同的drawable文件夹就可以解决问题: (2)不同尺寸的适配,这点主要靠将相关值以及布局文件放置于不同的文件夹中来解决. 2.1 values文件夹 可以在工程下创建不同的values文件夹:values-sw480dp, values-sw600dp, v

Android ListView 多种布局--进阶二

Android ListView 多种布局–进阶一 中提及了这么一个需求,本博文就这个需求的实现做进一步探讨. 前面是单列,后面是双列的情况,使用ListView实现,一般的解决思路是处理getView和getCount方法,如下实现: 首先实现Adapter,处理getView和getCount方法 public class DoubleAdapter extends BaseAdapter implements OnClickListener{ private List<String> m

Android适配器之DataModifyHelper数据操作类的封装

编写适配器代码时常常被以下几个问题所困扰: 1.业务层和适配器中对同一组数据进行维护,难以管理 2.在业务层针对数据进行修改后必须通知适配器更新,否则提示The content of the adapter has changed but ListView did not receive anotification 3.业务层修改数据时充斥大量的非空&数据标准化等冗余代码 针对前两个问题,可以将数据交由适配器去管理,业务层对数据的增删改查均通过适配器进行处理,这样仅需要维护好adapter中的数

Android 适配知识点

转载:https://gold.xitu.io/post/58451c1d8e450a006c0f1c74 支持多种屏幕 Android 可在各种具有不同屏幕尺寸和密度的设备上运行.对于 应用,Android 系统在不同设备中提供一致的开发环境, 可以处理大多数工作,将每个应用的用户界面调整为适应其显示的 屏幕.同时,系统提供 API,可用于控制 应用适用于特定屏幕尺寸和密度的 UI,以针对 不同屏幕配置优化 UI 设计.例如,您可能想要不同于手机 UI 的 平板电脑 UI. 虽然系统为使您的应

Android适配难题全面总结

支持多种屏幕 Android 可在各种具有不同屏幕尺寸和密度的设备上运行.对于 应用,Android 系统在不同设备中提供一致的开发环境, 可以处理大多数工作,将每个应用的用户界面调整为适应其显示的 屏幕.同时,系统提供 API,可用于控制 应用适用于特定屏幕尺寸和密度的 UI,以针对 不同屏幕配置优化 UI 设计.例如,您可能想要不同于手机 UI 的 平板电脑 UI. 虽然系统为使您的应用适用于不同的屏幕, 会进行缩放和大小调整,但您应针对不同的屏幕尺寸和密度优化 应用.这样可以最大程度优化所

Android中为APP创建快捷方式的原理(自己的理解)

我们首先来看Android中为APP创建快捷方式的原理: 从图上可以看出,Android大致分7步完成快捷方式的创建: 第一步:Android系统的launcher程序会调用它的pickShortcut()方法去启动系统的pickActivity程序(应用): 第二步:pickActivity程序(应用)启动后会调用它的CheckIntentFilter()方法,去在系统中寻找可以创建快捷方式的应用有哪些,并且列举出来.只要第三方                     App用<Intent-

Android刷三方rom之后 没有logcat日志的问题

现在市面上很多Android手机三方ROM包都默认关闭了日志的输出,原因当然是为了手机的流畅性. 但是同时也为广大的开发者带来了困扰: 1): eclipse 提示错误: Unable to open log device '/dev/log/main' 2)具体原因: 原因是因为现在很多rom的制作者都关闭了log日志,在系统初始化的时候会加载init.d目录的脚本文件,其中会有一行 "rm /dev/log/main"这行代码的意思就是系统初始化的时候删除系统的main主日志文件,