ShortCut 快捷方式的创建和判断
一、相关介绍
1. 快捷方式的创建、删除通过广播实现
2. 也就是要传一个intent
3. 接受intent的这个广播接收器负责把intent传的数据写入到launcher的favorite表
4. 系统是根据favorite生成桌面的快捷方式的
5. 抽屉,这个基本只有在原生的系统有的一个控件,里面罗列所有安装的appIcon
本来呢,如果是原生的桌面,其实是十分简单,直接调用系统相关的API就行了。但是众多的系统厂商以及众多第三方自己定制的桌面(Launcher,launcher数据库路径不一致, 修改favorite的字段),导致在适配、兼容方面存在很多问题。
比如,有些桌面无法删除快捷方式(比如小米),有些桌面无法生成快捷方式(比如锤子),有些系统无法更新桌面图标(比如华为荣耀6)。
在升级、降级的时候快捷方式发生变化;比如,全部变成应用的主图标,升级、降级后点击快捷方式没有反应,删除应用后无法删除快捷方式。
很多问题都是需要解决的,虽然有些由于系统限制,没有办法搞定所有的,但是仍然需要寻求一个最优的方案。
二、实现
1、增加快捷方式
在AndroidManifest.xml增加权限:
<uses-permissionandroid:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
在部分手机中发现需要添加一下filter到activity中,才能创建快捷方式:
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
</intent-filter>
同时,如果Intent是隐式,需要在Activity声明相关的intent-filter。
相关代码:
/**
* 创建应用入口的快捷方式
*/
public static boolean createAppShortcut(Context context, Class<?> cls, String shortCutName, int shortIconId) {
boolean isShortCutExist = isShortCutExist(context, shortCutName);
if (!isShortCutExist) {
Intent intent = new Intent(ACTION_INSTALL_SHORTCUT);
final Intent launchIntent = new Intent(context, cls);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
launchIntent.putExtra(ACTION_INTENT, shortCutName);
Parcelable icon = Intent.ShortcutIconResource.fromContext(
context.getApplicationContext(), shortIconId);
intent.putExtra("duplicate", false); // 不允许重复创建
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortCutName); // 快捷方式的标题
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon); // 快捷方式的图片
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launchIntent); // 快捷方式的运行程序主入口
context.sendBroadcast(intent);
}
return isShortCutExist;
} `
2、删除快捷方式
跟增加快捷方式一样,也是需要增加权限:
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
相关代码:
/**
* 删除快捷方式 不一定能成功
* @param context
* @param cls
* @param shortCutName
*/
public static void delShortcut(Context context, Class<?> cls, String shortCutName) {
boolean isShortCutExist = isShortCutExist(context, shortCutName);
if (isShortCutExist) {
Intent intent = new Intent(ACTION_UNINSTALL_SHORTCUT);
final Intent launchIntent = new Intent(context, cls);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
launchIntent.putExtra(ACTION_INTENT, shortCutName);
intent.putExtra("duplicate", false); // 为true是循环删除快捷方式
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortCutName); // 快捷方式的标题
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launchIntent); // 快捷方式的运行程序主入口
context.sendBroadcast(intent);
}
}
`
3、快捷方式的存在判断
需要增加的权限:
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
虽然说通过SharePreference来保证快捷方式不会重复创建,以及通过shortcutIntent.putExtra(“duplicate”, false)也可以确保,但是为了万无一失,还是可以通过去查询数据判断快捷方式是否存在,来避免重复创建。(用户清除应用数据后,不会删除快捷方式)
/**
* 检查快捷方式是否存在 <br/>
* <font color=red>注意:</font> 有些手机无法判断是否已经创建过快捷方式<br/>
* 因此,在创建快捷方式时,请添加<br/>
* shortcutIntent.putExtra("duplicate", false);// 不允许重复创建<br/>
* 最好使用{@link #isShortCutExist(Context, String, Intent)}
* 进行判断,因为可能有些应用生成的快捷方式名称是一样的的<br/>
* 此处需要在AndroidManifest.xml中配置相关的桌面权限信息<br/>
* 错误信息已捕获<br/>
*/
public static boolean isShortCutExist(Context context, String title) {
boolean result = false;
try {
final ContentResolver cr = context.getContentResolver();
StringBuilder uriStr = new StringBuilder();
String authority = LauncherUtil.getAuthorityFromPermissionDefault(context);
if(authority==null||authority.trim().equals("")){
authority = LauncherUtil.getAuthorityFromPermission(context,LauncherUtil.getCurrentLauncherPackageName(context)+".permission.READ_SETTINGS");
}
uriStr.append("content://");
if (TextUtils.isEmpty(authority)) {
int sdkInt = android.os.Build.VERSION.SDK_INT;
if (sdkInt < 8) { // Android 2.1.x(API 7)以及以下的
uriStr.append("com.android.launcher.settings");
} else if (sdkInt < 19) {// Android 4.4以下
uriStr.append("com.android.launcher2.settings");
} else {// 4.4以及以上
uriStr.append("com.android.launcher3.settings");
}
} else {
Log.d("ShortcutUtil", "authority=" + authority);
uriStr.append(authority);
}
uriStr.append("/favorites?notify=true");
Uri uri = Uri.parse(uriStr.toString());
Cursor c = cr.query(uri, null,
"title=? ",
new String[] { title }, null);
if (c != null && c.getCount() > 0) {
result = true;
}
if (c != null && !c.isClosed()) {
c.close();
}
} catch (Exception e) {
e.printStackTrace();
result=false;
}
Log.d("ShortcutUtil", "result isShortCutExist=" + result);
return result;
}
/**
* 不一定所有的手机都有效,因为国内大部分手机的桌面不是系统原生的<br/>
* 更多请参考{@link #isShortCutExist(Context, String)}<br/>
* 桌面有两种,系统桌面(ROM自带)与第三方桌面,一般只考虑系统自带<br/>
* 第三方桌面如果没有实现系统响应的方法是无法判断的,比如GO桌面<br/>
* 此处需要在AndroidManifest.xml中配置相关的桌面权限信息<br/>
* 错误信息已捕获<br/>
*/
public static boolean isShortCutExist(Context context, String title, Intent intent) {
boolean result = false;
try{
final ContentResolver cr = context.getContentResolver();
StringBuilder uriStr = new StringBuilder();
String authority = LauncherUtil.getAuthorityFromPermissionDefault(context);
if(authority==null||authority.trim().equals("")){
authority = LauncherUtil.getAuthorityFromPermission(context,LauncherUtil.getCurrentLauncherPackageName(context)+".permission.READ_SETTINGS");
}
uriStr.append("content://");
if (TextUtils.isEmpty(authority)) {
int sdkInt = android.os.Build.VERSION.SDK_INT;
if (sdkInt < 8) { // Android 2.1.x(API 7)以及以下的
uriStr.append("com.android.launcher.settings");
} else if (sdkInt < 19) {// Android 4.4以下
uriStr.append("com.android.launcher2.settings");
} else {// 4.4以及以上
uriStr.append("com.android.launcher3.settings");
}
} else {
uriStr.append(authority);
}
uriStr.append("/favorites?notify=true");
Uri uri = Uri.parse(uriStr.toString());
Cursor c = cr.query(uri, new String[] { "title", "intent" },
"title=? and intent=?",
new String[] { title, intent.toUri(0) }, null);
if (c != null && c.getCount() > 0) {
result = true;
}
if (c != null && !c.isClosed()) {
c.close();
}
}catch(Exception ex){
result=false;
ex.printStackTrace();
}
return result;
}
`
注意事项
因为国内rom改的太多,如需适配更多机型需要添加各个launcher的包名对应权限:
<uses-permission android:name="com.google.android.apps.nexuslauncher.permission.READ_SETTINGS"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher2.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="org.adw.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.qihoo360.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.lge.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="net.qihoo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="org.adwfreak.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="org.adw.launcher_donut.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.fede.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.sec.android.app.twlauncher.settings.READ_SETTINGS" />
<uses-permission android:name="com.anddoes.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.tencent.qqlauncher.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.launcher2.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.mylauncher.permission.READ_SETTINGS" />
<uses-permission android:name="com.ebproductions.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.lenovo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.bbk.launcher2.permission.READ_SETTINGS" />
<uses-permission android:name="cn.nubia.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="cn.nubia.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="cn.nubia.launcher2.permission.READ_SETTINGS" />
<uses-permission android:name="cn.nubia.launcher2.permission.WRITE_SETTINGS" />
<uses-permission android:name="net.oneplus.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="net.oneplus.launcher.permission.WRITE_SETTINGS" />
具体代码:https://github.com/AriesJiang/AriesDemo/tree/master/app/src/main/java/com/niqiu/shortcut