OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.webapk.shell_apk; | 5 package org.chromium.webapk.shell_apk; |
6 | 6 |
7 import android.app.Activity; | |
8 import android.content.ActivityNotFoundException; | 7 import android.content.ActivityNotFoundException; |
9 import android.content.Intent; | 8 import android.content.Intent; |
10 import android.content.pm.ApplicationInfo; | 9 import android.content.pm.ApplicationInfo; |
11 import android.content.pm.PackageManager; | 10 import android.content.pm.PackageManager; |
12 import android.content.pm.PackageManager.NameNotFoundException; | 11 import android.content.pm.PackageManager.NameNotFoundException; |
13 import android.net.Uri; | 12 import android.net.Uri; |
14 import android.os.Bundle; | 13 import android.os.Bundle; |
14 import android.support.v4.app.DialogFragment; | |
15 import android.support.v4.app.FragmentActivity; | |
16 import android.text.TextUtils; | |
15 import android.util.Log; | 17 import android.util.Log; |
16 | 18 |
17 import org.chromium.webapk.lib.common.WebApkConstants; | 19 import org.chromium.webapk.lib.common.WebApkConstants; |
18 import org.chromium.webapk.lib.common.WebApkMetaDataKeys; | 20 import org.chromium.webapk.lib.common.WebApkMetaDataKeys; |
19 | 21 |
20 import java.net.URISyntaxException; | 22 import java.net.MalformedURLException; |
23 import java.net.URL; | |
24 import java.util.Set; | |
21 | 25 |
22 /** | 26 /** |
23 * WebAPK's main Activity. | 27 * WebAPK's main Activity. |
24 */ | 28 */ |
25 public class MainActivity extends Activity { | 29 public class MainActivity |
30 extends FragmentActivity implements ChooseHostBrowserDialogFragment.Dial ogListener { | |
26 private static final String TAG = "cr_MainActivity"; | 31 private static final String TAG = "cr_MainActivity"; |
27 | 32 |
28 /** | 33 /** |
29 * Name of class which launches browser in WebAPK mode. | 34 * Name of class which launches browser in WebAPK mode. |
30 */ | 35 */ |
31 private static final String HOST_BROWSER_LAUNCHER_CLASS_NAME = | 36 private static final String HOST_BROWSER_LAUNCHER_CLASS_NAME = |
32 "org.chromium.webapk.lib.runtime_library.HostBrowserLauncher"; | 37 "org.chromium.webapk.lib.runtime_library.HostBrowserLauncher"; |
33 | 38 |
34 // Action for launching {@link WebappLauncherActivity}. Must stay in sync wi th | 39 // Action for launching {@link WebappLauncherActivity}. Must stay in sync wi th |
35 // {@link WebappLauncherActivity#ACTION_START_WEBAPP}. | 40 // {@link WebappLauncherActivity#ACTION_START_WEBAPP}. |
36 public static final String ACTION_START_WEBAPK = | 41 public static final String ACTION_START_WEBAPK = |
37 "com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_W EBAPP"; | 42 "com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_W EBAPP"; |
38 | 43 |
39 // Must stay in sync with | 44 // Must stay in sync with |
40 // {@link org.chromium.chrome.browser.ShortcutHelper#REUSE_URL_MATCHING_TAB_ ELSE_NEW_TAB}. | 45 // {@link org.chromium.chrome.browser.ShortcutHelper#REUSE_URL_MATCHING_TAB_ ELSE_NEW_TAB}. |
41 private static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB = | 46 private static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB = |
42 "REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB"; | 47 "REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB"; |
43 | 48 |
44 /** | 49 /** |
45 * Key for passing app icon id. | 50 * Key for passing app icon id. |
46 */ | 51 */ |
47 private static final String KEY_APP_ICON_ID = "app_icon_id"; | 52 private static final String KEY_APP_ICON_ID = "app_icon_id"; |
48 | 53 |
54 private String mOverrideUrl; | |
55 private String mStartUrl; | |
56 | |
49 /** | 57 /** |
50 * Creates install Intent. | 58 * Creates install Intent. |
51 * @param packageName Package to install. | 59 * @param packageName Package to install. |
52 * @return The intent. | 60 * @return The intent. |
53 */ | 61 */ |
54 public static Intent createInstallIntent(String packageName) { | 62 public static Intent createInstallIntent(String packageName) { |
55 String marketUrl = "market://details?id=" + packageName; | 63 String marketUrl = "market://details?id=" + packageName; |
56 return new Intent(Intent.ACTION_VIEW, Uri.parse(marketUrl)); | 64 return new Intent(Intent.ACTION_VIEW, Uri.parse(marketUrl)); |
57 } | 65 } |
58 | 66 |
59 @Override | 67 @Override |
60 protected void onCreate(Bundle savedInstanceState) { | 68 protected void onCreate(Bundle savedInstanceState) { |
61 super.onCreate(savedInstanceState); | 69 super.onCreate(savedInstanceState); |
62 launch(); | 70 mOverrideUrl = getOverrideUrl(); |
63 finish(); | 71 mStartUrl = (mOverrideUrl != null) ? mOverrideUrl : getStartUrl(); |
64 } | 72 if (mStartUrl == null) { |
65 | 73 finish(); |
66 /** | |
67 * Launches WebAPK. | |
68 */ | |
69 private void launch() { | |
70 String overrideUrl = getOverrideUrl(); | |
71 String startUrl = (overrideUrl != null) ? overrideUrl : getStartUrl(); | |
72 if (startUrl == null) { | |
73 return; | 74 return; |
74 } | 75 } |
75 | 76 |
76 if (launchHostBrowserInWebApkMode(startUrl, overrideUrl)) { | 77 Log.v(TAG, "Url of the WebAPK: " + mStartUrl); |
77 return; | |
78 } | |
79 if (launchBrowser(startUrl)) { | |
80 return; | |
81 } | |
82 installBrowser(); | |
83 } | |
84 | |
85 /** | |
86 * Launches host browser in WebAPK mode. | |
87 * @return True if successful. | |
88 */ | |
89 private boolean launchHostBrowserInWebApkMode(String startUrl, String overri deUrl) { | |
90 Log.v(TAG, "Url of the WebAPK: " + startUrl); | |
91 String packageName = getPackageName(); | 78 String packageName = getPackageName(); |
92 Log.v(TAG, "Package name of the WebAPK:" + packageName); | 79 Log.v(TAG, "Package name of the WebAPK:" + packageName); |
93 | 80 |
94 String runtimeHost = WebApkUtils.getHostBrowserPackageName(this); | 81 String runtimeHost = WebApkUtils.getHostBrowserPackageName(this); |
82 if (!TextUtils.isEmpty(runtimeHost) && launchInHostBrowser(runtimeHost)) { | |
83 finish(); | |
84 return; | |
85 } | |
86 | |
87 String hostUrl = ""; | |
88 try { | |
89 hostUrl = new URL(mStartUrl).getHost(); | |
90 } catch (MalformedURLException e) { | |
91 Log.e(TAG, "Invalid URL of the WebApk."); | |
92 finish(); | |
93 return; | |
94 } | |
pkotwicz
2017/05/26 22:38:39
Don't you need to call WebApkUtils#deleteSharedPre
Xi Han
2017/05/29 21:18:56
You are right. Call it inside launchiInHostBrowser
| |
95 DialogFragment dialogFragment = ChooseHostBrowserDialogFragment.newInsta nce(hostUrl); | |
96 dialogFragment.show(getSupportFragmentManager(), "ChooseHostBrowserDialo gFragment"); | |
97 } | |
98 | |
99 /** Retrieves URL from the intent's data. Returns null if a URL could not be retrieved. */ | |
100 private String getOverrideUrl() { | |
101 String overrideUrl = getIntent().getDataString(); | |
102 if (overrideUrl != null && overrideUrl.startsWith("https:")) { | |
103 return overrideUrl; | |
104 } | |
105 return null; | |
106 } | |
107 | |
108 /** Returns the start URL from the Android Manifest. */ | |
109 private String getStartUrl() { | |
110 ApplicationInfo appInfo; | |
111 try { | |
112 appInfo = getPackageManager().getApplicationInfo( | |
113 getPackageName(), PackageManager.GET_META_DATA); | |
114 } catch (NameNotFoundException e) { | |
115 return null; | |
116 } | |
117 return appInfo.metaData.getString(WebApkMetaDataKeys.START_URL); | |
118 } | |
119 | |
120 @Override | |
121 public void onHostBrowserSelected(String runtimeHost) { | |
122 Set<String> installedBrowsers = WebApkUtils.getInstalledBrowsers(getPack ageManager()); | |
123 if (installedBrowsers.contains(runtimeHost)) { | |
124 launchInHostBrowser(runtimeHost); | |
125 } else { | |
126 installBrowser(runtimeHost); | |
127 } | |
pkotwicz
2017/05/26 22:38:39
Don't you need to call WebApkUtils#deleteSharedPre
Xi Han
2017/05/29 21:18:55
Add a call in |launchInHostBrowser|.
| |
128 // It is safe to cache the runtimeHost to the share pref if user didn't install the browser | |
129 // in {@link installBrowser}. On next launch, | |
130 // {@link WebApkUtils#getHostBrowserPackageName()} will catch it, and th e dialog to choose | |
131 // host browser will show again. If user did install the browser chosen, saving the | |
132 // runtimeHost to the shared pref can avoid showing the dialog. | |
133 WebApkUtils.writeHostBrowserToSharedPref(this, runtimeHost); | |
134 finish(); | |
135 } | |
136 | |
137 @Override | |
138 public void onQuit() { | |
139 finish(); | |
140 } | |
141 | |
142 private boolean launchInHostBrowser(String runtimeHost) { | |
95 boolean forceNavigation = false; | 143 boolean forceNavigation = false; |
96 int source = getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, 0); | 144 int source = getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, 0); |
97 if (overrideUrl != null) { | 145 if (mOverrideUrl != null) { |
98 if (source == WebApkConstants.SHORTCUT_SOURCE_UNKNOWN) { | 146 if (source == WebApkConstants.SHORTCUT_SOURCE_UNKNOWN) { |
99 source = WebApkConstants.SHORTCUT_SOURCE_EXTERNAL_INTENT; | 147 source = WebApkConstants.SHORTCUT_SOURCE_EXTERNAL_INTENT; |
100 } | 148 } |
101 forceNavigation = getIntent().getBooleanExtra( | 149 forceNavigation = getIntent().getBooleanExtra( |
102 WebApkConstants.EXTRA_WEBAPK_FORCE_NAVIGATION, true); | 150 WebApkConstants.EXTRA_WEBAPK_FORCE_NAVIGATION, true); |
103 } | 151 } |
104 | 152 |
105 // The override URL is non null when the WebAPK is launched from a deep link. The WebAPK | 153 // The override URL is non null when the WebAPK is launched from a deep link. The WebAPK |
106 // should navigate to the URL in the deep link even if the WebAPK is alr eady open. | 154 // should navigate to the URL in the deep link even if the WebAPK is alr eady open. |
107 Intent intent = new Intent(); | 155 Intent intent = new Intent(); |
108 intent.setAction(ACTION_START_WEBAPK); | 156 intent.setAction(ACTION_START_WEBAPK); |
109 intent.setPackage(runtimeHost); | 157 intent.setPackage(runtimeHost); |
110 intent.putExtra(WebApkConstants.EXTRA_URL, startUrl) | 158 intent.putExtra(WebApkConstants.EXTRA_URL, mStartUrl) |
111 .putExtra(WebApkConstants.EXTRA_SOURCE, source) | 159 .putExtra(WebApkConstants.EXTRA_SOURCE, source) |
112 .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName ) | 160 .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, getPackageN ame()) |
113 .putExtra(WebApkConstants.EXTRA_WEBAPK_FORCE_NAVIGATION, forceNa vigation); | 161 .putExtra(WebApkConstants.EXTRA_WEBAPK_FORCE_NAVIGATION, forceNa vigation); |
114 | 162 |
115 try { | 163 try { |
116 startActivity(intent); | 164 startActivity(intent); |
117 return true; | 165 return true; |
118 } catch (ActivityNotFoundException e) { | 166 } catch (ActivityNotFoundException e) { |
119 Log.w(TAG, "Unable to launch browser in WebAPK mode."); | 167 Log.w(TAG, "Unable to launch browser in WebAPK mode."); |
120 e.printStackTrace(); | 168 e.printStackTrace(); |
121 return false; | 169 return false; |
122 } | 170 } |
123 } | 171 } |
124 | 172 |
125 /** | 173 /** |
126 * Launches browser (not necessarily the host browser). | |
127 * @param startUrl URL to navigate browser to. | |
128 * @return True if successful. | |
129 */ | |
130 private boolean launchBrowser(String startUrl) { | |
131 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl)); | |
132 intent.addCategory(Intent.CATEGORY_BROWSABLE); | |
133 | |
134 // The WebAPK can handle {@link startUrl}. Set a selector to prevent the WebAPK from | |
135 // launching itself. | |
136 try { | |
137 Intent selectorIntent = Intent.parseUri("https://", Intent.URI_INTEN T_SCHEME); | |
138 intent.setSelector(selectorIntent); | |
139 } catch (URISyntaxException e) { | |
140 return false; | |
141 } | |
142 | |
143 // Add extras in case that the URL is launched in Chrome. | |
144 int source = | |
145 getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, Intent.URI _INTENT_SCHEME); | |
146 intent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true) | |
147 .putExtra(WebApkConstants.EXTRA_SOURCE, source); | |
148 | |
149 try { | |
150 startActivity(intent); | |
151 } catch (ActivityNotFoundException e) { | |
152 return false; | |
153 } | |
154 return true; | |
155 } | |
156 | |
157 /** | |
158 * Launches the Play Store with the host browser's page. | 174 * Launches the Play Store with the host browser's page. |
159 */ | 175 */ |
160 private void installBrowser() { | 176 private void installBrowser(String hostBrowserPackageName) { |
161 String hostBrowserPackageName = WebApkUtils.getHostBrowserPackageName(th is); | |
162 if (hostBrowserPackageName == null) { | |
163 return; | |
164 } | |
165 | |
166 try { | 177 try { |
167 startActivity(createInstallIntent(hostBrowserPackageName)); | 178 startActivity(createInstallIntent(hostBrowserPackageName)); |
168 } catch (ActivityNotFoundException e) { | 179 } catch (ActivityNotFoundException e) { |
169 } | 180 } |
170 } | 181 } |
171 | |
172 /** Retrieves URL from the intent's data. Returns null if a URL could not be retrieved. */ | |
173 private String getOverrideUrl() { | |
174 String overrideUrl = getIntent().getDataString(); | |
175 if (overrideUrl != null && overrideUrl.startsWith("https:")) { | |
176 return overrideUrl; | |
177 } | |
178 return null; | |
179 } | |
180 | |
181 /** Returns the start URL from the Android Manifest. */ | |
182 private String getStartUrl() { | |
183 ApplicationInfo appInfo; | |
184 try { | |
185 appInfo = getPackageManager().getApplicationInfo( | |
186 getPackageName(), PackageManager.GET_META_DATA); | |
187 } catch (NameNotFoundException e) { | |
188 return null; | |
189 } | |
190 return appInfo.metaData.getString(WebApkMetaDataKeys.START_URL); | |
191 } | |
192 } | 182 } |
OLD | NEW |