Android桌面快捷方式那些事与那些坑

原文来自

将近二个多月没写博客了。之前一段时间一直在搞红包助手,就没抽时间写博客,但写这个真的是很好玩。没想到居然在Android上实现模拟点击,从而实现自动抢红包,有兴趣的同学可以参考https://github.com/waylife/RedEnvelopeAssistant,代码已经开源。红包助手还有一些问题,但是现在基本的抢红包基本没问题了。目前正在对它进行优化以及较低版本的一些适配,还有项目的国际化工作。废话不多说了,下面是Andrioid开发过程中快捷方式相关的事与坑。数据来源于上次组内自己的CodeReview总结。

背景

一般情况下,为了让用户更方便的打开应用,程序会在桌面上生成一些快捷方式。本来呢,如果是原生的桌面,其实是十分简单,直接调用系统相关的API就行了。但是众多的系统厂商以及众多第三方自己定制的桌面(Launcher),导致在适配、兼容方面存在很多问题。比如,有些桌面无法删除快捷方式(比如小米),有些桌面无法生成快捷方式(比如锤子),有些系统无法更新桌面图标(比如华为荣耀6)。在升级、降级的时候快捷方式发生变化;比如,全部变成应用的主图标,升级、降级后点击快捷方式没有反应,删除应用后无法删除快捷方式。很多问题都是需要解决的,虽然有些由于系统限制,没有办法搞定所有的,但是仍然需要寻求一个最优的方案。这也就是本文需要讨论的问题。本文说指的快捷方式是指应用桌面快捷方式,不包含长按弹出的生成快捷方式。快捷方式所有信息都是存在于launcher的favorite表。一般需要用到的字段为_id,title,intent,iconResource,icon,分别表示 快捷方式名称,快捷方式intent,快捷方式图标(本地),快捷方式图标(data二进制压缩数据)。

两个intent数据如下

数据可以通过SQLite Editor查看,需要已经ROOT的手机

实现增加快捷方式

在AndroidManifest.xml增加权限

<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />

同时,根据Intent是隐式还是显示在相关的Activity声明相关的intent-filter。相关代码:

删除快捷方式

跟增加快捷方式一样,也是需要增加权限的。加上

<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />

相关代码:

快捷方式修改

需要增加权限

<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /><uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />如果适配所有桌面,请添加附录中第二条所列出的权限。系统并没有提供API去更改桌面快捷方式。只能通过其他猥琐的办法了,可行的的办法之一就是通过ContentProvider去更改数据库相关的信息。当然有人会说了,先删掉快捷方式,再重新创建不就行了?这是个办法。但是有些系统是无法删除快捷方式的;另外,删除快捷方式与创建快捷方式都是通过广播实现的,这个地方需要控制两者的时间间隔。权衡之后,选用第一种办法相对稳妥。废话不多少,上代码。

/** * 更新桌面快捷方式图标,不一定所有图标都有效<br/> * 如果快捷方式不存在,则不更新<br/>. */ public static void updateShortcutIcon(Context context, String title, Intent intent,Bitmap bitmap) { if(bitmap==null){ XLog.i(TAG, "update shortcut icon,bitmap empty"); return; } try{ final ContentResolver cr = context.getContentResolver(); StringBuilder uriStr = new StringBuilder(); String urlTemp=""; 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); } urlTemp=uriStr.toString(); uriStr.append("/favorites?notify=true"); Uri uri = Uri.parse(uriStr.toString()); Cursor c = cr.query(uri, new String[] {"_id", "title", "intent" },"title=? and intent=? ",new String[] { title, intent.toUri(0) }, null); int index=-1; if (c != null && c.getCount() > 0) {c.moveToFirst();index=c.getInt(0);//获得图标索引ContentValues cv=new ContentValues();cv.put("icon", flattenBitmap(bitmap));Uri uri2=Uri.parse(urlTemp+"/favorites/"+index+"?notify=true");int i=context.getContentResolver().update(uri2, cv, null,null);context.getContentResolver().notifyChange(uri,null);//此处不能用uri2,是个坑XLog.i(TAG, "update ok: affected "+i+" rows,index is"+index); }else{XLog.i(TAG, "update result failed"); } if (c != null && !c.isClosed()) {c.close(); } }catch(Exception ex){ ex.printStackTrace(); XLog.i(TAG, "update shortcut icon,get errors:"+ex.getMessage()); } } private static byte[] flattenBitmap(Bitmap bitmap) { // Try go guesstimate how much space the icon will take when serialized // to avoid unnecessary allocations/copies during the write. int size = bitmap.getWidth() * bitmap.getHeight() * 4; ByteArrayOutputStream out = new ByteArrayOutputStream(size); try { bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); out.close(); return out.toByteArray(); } catch (IOException e) { XLog.w(TAG, "Could not write icon"); return null; } }

快捷方式存在判断上帝从不埋怨人们的愚昧,人们却埋怨上帝的不公平

Android桌面快捷方式那些事与那些坑

相关文章:

你感兴趣的文章:

标签云: