Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java

Issue 2872473002: Merge ChromeShortcutManager into ShortcutHelper. (Closed)
Patch Set: fix Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 6fcc9e915329bc248f897e33a9be34adb53a0853..f16c72f450e5f7e8896d478fb840bbb77b27c342 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -4,13 +4,17 @@
package org.chromium.chrome.browser;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -19,6 +23,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
@@ -26,6 +31,7 @@ import android.text.TextUtils;
import android.util.Base64;
import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.BuildInfo;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
@@ -33,7 +39,6 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.blink_public.platform.WebDisplayMode;
import org.chromium.chrome.R;
-import org.chromium.chrome.browser.webapps.ChromeShortcutManager;
import org.chromium.chrome.browser.webapps.ChromeWebApkHost;
import org.chromium.chrome.browser.webapps.WebApkInfo;
import org.chromium.chrome.browser.webapps.WebappActivity;
@@ -47,6 +52,9 @@ import org.chromium.ui.widget.Toast;
import org.chromium.webapk.lib.client.WebApkValidator;
import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -88,6 +96,8 @@ public class ShortcutHelper {
private static final String TAG = "ShortcutHelper";
+ private static final String INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";
+
// The activity class used for launching a WebApk.
private static final String WEBAPK_MAIN_ACTIVITY = "org.chromium.webapk.shell_apk.MainActivity";
@@ -99,6 +109,15 @@ public class ShortcutHelper {
private static final float GENERATED_ICON_PADDING_RATIO = 1.0f / 12.0f;
private static final float GENERATED_ICON_FONT_SIZE_RATIO = 1.0f / 3.0f;
+ // True when Android O's ShortcutManager.requestPinShortcut() is supported.
+ private static boolean sIsRequestPinShortcutSupported;
+
+ // True when it is already checked if ShortcutManager.requestPinShortcut() is supported.
+ private static boolean sCheckedIfRequestPinShortcutSupported;
+
+ // TODO(martiw): Use 'ShortcutInfo' instead of 'Object' below when compileSdk is bumped to O.
+ private static Object sShortcutManager;
+
/** Helper for generating home screen shortcuts. */
public static class Delegate {
/**
@@ -108,8 +127,12 @@ public class ShortcutHelper {
* @param intent Intent to fire when the shortcut is activated.
*/
public void addShortcutToHomescreen(String title, Bitmap icon, Intent shortcutIntent) {
- ChromeShortcutManager.getInstance().addShortcutToHomeScreen(
- title, icon, shortcutIntent);
+ if (isRequestPinShortcutSupported()) {
+ addShortcutWithShortcutManager(title, icon, shortcutIntent);
+ return;
+ }
+ Intent intent = createAddToHomeIntent(title, icon, shortcutIntent);
+ ContextUtils.getApplicationContext().sendBroadcast(intent);
}
/**
@@ -173,7 +196,7 @@ public class ShortcutHelper {
nativeOnWebappDataStored(callbackPointer);
}
});
- if (ChromeShortcutManager.getInstance().shouldShowToastWhenAddingShortcut()) {
+ if (shouldShowToastWhenAddingShortcut()) {
showAddedToHomescreenToast(userTitle);
}
}
@@ -192,8 +215,7 @@ public class ShortcutHelper {
Intent i = new Intent();
i.setClassName(packageName, WEBAPK_MAIN_ACTIVITY);
i.addCategory(Intent.CATEGORY_LAUNCHER);
- context.sendBroadcast(
- ChromeShortcutManager.createAddToHomeIntent(shortcutTitle, bitmap, i));
+ context.sendBroadcast(createAddToHomeIntent(shortcutTitle, bitmap, i));
} catch (NameNotFoundException e) {
e.printStackTrace();
}
@@ -212,11 +234,59 @@ public class ShortcutHelper {
shortcutIntent.putExtra(EXTRA_SOURCE, source);
shortcutIntent.setPackage(context.getPackageName());
sDelegate.addShortcutToHomescreen(userTitle, icon, shortcutIntent);
- if (ChromeShortcutManager.getInstance().shouldShowToastWhenAddingShortcut()) {
+ if (shouldShowToastWhenAddingShortcut()) {
showAddedToHomescreenToast(userTitle);
}
}
+ // TODO(martiw): Use Build.VERSION_CODES.O instead of hardcoded number when it is available.
+ @TargetApi(26)
+ private static void addShortcutWithShortcutManager(
+ String title, Bitmap icon, Intent shortcutIntent) {
+ String id = shortcutIntent.getStringExtra(ShortcutHelper.EXTRA_ID);
+ Context context = ContextUtils.getApplicationContext();
+
+ // The code in the try-block uses reflection in order to compile as it calls APIs newer than
+ // our compileSdkVersion of Android. The equivalent code without reflection looks like this:
+ // ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(context, id)
+ // .setShortLabel(title)
+ // .setLongLabel(title)
+ // .setIcon(Icon.createWithBitmap(icon))
+ // .setIntent(shortcutIntent)
+ // .build();
+ // sShortcutManager.requestPinShortcut(shortcutInfo, null);
+ // TODO(martiw): Remove the following reflection once compileSdk is bumped to O.
+ try {
+ Class<?> builderClass = Class.forName("android.content.pm.ShortcutInfo$Builder");
+ Constructor<?> builderConstructor =
+ builderClass.getDeclaredConstructor(Context.class, String.class);
+ Object shortcutBuilder = builderConstructor.newInstance(context, id);
+
+ Method setShortLabel = builderClass.getMethod("setShortLabel", CharSequence.class);
+ setShortLabel.invoke(shortcutBuilder, title);
+
+ Method setLongLabel = builderClass.getMethod("setLongLabel", CharSequence.class);
+ setLongLabel.invoke(shortcutBuilder, title);
+
+ Method setIcon = builderClass.getMethod("setIcon", Icon.class);
+ setIcon.invoke(shortcutBuilder, Icon.createWithBitmap(icon));
+
+ Method setIntent = builderClass.getMethod("setIntent", Intent.class);
+ setIntent.invoke(shortcutBuilder, shortcutIntent);
+
+ Method build = builderClass.getMethod("build");
+ Object shortcutInfo = build.invoke(shortcutBuilder);
+
+ Class<?> ShortcutInfoClass = Class.forName("android.content.pm.ShortcutInfo");
+ Method requestPinShortcut = sShortcutManager.getClass().getMethod(
+ "requestPinShortcut", ShortcutInfoClass, IntentSender.class);
+ requestPinShortcut.invoke(sShortcutManager, shortcutInfo, null);
+ } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
+ | InvocationTargetException | IllegalAccessException e) {
+ Log.e(TAG, "Error adding shortcut with ShortcutManager:", e);
+ }
+ }
+
/**
* Show toast to alert user that the shortcut was added to the home screen.
*/
@@ -270,6 +340,21 @@ public class ShortcutHelper {
}
}
+ /**
+ * Creates an intent that will add a shortcut to the home screen.
+ * @param title Title of the shortcut.
+ * @param icon Image that represents the shortcut.
+ * @param shortcutIntent Intent to fire when the shortcut is activated.
+ * @return Intent for the shortcut.
+ */
+ public static Intent createAddToHomeIntent(String title, Bitmap icon, Intent shortcutIntent) {
+ Intent i = new Intent(INSTALL_SHORTCUT);
+ i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
+ i.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
+ return i;
+ }
+
/**
* Creates a shortcut to launch a web app on the home screen.
* @param id Id of the web app.
@@ -342,8 +427,15 @@ public class ShortcutHelper {
* Utility method to check if a shortcut can be added to the home screen.
* @return if a shortcut can be added to the home screen under the current profile.
*/
+ // TODO(crbug.com/635567): Fix this properly.
+ @SuppressLint("WrongConstant")
public static boolean isAddToHomeIntentSupported() {
- return ChromeShortcutManager.getInstance().canAddShortcutToHomescreen();
+ if (isRequestPinShortcutSupported()) return true;
+ PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
+ Intent i = new Intent(INSTALL_SHORTCUT);
+ List<ResolveInfo> receivers =
+ pm.queryBroadcastReceivers(i, PackageManager.GET_INTENT_FILTERS);
+ return !receivers.isEmpty();
}
/**
@@ -623,6 +715,44 @@ public class ShortcutHelper {
return false;
}
+ private static boolean shouldShowToastWhenAddingShortcut() {
+ return !isRequestPinShortcutSupported();
+ }
+
+ private static boolean isRequestPinShortcutSupported() {
+ if (!sCheckedIfRequestPinShortcutSupported) {
+ if (BuildInfo.isAtLeastO()) {
+ checkIfRequestPinShortcutSupported();
+ }
+ sCheckedIfRequestPinShortcutSupported = true;
+ }
+ return sIsRequestPinShortcutSupported;
+ }
+
+ // TODO(martiw): Use Build.VERSION_CODES.O instead of hardcoded number when it is available.
+ @TargetApi(26)
+ private static void checkIfRequestPinShortcutSupported() {
+ // The code in the try-block uses reflection in order to compile as it calls APIs newer than
+ // our target version of Android. The equivalent code without reflection is as follows:
+ // sShortcutManager =
+ // ContextUtils.getApplicationContext().getSystemService(ShortcutManager.class);
+ // sIsRequestPinShortcutSupported = sShortcutManager.isRequestPinShortcutSupported();
+ // TODO(martiw): Remove the following reflection once compileSdk is bumped to O.
+ try {
+ Class<?> ShortcutManagerClass = Class.forName("android.content.pm.ShortcutManager");
+ sShortcutManager =
+ ContextUtils.getApplicationContext().getSystemService(ShortcutManagerClass);
+
+ Method isRequestPinShortcutSupported =
+ ShortcutManagerClass.getMethod("isRequestPinShortcutSupported");
+ sIsRequestPinShortcutSupported =
+ (boolean) isRequestPinShortcutSupported.invoke(sShortcutManager);
+ } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException
+ | IllegalAccessException e) {
+ Log.e(TAG, "Error checking if RequestPinShortcut is supported:", e);
+ }
+ }
+
private static int getSizeFromResourceInPx(Context context, int resource) {
return Math.round(context.getResources().getDimension(resource));
}

Powered by Google App Engine
This is Rietveld 408576698