diff options
| author | Dan Sandler <dsandler@android.com> | 2015-05-06 15:18:49 -0400 |
|---|---|---|
| committer | Daniel Sandler <dsandler@android.com> | 2015-05-15 12:35:21 +0000 |
| commit | d63f9321e62064660d426efd5abbd885c4a24652 (patch) | |
| tree | 96d7252ec6ba03410097d24a93abed13e52516d7 /core/java/android | |
| parent | aee0c2ce39fe92716bb76d33d6f8cc8789467cf6 (diff) | |
| download | frameworks_base-d63f9321e62064660d426efd5abbd885c4a24652.zip frameworks_base-d63f9321e62064660d426efd5abbd885c4a24652.tar.gz frameworks_base-d63f9321e62064660d426efd5abbd885c4a24652.tar.bz2 | |
Icon support comes to Notification.
And you may ask yourself: what is that beautiful icon?
And you may ask yourself: where does that API go to?
And you may ask yourself: is it a resource? is it a Bitmap?
And you may say to yourself: my god, what have I done
(This patch fixes a number of bugs in the initial
implementation, but other than that, it's the same as it
ever was.)
Bug: 18568715
Bug: 21141842
Change-Id: I1d3f9427abd7f0bb57e533fcfac708851ff644b6
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/Notification.java | 149 | ||||
| -rw-r--r-- | core/java/android/app/NotificationManager.java | 9 |
2 files changed, 120 insertions, 38 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 49b2549..3309443 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -30,6 +30,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.session.MediaSession; @@ -885,6 +886,9 @@ public class Notification implements Parcelable */ public static final int HEADS_UP_REQUESTED = 2; + private Icon mSmallIcon; + private Icon mLargeIcon; + /** * Structure to encapsulate a named action that can be shown as part of this notification. * It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is @@ -1362,7 +1366,7 @@ public class Notification implements Parcelable int version = parcel.readInt(); when = parcel.readLong(); - icon = parcel.readInt(); + mSmallIcon = Icon.CREATOR.createFromParcel(parcel); number = parcel.readInt(); if (parcel.readInt() != 0) { contentIntent = PendingIntent.CREATOR.createFromParcel(parcel); @@ -1380,7 +1384,7 @@ public class Notification implements Parcelable contentView = RemoteViews.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { - largeIcon = Bitmap.CREATOR.createFromParcel(parcel); + mLargeIcon = Icon.CREATOR.createFromParcel(parcel); } defaults = parcel.readInt(); flags = parcel.readInt(); @@ -1445,7 +1449,7 @@ public class Notification implements Parcelable */ public void cloneInto(Notification that, boolean heavy) { that.when = this.when; - that.icon = this.icon; + that.mSmallIcon = this.mSmallIcon; that.number = this.number; // PendingIntents are global, so there's no reason (or way) to clone them. @@ -1462,8 +1466,8 @@ public class Notification implements Parcelable if (heavy && this.contentView != null) { that.contentView = this.contentView.clone(); } - if (heavy && this.largeIcon != null) { - that.largeIcon = Bitmap.createBitmap(this.largeIcon); + if (heavy && this.mLargeIcon != null) { + that.mLargeIcon = this.mLargeIcon; } that.iconLevel = this.iconLevel; that.sound = this.sound; // android.net.Uri is immutable @@ -1544,7 +1548,7 @@ public class Notification implements Parcelable contentView = null; bigContentView = null; headsUpContentView = null; - largeIcon = null; + mLargeIcon = null; if (extras != null) { extras.remove(Notification.EXTRA_LARGE_ICON); extras.remove(Notification.EXTRA_LARGE_ICON_BIG); @@ -1586,7 +1590,7 @@ public class Notification implements Parcelable parcel.writeInt(1); parcel.writeLong(when); - parcel.writeInt(icon); + mSmallIcon.writeToParcel(parcel, 0); parcel.writeInt(number); if (contentIntent != null) { parcel.writeInt(1); @@ -1618,9 +1622,9 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } - if (largeIcon != null) { + if (mLargeIcon != null) { parcel.writeInt(1); - largeIcon.writeToParcel(parcel, 0); + mLargeIcon.writeToParcel(parcel, 0); } else { parcel.writeInt(0); } @@ -1865,6 +1869,35 @@ public class Notification implements Parcelable } /** + * The small icon representing this notification in the status bar and content view. + * + * @return the small icon representing this notification. + * + * @see Builder#getSmallIcon() + * @see Builder#setSmallIcon(Icon) + */ + public Icon getSmallIcon() { + return mSmallIcon; + } + + /** + * Used when notifying to clean up legacy small icons. + * @hide + */ + public void setSmallIcon(Icon icon) { + mSmallIcon = icon; + } + + /** + * The large icon shown in this notification's content view. + * @see Builder#getLargeIcon() + * @see Builder#setLargeIcon(Icon) + */ + public Icon getLargeIcon() { + return mLargeIcon; + } + + /** * @hide */ public boolean isValid() { @@ -1966,7 +1999,7 @@ public class Notification implements Parcelable private Context mContext; private long mWhen; - private int mSmallIcon; + private Icon mSmallIcon, mLargeIcon; private int mSmallIconLevel; private int mNumber; private CharSequence mContentTitle; @@ -1979,7 +2012,6 @@ public class Notification implements Parcelable private PendingIntent mFullScreenIntent; private CharSequence mTickerText; private RemoteViews mTickerView; - private Bitmap mLargeIcon; private Uri mSound; private int mAudioStreamType; private AudioAttributes mAudioAttributes; @@ -2160,8 +2192,9 @@ public class Notification implements Parcelable * @see Notification#icon */ public Builder setSmallIcon(@DrawableRes int icon) { - mSmallIcon = icon; - return this; + return setSmallIcon(icon != 0 + ? Icon.createWithResource(mContext, icon) + : null); } /** @@ -2176,8 +2209,20 @@ public class Notification implements Parcelable * @see Notification#iconLevel */ public Builder setSmallIcon(@DrawableRes int icon, int level) { - mSmallIcon = icon; mSmallIconLevel = level; + return setSmallIcon(icon); + } + + /** + * Set the small icon, which will be used to represent the notification in the + * status bar and content view (unless overriden there by a + * {@link #setLargeIcon(Bitmap) large icon}). + * + * @param icon An Icon object to use. + * @see Notification#icon + */ + public Builder setSmallIcon(Icon icon) { + mSmallIcon = icon; return this; } @@ -2324,14 +2369,24 @@ public class Notification implements Parcelable } /** - * Add a large icon to the notification (and the ticker on some devices). + * Add a large icon to the notification content view. * * In the platform template, this image will be shown on the left of the notification view - * in place of the {@link #setSmallIcon(int) small icon} (which will move to the right side). + * in place of the {@link #setSmallIcon(Icon) small icon} (which will be placed in a small + * badge atop the large icon). + */ + public Builder setLargeIcon(Bitmap b) { + return setLargeIcon(b != null ? Icon.createWithBitmap(b) : null); + } + + /** + * Add a large icon to the notification content view. * - * @see Notification#largeIcon + * In the platform template, this image will be shown on the left of the notification view + * in place of the {@link #setSmallIcon(Icon) small icon} (which will be placed in a small + * badge atop the large icon). */ - public Builder setLargeIcon(Bitmap icon) { + public Builder setLargeIcon(Icon icon) { mLargeIcon = icon; return this; } @@ -2840,13 +2895,13 @@ public class Notification implements Parcelable boolean contentTextInLine2 = false; if (mLargeIcon != null) { - contentView.setImageViewBitmap(R.id.icon, mLargeIcon); + contentView.setImageViewIcon(R.id.icon, mLargeIcon); processLargeLegacyIcon(mLargeIcon, contentView); - contentView.setImageViewResource(R.id.right_icon, mSmallIcon); + contentView.setImageViewIcon(R.id.right_icon, mSmallIcon); contentView.setViewVisibility(R.id.right_icon, View.VISIBLE); processSmallRightIcon(mSmallIcon, contentView); } else { // small icon at left - contentView.setImageViewResource(R.id.icon, mSmallIcon); + contentView.setImageViewIcon(R.id.icon, mSmallIcon); contentView.setViewVisibility(R.id.icon, View.VISIBLE); processSmallIconAsLarge(mSmallIcon, contentView); } @@ -3086,14 +3141,16 @@ public class Notification implements Parcelable /** * Apply any necessary background to smallIcons being used in the largeIcon spot. */ - private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) { + private void processSmallIconAsLarge(Icon largeIcon, RemoteViews contentView) { if (!isLegacy()) { contentView.setDrawableParameters(R.id.icon, false, -1, 0xFFFFFFFF, PorterDuff.Mode.SRC_ATOP, -1); - } - if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) { applyLargeIconBackground(contentView); + } else { + if (mColorUtil.isGrayscaleIcon(mContext, largeIcon)) { + applyLargeIconBackground(contentView); + } } } @@ -3102,8 +3159,9 @@ public class Notification implements Parcelable * if it's grayscale). */ // TODO: also check bounds, transparency, that sort of thing. - private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) { - if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) { + private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) { + if (largeIcon != null && isLegacy() + && mColorUtil.isGrayscaleIcon(mContext, largeIcon)) { applyLargeIconBackground(contentView); } else { removeLargeIconBackground(contentView); @@ -3137,14 +3195,16 @@ public class Notification implements Parcelable /** * Recolor small icons when used in the R.id.right_icon slot. */ - private void processSmallRightIcon(int smallIconDrawableId, - RemoteViews contentView) { + private void processSmallRightIcon(Icon smallIcon, RemoteViews contentView) { if (!isLegacy()) { contentView.setDrawableParameters(R.id.right_icon, false, -1, 0xFFFFFFFF, PorterDuff.Mode.SRC_ATOP, -1); } - if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) { + final boolean gray = isLegacy() + && smallIcon.getType() == Icon.TYPE_RESOURCE + && mColorUtil.isGrayscaleIcon(mContext, smallIcon.getResId()); + if (!isLegacy() || gray) { contentView.setInt(R.id.right_icon, "setBackgroundResource", R.drawable.notification_icon_legacy_bg); @@ -3180,7 +3240,10 @@ public class Notification implements Parcelable public Notification buildUnstyled() { Notification n = new Notification(); n.when = mWhen; - n.icon = mSmallIcon; + n.mSmallIcon = mSmallIcon; + if (mSmallIcon.getType() == Icon.TYPE_RESOURCE) { + n.icon = mSmallIcon.getResId(); + } n.iconLevel = mSmallIconLevel; n.number = mNumber; @@ -3192,7 +3255,10 @@ public class Notification implements Parcelable n.fullScreenIntent = mFullScreenIntent; n.tickerText = mTickerText; n.tickerView = makeTickerView(); - n.largeIcon = mLargeIcon; + n.mLargeIcon = mLargeIcon; + if (mLargeIcon != null && mLargeIcon.getType() == Icon.TYPE_BITMAP) { + n.largeIcon = mLargeIcon.getBitmap(); + } n.sound = mSound; n.audioStreamType = mAudioStreamType; n.audioAttributes = mAudioAttributes; @@ -3242,7 +3308,7 @@ public class Notification implements Parcelable extras.putCharSequence(EXTRA_TEXT, mContentText); extras.putCharSequence(EXTRA_SUB_TEXT, mSubText); extras.putCharSequence(EXTRA_INFO_TEXT, mContentInfo); - extras.putInt(EXTRA_SMALL_ICON, mSmallIcon); + extras.putParcelable(EXTRA_SMALL_ICON, mSmallIcon); extras.putInt(EXTRA_PROGRESS, mProgress); extras.putInt(EXTRA_PROGRESS_MAX, mProgressMax); extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate); @@ -3430,7 +3496,7 @@ public class Notification implements Parcelable // Notification fields. mWhen = n.when; - mSmallIcon = n.icon; + mSmallIcon = n.mSmallIcon; mSmallIconLevel = n.iconLevel; mNumber = n.number; @@ -3441,7 +3507,7 @@ public class Notification implements Parcelable mFullScreenIntent = n.fullScreenIntent; mTickerText = n.tickerText; mTickerView = n.tickerView; - mLargeIcon = n.largeIcon; + mLargeIcon = n.mLargeIcon; mSound = n.sound; mAudioStreamType = n.audioStreamType; mAudioAttributes = n.audioAttributes; @@ -3472,7 +3538,7 @@ public class Notification implements Parcelable mContentText = extras.getCharSequence(EXTRA_TEXT); mSubText = extras.getCharSequence(EXTRA_SUB_TEXT); mContentInfo = extras.getCharSequence(EXTRA_INFO_TEXT); - mSmallIcon = extras.getInt(EXTRA_SMALL_ICON); + mSmallIcon = extras.getParcelable(EXTRA_SMALL_ICON); mProgress = extras.getInt(EXTRA_PROGRESS); mProgressMax = extras.getInt(EXTRA_PROGRESS_MAX); mProgressIndeterminate = extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE); @@ -3764,7 +3830,7 @@ public class Notification implements Parcelable */ public static class BigPictureStyle extends Style { private Bitmap mPicture; - private Bitmap mBigLargeIcon; + private Icon mBigLargeIcon; private boolean mBigLargeIconSet = false; public BigPictureStyle() { @@ -3803,8 +3869,15 @@ public class Notification implements Parcelable * Override the large icon when the big notification is shown. */ public BigPictureStyle bigLargeIcon(Bitmap b) { + return bigLargeIcon(b != null ? Icon.createWithBitmap(b) : null); + } + + /** + * Override the large icon when the big notification is shown. + */ + public BigPictureStyle bigLargeIcon(Icon icon) { mBigLargeIconSet = true; - mBigLargeIcon = b; + mBigLargeIcon = icon; return this; } @@ -3815,7 +3888,7 @@ public class Notification implements Parcelable // 1. mBigLargeIconSet -> mBigLargeIcon (null or non-null) applies, overrides // mLargeIcon // 2. !mBigLargeIconSet -> mLargeIcon applies - Bitmap oldLargeIcon = null; + Icon oldLargeIcon = null; if (mBigLargeIconSet) { oldLargeIcon = mBuilder.mLargeIcon; mBuilder.mLargeIcon = mBigLargeIcon; diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index e4bbe27..557964b 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -23,6 +23,7 @@ import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; import android.content.pm.ParceledListSlice; +import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -204,6 +205,7 @@ public class NotificationManager notification.sound.checkFileUriExposed("Notification.sound"); } } + fixLegacySmallIcon(notification, pkg); if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); Notification stripped = notification.clone(); Builder.stripForDelivery(stripped); @@ -231,6 +233,7 @@ public class NotificationManager notification.sound.checkFileUriExposed("Notification.sound"); } } + fixLegacySmallIcon(notification, pkg); if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); Notification stripped = notification.clone(); Builder.stripForDelivery(stripped); @@ -244,6 +247,12 @@ public class NotificationManager } } + private void fixLegacySmallIcon(Notification n, String pkg) { + if (n.getSmallIcon() == null && n.icon != 0) { + n.setSmallIcon(Icon.createWithResource(pkg, n.icon)); + } + } + /** * Cancel a previously shown notification. If it's transient, the view * will be hidden. If it's persistent, it will be removed from the status |
