Index: chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java |
index c5b0fc072f4f25b359cd9df80dd291e1933047ca..7a90f34d50cdd2ab0a81da8aeb74ce85b8d1bcd7 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java |
@@ -7,6 +7,8 @@ package org.chromium.chrome.browser.notifications; |
import android.annotation.TargetApi; |
import android.app.Notification; |
import android.app.PendingIntent; |
+import android.content.Context; |
+import android.content.res.Resources; |
import android.graphics.Bitmap; |
import android.graphics.Canvas; |
import android.graphics.Color; |
@@ -17,6 +19,7 @@ import android.graphics.drawable.Icon; |
import android.os.Build; |
import org.chromium.base.VisibleForTesting; |
+import org.chromium.chrome.browser.widget.RoundedIconGenerator; |
import java.util.ArrayList; |
import java.util.Arrays; |
@@ -56,11 +59,27 @@ public abstract class NotificationBuilderBase { |
static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024; |
/** |
+ * Background color for generated notification icons. |
+ */ |
+ @VisibleForTesting |
+ static final int NOTIFICATION_ICON_BG_COLOR = 0xFF969696; |
+ |
+ /** |
+ * Density-independent text size for generated notification icons. |
+ */ |
+ @VisibleForTesting |
+ static final int NOTIFICATION_ICON_TEXT_SIZE_DP = 28; |
+ |
+ /** |
* The maximum number of author provided action buttons. The settings button is not part of this |
* count. |
*/ |
private static final int MAX_AUTHOR_PROVIDED_ACTION_BUTTONS = 2; |
+ private final int mLargeIconWidthPx; |
+ private final int mLargeIconHeightPx; |
+ private final RoundedIconGenerator mIconGenerator; |
+ |
protected CharSequence mTitle; |
protected CharSequence mBody; |
protected CharSequence mOrigin; |
@@ -78,6 +97,14 @@ public abstract class NotificationBuilderBase { |
protected long mTimestamp; |
protected boolean mRenotify; |
+ public NotificationBuilderBase(Resources resources) { |
+ mLargeIconWidthPx = |
+ resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); |
+ mLargeIconHeightPx = |
+ resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); |
+ mIconGenerator = createIconGenerator(resources); |
+ } |
+ |
/** |
* Combines all of the options that have been set and returns a new Notification object. |
*/ |
@@ -238,6 +265,79 @@ public abstract class NotificationBuilderBase { |
return this; |
} |
+ /** |
+ * Gets the large icon for the notification. |
+ * |
+ * If a large icon was supplied to the builder, returns this icon, scaled to an appropriate size |
+ * if necessary. |
+ * |
+ * If no large icon was supplied then returns a default icon based on the notification origin. |
+ * |
+ * See {@link NotificationBuilderBase#ensureNormalizedIcon} for more details. |
+ */ |
+ protected Bitmap getNormalizedLargeIcon() { |
+ return ensureNormalizedIcon(mLargeIcon, mOrigin); |
+ } |
+ |
+ /** |
+ * Ensures the availability of an icon for the notification. |
+ * |
+ * If |icon| is a valid, non-empty Bitmap, the bitmap will be scaled to be of an appropriate |
+ * size for the current Android device. Otherwise, a default icon will be created based on the |
+ * origin the notification is being displayed for. |
+ * |
+ * @param icon The developer-provided icon they intend to use for the notification. |
+ * @param origin The origin the notification is being displayed for. |
+ * @return An appropriately sized icon to use for the notification. |
+ */ |
+ @VisibleForTesting |
+ public Bitmap ensureNormalizedIcon(Bitmap icon, CharSequence origin) { |
+ if (icon == null || icon.getWidth() == 0) { |
+ return origin != null ? mIconGenerator.generateIconForUrl(origin.toString(), true) |
+ : null; |
+ } |
+ if (icon.getWidth() > mLargeIconWidthPx || icon.getHeight() > mLargeIconHeightPx) { |
+ return Bitmap.createScaledBitmap( |
+ icon, mLargeIconWidthPx, mLargeIconHeightPx, false /* not filtered */); |
+ } |
+ return icon; |
+ } |
+ |
+ /** |
+ * Creates a public version of the notification to be displayed in sensitive contexts, such as |
+ * on the lockscreen, displaying just the site origin and badge or generated icon. |
+ */ |
+ protected Notification createPublicNotification(Context context) { |
+ // Use Android's Notification.Builder because we want the default small icon behaviour. |
+ Notification.Builder builder = |
+ new Notification.Builder(context) |
+ .setContentText(context.getString( |
+ org.chromium.chrome.R.string.notification_hidden_text)) |
+ .setSmallIcon(org.chromium.chrome.R.drawable.ic_chrome); |
+ |
+ // TODO Change the following version check to '== Build.VERSION_CODES.N' when we bump the |
+ // targetSdkVersion to 24. |
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { |
+ // On N, 'subtext' displays at the top of the notification and this looks better. |
+ builder.setSubText(mOrigin); |
+ } else { |
+ // Set origin as title on L & M, because they look odd without one. |
+ builder.setContentTitle(mOrigin); |
+ } |
+ |
+ // Use the badge if provided and SDK supports it, else use a generated icon. |
+ if (mSmallIconBitmap != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
+ // The Icon class was added in Android M. |
+ Bitmap publicIcon = mSmallIconBitmap.copy(mSmallIconBitmap.getConfig(), true); |
+ builder.setSmallIcon(Icon.createWithBitmap(publicIcon)); |
+ } else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M && mOrigin != null) { |
+ // Only set the large icon for L & M because on N(+?) it would add an extra icon on |
+ // the right hand side, which looks odd without a notification title. |
+ builder.setLargeIcon(mIconGenerator.generateIconForUrl(mOrigin.toString(), true)); |
+ } |
+ return builder.build(); |
+ } |
+ |
@Nullable |
private static CharSequence limitLength(@Nullable CharSequence input) { |
if (input == null) { |
@@ -290,4 +390,16 @@ public abstract class NotificationBuilderBase { |
Canvas canvas = new Canvas(bitmap); |
canvas.drawBitmap(bitmap, 0, 0, paint); |
} |
+ |
+ @VisibleForTesting |
+ static RoundedIconGenerator createIconGenerator(Resources resources) { |
+ int largeIconWidthPx = |
+ resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); |
+ int largeIconHeightPx = |
+ resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); |
+ float density = resources.getDisplayMetrics().density; |
+ int cornerRadiusPx = Math.min(largeIconWidthPx, largeIconHeightPx) / 2; |
+ return new RoundedIconGenerator(largeIconWidthPx, largeIconHeightPx, cornerRadiusPx, |
+ NOTIFICATION_ICON_BG_COLOR, NOTIFICATION_ICON_TEXT_SIZE_DP * density); |
+ } |
} |