在 Android 开始时以 Web-App 开始 Chrome
Start Chrome as Web-App on Android start
我有一个非常具体的问题。我已经在 Android 平板电脑上实现了一个 Web 应用程序,它将用于展览 (Outform iDisplay)。因此,Web App 必须在开机后直接启动。 after-boot 没有问题(用 "android.permission.RECEIVE_BOOT_COMPLETED" 广播),但我无法将 Chrome 启动为 Web-App。为了获得意图,我已经阅读了启动器收藏夹中的图标和这个片段:
//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());
}
Intent 字符串包含如下内容:
#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
这看起来不错,但是我如何在一个只有一个目的的小应用程序中启动这样的 Intent?
最后的小提示:我曾尝试将此东西打包到 webview 中,但 webview 由于 libc 错误而不断死机,所以这对我来说不是选择。
我终于让这个东西工作了。我走的路是对的,但一些 Chrome.apk 逆向工程帮助我完成了最后一英里。
我在 onCreate 中使用以下代码创建了一个虚拟 activity:
在主屏幕上搜索正确的条目,在我的例子中是 AOSP 启动器 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());
在这一点上,我希望将意图作为字符串。因此,解析字符串并创建一个新的意图:
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();
并且此函数从意图字符串中解析出意图参数:
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;
}
和res/values中的strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WebAppStarter</string>
<string name="homescreen_link">History Book</string>
</resources>
就是这样。您可以配置要在 strings.xml 中搜索的主屏幕 link 名称。当应用程序找到该字符串时,它会解析意图字符串并创建一个新意图以启动 Chrome 作为全屏 Activity Web 应用程序。
我有一个非常具体的问题。我已经在 Android 平板电脑上实现了一个 Web 应用程序,它将用于展览 (Outform iDisplay)。因此,Web App 必须在开机后直接启动。 after-boot 没有问题(用 "android.permission.RECEIVE_BOOT_COMPLETED" 广播),但我无法将 Chrome 启动为 Web-App。为了获得意图,我已经阅读了启动器收藏夹中的图标和这个片段:
//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());
}
Intent 字符串包含如下内容:
#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
这看起来不错,但是我如何在一个只有一个目的的小应用程序中启动这样的 Intent?
最后的小提示:我曾尝试将此东西打包到 webview 中,但 webview 由于 libc 错误而不断死机,所以这对我来说不是选择。
我终于让这个东西工作了。我走的路是对的,但一些 Chrome.apk 逆向工程帮助我完成了最后一英里。 我在 onCreate 中使用以下代码创建了一个虚拟 activity:
在主屏幕上搜索正确的条目,在我的例子中是 AOSP 启动器 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());
在这一点上,我希望将意图作为字符串。因此,解析字符串并创建一个新的意图:
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();
并且此函数从意图字符串中解析出意图参数:
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;
}
和res/values中的strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WebAppStarter</string>
<string name="homescreen_link">History Book</string>
</resources>
就是这样。您可以配置要在 strings.xml 中搜索的主屏幕 link 名称。当应用程序找到该字符串时,它会解析意图字符串并创建一个新意图以启动 Chrome 作为全屏 Activity Web 应用程序。