i have a quite specific problem. I have realized a Web App on an Android tablet, which will be used on an exhibition (Outform iDisplay). For this reason, the Web App has to start directly after boot. The after-boot thing is no problem (Broadcast with "android.permission.RECEIVE_BOOT_COMPLETED"), but i have a problem to start Chrome as Web-App. For getting the Intent, i have read the Icons in the launcher favorites with this snippet:
//Kitkat, therefore launcher3 url = "content://com.android.launcher3.settings/favorites?Notify=true"; ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse(url), null, null, null, null); if (cursor != null && cursor.moveToFirst()) { do { String ent1 = cursor.getString(0); String ent2 = cursor.getString(1); String ent3 = cursor.getString(2); //there is the Intent string String ent4 = cursor.getString(3); System.out.println("Test"); String ent5 = cursor.getString(4); String ent6 = cursor.getString(5); String ent7 = cursor.getString(6); String ent8 = cursor.getString(7); String ent9 = cursor.getString(8); String ent10 = cursor.getString(9); String ent11 = cursor.getString(10); String ent12 = cursor.getString(11); String ent14 = cursor.getString(13); String ent15 = cursor.getString(14); String ent17 = cursor.getString(16); String ent18 = cursor.getString(17); String ent19 = cursor.getString(18); String ent20 = cursor.getString(19); if(ent2.equals("History Book")) //Get the right intent { runAction = ent3; } System.out.println(ent3); } while (cursor.moveToNext()); }
The Intent string contains something like this:
#Intent;action=com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_WEBAPP;package=com.android.chrome;S.org.chromium.chrome.browser.webapp_title=History%20Book;S.org.chromium.chrome.browser.webapp_id=86e362e4-a25d-4142-8a32-c02ffcb176a9;i.org.chromium.content_public.common.orientation=6;S.org.chromium.chrome.browser.webapp_icon=;S.org.chromium.chrome.browser.webapp_mac=3ZaXFbyWnJQaqFFOuUj3OssNz7DrBaaiWfzO2Dd7VIU%3D%0A;S.org.chromium.chrome.browser.webapp_url=http%3A%2F%2F192.168.5.148%2Fstyria%2Fhistorybook%2Findex.html;end
This looks quite good, but how can i start an Intent like this in a small app, which just has the single purpose to start this intent?
Just a small note at the end: I have tried to pack this thing into a webview, but the webview died constantly because of an libc error, so this is no option for me.
Finally i got this thing working. I was on the right way, but some Chrome.apk reverse engineering helped me for the last mile. I have created a dummy activity with the following code in onCreate:
Search for the right entry on the homescreen, in my case for the AOSP launcher 3:
//Search for the History Book Shortcut on the Homescreen String url = ""; String runAction=""; final String AUTHORITY = "com.android.launcher3.settings"; final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true"); final ContentResolver cr = getContentResolver(); Cursor cursor = cr.query(CONTENT_URI,null,null,null,null); cursor.moveToFirst(); do { String id = cursor.getString(cursor.getColumnIndex("_id")); String title = cursor.getString(cursor.getColumnIndex("title")); String intent = cursor.getString(cursor.getColumnIndex("intent")); if(title.equals(getResources().getString(R.string.homescreen_link))) { runAction = intent; } } while (cursor.moveToNext());
At this point, i have hopefully the intent as string. So, parse the string and create a new intent:
Intent intent = new Intent(); intent.setAction("com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_WEBAPP"); intent.setPackage("com.android.chrome"); intent.setClassName("com.android.chrome", "com.google.android.apps.chrome.webapps.WebappManager"); HashMap<String, String> intentVals = getIntentParams(runAction); intent.putExtra("org.chromium.chrome.browser.webapp_title",intentVals.get("S.org.chromium.chrome.browser.webapp_title")); intent.putExtra("org.chromium.chrome.browser.webapp_icon",intentVals.get("S.org.chromium.chrome.browser.webapp_icon")); intent.putExtra("org.chromium.chrome.browser.webapp_id",intentVals.get("S.org.chromium.chrome.browser.webapp_id")); intent.putExtra("org.chromium.chrome.browser.webapp_url",intentVals.get("S.org.chromium.chrome.browser.webapp_url")); intent.putExtra("org.chromium.chrome.browser.webapp_mac",intentVals.get("S.org.chromium.chrome.browser.webapp_mac")); int orientation = 6; try { orientation = Integer.parseInt(intentVals.get("i.org.chromium.content_public.common.orientation")); } catch(NumberFormatException _nex) { Log.e(TAG, "Wrong format, using default (6)"); } intent.putExtra("org.chromium.content_public.common.orientation", orientation); try { byte[] abyte0 = Base64.decode( intentVals.get("S.org.chromium.chrome.browser.webapp_mac"), 0); System.out.println(new String(abyte0)); } catch (IllegalArgumentException _iae) { Log.e(TAG, "Wrong webapp_mac: " + intentVals .get("S.org.chromium.chrome.browser.webapp_mac")); } startActivity(intent); finish();
And this function parses the intent parameters out of the intent string:
private HashMap<String, String> getIntentParams(String _runAction) { HashMap<String, String> retMap = new HashMap<String, String>(); String[] pairs = _runAction.split(";"); for (int i = 0; i < pairs.length; i++) { String[] keyval = pairs[i].split("="); if(keyval.length==2) { String key = keyval[0]; String value = ""; try { value = java.net.URLDecoder.decode(keyval[1], "UTF-8"); } catch (UnsupportedEncodingException _uee) { Log.e(TAG, "Unsupported Encoding: " + _uee.getMessage()); } retMap.put(key, value); } } return retMap; }
And the strings.xml in res/values:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">WebAppStarter</string> <string name="homescreen_link">History Book</string> </resources>
That's it. You can configure the Homescreen link name to search for in strings.xml. When the app finds the string, it parses the intent string and creates a new intent to start Chrome as a Full Screen Activity Web App.