diff --git a/api/current.txt b/api/current.txt index 18eb3d840121f..df6005def844c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4456,6 +4456,7 @@ package android.app { field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText"; field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon"; field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big"; + field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession"; field public static final java.lang.String EXTRA_PEOPLE = "android.people"; field public static final java.lang.String EXTRA_PICTURE = "android.picture"; field public static final java.lang.String EXTRA_PROGRESS = "android.progress"; @@ -4624,6 +4625,14 @@ package android.app { method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence); } + public static class Notification.MediaStyle extends android.app.Notification.Style { + ctor public Notification.MediaStyle(); + ctor public Notification.MediaStyle(android.app.Notification.Builder); + method public android.app.Notification buildStyled(android.app.Notification); + method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSessionToken); + method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...); + } + public static abstract class Notification.Style { ctor public Notification.Style(); method public android.app.Notification build(); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 4524822678aa8..dfd927f768114 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -23,6 +23,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.media.AudioManager; +import android.media.session.MediaSessionToken; import android.net.Uri; import android.os.BadParcelableException; import android.os.Build; @@ -686,6 +687,11 @@ public class Notification implements Parcelable * notifications, each of which was supplied to {@link InboxStyle#addLine(CharSequence)}. */ public static final String EXTRA_TEXT_LINES = "android.textLines"; + + /** + * {@link #extras} key: A string representing the name of the specific + * {@link android.app.Notification.Style} used to create this notification. + */ public static final String EXTRA_TEMPLATE = "android.template"; /** @@ -725,6 +731,13 @@ public class Notification implements Parcelable */ public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri"; + /** + * {@link #extras} key: A + * {@link android.media.session.MediaSessionToken} associated with a + * {@link android.app.Notification.MediaStyle} notification. + */ + public static final String EXTRA_MEDIA_SESSION = "android.mediaSession"; + /** * Value for {@link #EXTRA_AS_HEADS_UP}. * @hide @@ -2298,14 +2311,12 @@ public class Notification implements Parcelable int N = mActions.size(); if (N > 0) { - // Log.d("Notification", "has actions: " + mContentText); big.setViewVisibility(R.id.actions, View.VISIBLE); big.setViewVisibility(R.id.action_divider, View.VISIBLE); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; big.removeAllViews(R.id.actions); for (int i=0; i + * Notification noti = new Notification.Builder() + * .setSmallIcon(R.drawable.ic_stat_player) + * .setContentTitle("Track title") // these three lines are optional + * .setContentText("Artist - Album") // if you use + * .setLargeIcon(albumArtBitmap)) // setMediaSession(token, true) + * .setMediaSession(mySession, true) + * .setStyle(new Notification.MediaStyle()) + * .build(); + * + * + * @see Notification#bigContentView + */ + public static class MediaStyle extends Style { + static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 2; + static final int MAX_MEDIA_BUTTONS = 5; + + private int[] mActionsToShowInCompact = null; + private MediaSessionToken mToken; + + public MediaStyle() { + } + + public MediaStyle(Builder builder) { + setBuilder(builder); + } + + /** + * Request up to 2 actions (by index in the order of addition) to be shown in the compact + * notification view. + */ + public MediaStyle setShowActionsInCompactView(int...actions) { + mActionsToShowInCompact = actions; + return this; + } + + /** + * Attach a {@link android.media.session.MediaSessionToken} to this Notification to provide + * additional playback information and control to the SystemUI. + */ + public MediaStyle setMediaSession(MediaSessionToken token) { + mToken = token; + return this; + } + + @Override + public Notification buildStyled(Notification wip) { + wip.contentView = makeMediaContentView(); + wip.bigContentView = makeMediaBigContentView(); + + return wip; + } + + /** @hide */ + @Override + public void addExtras(Bundle extras) { + super.addExtras(extras); + + if (mToken != null) { + extras.putParcelable(EXTRA_MEDIA_SESSION, mToken); + } + } + + private RemoteViews generateMediaActionButton(Action action) { + final boolean tombstone = (action.actionIntent == null); + RemoteViews button = new RemoteViews(mBuilder.mContext.getPackageName(), + R.layout.notification_quantum_media_action); + button.setImageViewResource(R.id.action0, action.icon); + if (!tombstone) { + button.setOnClickPendingIntent(R.id.action0, action.actionIntent); + } + button.setContentDescription(R.id.action0, action.title); + return button; + } + + private RemoteViews makeMediaContentView() { + RemoteViews view = mBuilder.applyStandardTemplate( + R.layout.notification_template_quantum_media, true /* 1U */); + + final int numActions = mBuilder.mActions.size(); + final int N = mActionsToShowInCompact == null + ? 0 + : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT); + if (N > 0) { + view.removeAllViews(R.id.actions); + for (int i = 0; i < N; i++) { + if (i >= numActions) { + throw new IllegalArgumentException(String.format( + "setShowActionsInCompactView: action %d out of bounds (max %d)", + i, numActions - 1)); + } + + final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]); + final RemoteViews button = generateMediaActionButton(action); + view.addView(R.id.actions, button); + } + } + return view; + } + + private RemoteViews makeMediaBigContentView() { + RemoteViews big = mBuilder.applyStandardTemplate( + R.layout.notification_template_quantum_big_media, false); + + final int N = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS); + if (N > 0) { + big.removeAllViews(R.id.actions); + for (int i=0; i + + + + + + + + + + + + diff --git a/core/res/res/layout/notification_quantum_media_action.xml b/core/res/res/layout/notification_quantum_media_action.xml new file mode 100644 index 0000000000000..17f0848e66452 --- /dev/null +++ b/core/res/res/layout/notification_quantum_media_action.xml @@ -0,0 +1,25 @@ + + + + diff --git a/core/res/res/layout/notification_template_part_chronometer.xml b/core/res/res/layout/notification_template_part_chronometer.xml index aa9c4dc984e44..9b6e6c579f9c6 100644 --- a/core/res/res/layout/notification_template_part_chronometer.xml +++ b/core/res/res/layout/notification_template_part_chronometer.xml @@ -15,7 +15,7 @@ --> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/layout/notification_template_quantum_media.xml b/core/res/res/layout/notification_template_quantum_media.xml new file mode 100644 index 0000000000000..14fabce9584f5 --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_media.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index ad29505bb60f1..5a2609eafa8e7 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -129,6 +129,10 @@ #ffa3a3a3 #ff555555 + #00000000 + #40FFFFFF + #FFFFFFFF + #ffffffff #80000000 diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index fd57c5e9d7f00..4a27ebe5b99fc 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -299,6 +299,10 @@ please see styles_device_defaults.xml. +