Original from http://blog.zanlabs.com/2015/03/14/android-shortcut-summary/
I haven't written a blog for nearly two months.
A long time ago has been engaged in the red Envelope assistant, did not take the time to write a blog, but write this really is very fun. Unexpectedly on Android to achieve analog click, so as to realize the automatic snatch red envelopes, interested students can refer to Https://github.com/waylife/RedEnvelopeAssistant, code has been open source.
Red Envelope Helper still have some questions, but now basic Rob red envelopes basically no problem. It is currently being optimized as well as some adaptation of the lower version, as well as the internationalization of the project.
Needless to say, the following is the andrioid development process of the shortcut related to the pit.
The data comes from the last group's own Codereview summary.
Background
In general, to make it easier for users to open apps, the program generates shortcuts on the desktop.
Originally, if is the native desktop, actually is very simple, directly calls the system related API to be OK. However, many system vendors, as well as many third-party customized desktops (Launcher), cause a lot of problems in adaptation and compatibility.
For example, some desktops cannot delete shortcuts (such as Xiaomi), some desktops cannot generate shortcuts (such as hammers), and some systems cannot update desktop icons (such as Huawei Glory 6).
The shortcut changes when upgrading, downgrading, for example, all become the app's main icon, upgrade, downgrade after clicking the shortcut does not respond, delete the app cannot delete the shortcut.
Many problems need to be solved, although some due to the system constraints, there is no way to fix all, but still need to find an optimal solution. This is the question to be discussed in this paper.
The shortcut referred to in this article refers to the app desktop shortcut, which does not include a long press popup for the build shortcut.
Shortcuts all information is present in the launcher favorite table. Commonly used fields are _id,title,intent,iconresource,icon, which indicate shortcut name, shortcut intent, shortcut icon (local), shortcut icon (data binary compression).
Two intent data are as follows
Data can be viewed in SQLite editor and requires a rooted phone
Implement add Shortcut
Add Permissions in Androidmanifest.xml
<uses-permission android:name= "Com.android.launcher.permission.INSTALL_SHORTCUT"/>
Also, depending on whether the intent is implicit or displayed in the relevant activity statement related Intent-filter.
Related code:
Delete Shortcut
As with adding shortcuts, you also need to increase permissions. Plus
<uses-permission android:name= "Com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
Related code:
Shortcut modifications
Need to increase permissions
<uses-permission android:name= "Com.android.launcher.permission.READ_SETTINGS"/><uses-permission Android : Name= "Com.android.launcher.permission.WRITE_SETTINGS"/>
If you are adapting to all desktops, add the permissions listed in the second section of the appendix.
The system does not provide an API to change desktop shortcuts. Only through other wretched ways, one of the possible ways is to change database-related information through ContentProvider. Of course someone will say, first delete the shortcut, and then re-create it is OK? It's a solution. However, some systems cannot delete shortcuts, and deleting shortcuts and creating shortcuts are all broadcast, and this place needs to control the time interval between them. After the trade-off, the first method is relatively safe to use.
Nonsense not much, on the code.
/** * Update desktop shortcut icon, not all icons are valid <br/> * If the shortcut does not exist, the <BR/> is not updated. */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) and the following uristr.append ("Com.android.launcher.settings"); } else if (Sdkint < +) {//Android 4.4 below Uristr.append ("com.android.launcher2.settings"); } ELSE {//4.4 and above 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);//Get icon index 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);//This can not be used uri2, is a pit 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 would take when Ser Ialized//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, N, out); Out.flush (); Out.close (); return Out.tobytearray (); } catch (IOException e) {XLOG.W (TAG, "Could not write icon"); return null; } }
Shortcut existence judgment
Need to increase the permissions with the Modify shortcut
Although it is said through Sharepreference that shortcuts are not created repeatedly, and through Shortcutintent.putextra ("duplicate", false) can also be ensured, but in order to be foolproof, You can also avoid duplicate creation by querying the data to determine if a shortcut exists. The code is as follows:
/** * Check if shortcut exists <br/> * <font color=red> Note:</font> Some phones can't tell if a shortcut has been created <br/> * So, when creating a shortcut, add & lt;br/> * Shortcutintent.putextra ("duplicate", false);//Do not allow duplicate creation <br/> * Best Use {@link #isShortCutExist (Context, String, Intent)} * is judged because there may be apps that generate the same name as the shortcut <br/> * Here you need to configure the relevant desktop permissions information in androidmanifest.xml <br/> * error message captured <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) and the following uristr.append ("Com.android.launcher.settings"); } else if (Sdkint < +) {//Android 4.4 below Uristr.append ("com.android.launcher2.settings"); } else {//4.4 and above 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"}, "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; } return result; }/** * Not all phones are valid, because most of the domestic phone's desktop is not the system native <br/> * More please refer to {@link #isShortCutExist (Context, String)}<br/> * Desktop There are two kinds, System Desktop (Rom comes with) and third-party desktop, generally only consider the system comes with <br/> * third-party desktop if there is no way to implement system response is not judged, such as Go desktop <br/> * Here you need to configure the relevant desktop permissions information in androidmanifest.xml <br/> * error messages captured <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) and the following uristr.append ("Com.android.launcher.settings"); } else if (Sdkint < +) {//Android 4.4 below Uristr.append ("com.android.launcher2.settings"); } else {//4.4 and above 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; }
Compatibility and Precautions compatible
All shortcuts Intent if not the previous version of the existence of a big problem, never change the parameters, or upgrade or downgrade when the shortcut will be a problem;
At the same time, use implicit invocation as much as possible, custom category, not custom action,action parameter must be action_main, otherwise some phones cannot delete shortcut (WTF) when unload.
Precautions
- Changes to the "all" activity path cause the shortcut to be unusable after the old version upgrade
1. Once the package path of activity has been determined, no further changes will be made;
2. Use implicit invocation whenever possible, but if the previous version has been issued, for compatibility, you must always use the old way, the new version as far as possible do not change the way, if the user degraded, the old version of the shortcut will not be used.
- "Partial" multiple shortcuts point to an activity causing some phones (Samsung SII) to upgrade when the icon becomes an app icon
As much as possible to avoid multiple shortcuts to the same activity, possibly through multiple activity and then jump past
- The shortcut cannot be deleted when the "partial" app is deleted. Related to the System Desktop launcher implementation.
To fit all launcher,intent ACTION use Intent.action_main. If this is an implicit invocation, customize the category as much as possible, rather than customizing the action.
- Part of the app upgrade needs to remove the old version part of the shortcut, but some phones cannot be deleted
No solution
- "Partial" third-party desktops cannot generate, delete, update shortcuts
-hehe, generally generated no problem, but delete, update most of the desktop will have a problem. Avoid these operations as much as possible. or specially adapted to the desktop, the cost is higher.
- Partial desktop does not update icons in real time and requires restart
No solution, try to restart launcher, but the result is that the previous shortcuts have disappeared. Only restart the phone, supposedly there should be a way to trigger launcher to refresh.
The above "All" "section", respectively, indicates that there must be a partial occurrence.
Reference
- Http://grepcode.com/search/?query=InstallShortcutReceiver
- Http://developer.android.com/index.html
Appendix
- The complete code can be consulted
https://gist.github.com/waylife/437a3d98a84f245b9582
- Generic Update shortcut Permissions List
<uses-permission android:name= "Com.android.launcher.permission.READ_SETTINGS"/> <uses-permission Android : Name= "Com.android.launcher.permission.WRITE_SETTINGS"/> <uses-permission android:name= " Com.android.launcher2.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.android.launcher2.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.android.launcher3.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.android.launcher3.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Org.adw.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Org.adw.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.htc.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.htc.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.qihoo360.launcher.permission.READ_SETTINGS "/> <uses-perMission android:name= "Com.qihoo360.launcher.permission.WRITE_SETTINGS"/> <uses-permission android:name= " Com.lge.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.lge.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Net.qihoo.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Net.qihoo.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Org.adwfreak.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Org.adwfreak.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Org.adw.launcher_ Donut.permission.READ_SETTINGS "/> <uses-permission android:name=" org.adw.launcher_donut.permission.WRITE_ SETTINGS "/> <uses-permission android:name=" Com.huawei.launcher3.permission.READ_SETTINGS "/> <uses-per Mission android:name= "Com.huawei.launcher3.permission.WRITE_SETTINGS"/> <uses-permission ANdroid:name= "Com.fede.launcher.permission.READ_SETTINGS"/> <uses-permission android:name= " Com.fede.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.sec.android.app.twlauncher.settings.READ_SETTINGS "/> <uses-permission android:name=" Com.sec.android.app.twlauncher.settings.WRITE_SETTINGS "/> <uses-permission android:name=" Com.anddoes.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.anddoes.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.tencent.qqlauncher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.tencent.qqlauncher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.huawei.launcher2.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.huawei.launcher2.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.android.mylauncher.permission.READ_SETTINGS "/> <uses-pErmission android:name= "Com.android.mylauncher.permission.WRITE_SETTINGS"/> <uses-permission android:name= " Com.ebproductions.android.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.ebproductions.android.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.oppo.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.oppo.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Com.huawei.android.launcher.permission.READ_SETTINGS "/> <uses-permission android:name=" Com.huawei.android.launcher.permission.WRITE_SETTINGS "/> <uses-permission android:name=" Telecom.mdesk.permission.READ_SETTINGS "/> <uses-permission android:name=" telecom.mdesk.permission.WRITE_ SETTINGS "/> <uses-permission android:name=" Dianxin.permission.ACCESS_LAUNCHER_DATA "/>
Android Desktop shortcuts Those things with those pits