diff options
-rw-r--r-- | api/current.txt | 65 | ||||
-rw-r--r-- | core/java/android/app/Notification.java | 784 | ||||
-rw-r--r-- | core/java/android/app/RemoteInput.java | 32 | ||||
-rw-r--r-- | core/java/android/app/wearable/WearableActionExtensions.java | 176 | ||||
-rw-r--r-- | core/java/android/app/wearable/WearableNotificationExtensions.java | 702 |
5 files changed, 836 insertions, 923 deletions
diff --git a/api/current.txt b/api/current.txt index a829bdf..1aa4d2a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4538,13 +4538,22 @@ package android.app { ctor public Notification.Action.Builder(android.app.Notification.Action); method public android.app.Notification.Action.Builder addExtras(android.os.Bundle); method public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput); - method public android.app.Notification.Action.Builder apply(android.app.Notification.Action.Builder.Extender); method public android.app.Notification.Action build(); + method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender); method public android.os.Bundle getExtras(); } - public static abstract interface Notification.Action.Builder.Extender { - method public abstract android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder); + public static abstract interface Notification.Action.Extender { + method public abstract android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder); + } + + public static final class Notification.Action.WearableExtender implements android.app.Notification.Action.Extender { + ctor public Notification.Action.WearableExtender(); + ctor public Notification.Action.WearableExtender(android.app.Notification.Action); + method public android.app.Notification.Action.WearableExtender clone(); + method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder); + method public boolean isAvailableOffline(); + method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean); } public static class Notification.BigPictureStyle extends android.app.Notification.Style { @@ -4572,6 +4581,7 @@ package android.app { method public android.app.Notification.Builder addPerson(java.lang.String); method public android.app.Notification.Builder apply(android.app.Notification.Builder.Extender); method public android.app.Notification build(); + method public android.app.Notification.Builder extend(android.app.Notification.Extender); method public android.os.Bundle getExtras(); method public deprecated android.app.Notification getNotification(); method public android.app.Notification.Builder setAutoCancel(boolean); @@ -4613,8 +4623,8 @@ package android.app { method public android.app.Notification.Builder setWhen(long); } - public static abstract interface Notification.Builder.Extender { - method public abstract android.app.Notification.Builder applyTo(android.app.Notification.Builder); + public static abstract interface Notification.Extender { + method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder); } public static class Notification.InboxStyle extends android.app.Notification.Style { @@ -4644,6 +4654,51 @@ package android.app { field protected android.app.Notification.Builder mBuilder; } + public static final class Notification.WearableExtender implements android.app.Notification.Extender { + ctor public Notification.WearableExtender(); + ctor public Notification.WearableExtender(android.app.Notification); + method public android.app.Notification.WearableExtender addAction(android.app.Notification.Action); + method public android.app.Notification.WearableExtender addActions(java.util.List<android.app.Notification.Action>); + method public android.app.Notification.WearableExtender addPage(android.app.Notification); + method public android.app.Notification.WearableExtender addPages(java.util.List<android.app.Notification>); + method public android.app.Notification.WearableExtender clearActions(); + method public android.app.Notification.WearableExtender clearPages(); + method public android.app.Notification.WearableExtender clone(); + method public android.app.Notification.Builder extend(android.app.Notification.Builder); + method public java.util.List<android.app.Notification.Action> getActions(); + method public android.graphics.Bitmap getBackground(); + method public int getContentAction(); + method public int getContentIcon(); + method public int getContentIconGravity(); + method public boolean getContentIntentAvailableOffline(); + method public int getCustomContentHeight(); + method public int getCustomSizePreset(); + method public android.app.PendingIntent getDisplayIntent(); + method public int getGravity(); + method public boolean getHintHideIcon(); + method public boolean getHintShowBackgroundOnly(); + method public java.util.List<android.app.Notification> getPages(); + method public boolean getStartScrollBottom(); + method public android.app.Notification.WearableExtender setBackground(android.graphics.Bitmap); + method public android.app.Notification.WearableExtender setContentAction(int); + method public android.app.Notification.WearableExtender setContentIcon(int); + method public android.app.Notification.WearableExtender setContentIconGravity(int); + method public android.app.Notification.WearableExtender setContentIntentAvailableOffline(boolean); + method public android.app.Notification.WearableExtender setCustomContentHeight(int); + method public android.app.Notification.WearableExtender setCustomSizePreset(int); + method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent); + method public android.app.Notification.WearableExtender setGravity(int); + method public android.app.Notification.WearableExtender setHintHideIcon(boolean); + method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean); + method public android.app.Notification.WearableExtender setStartScrollBottom(boolean); + field public static final int SIZE_DEFAULT = 0; // 0x0 + field public static final int SIZE_LARGE = 4; // 0x4 + field public static final int SIZE_MEDIUM = 3; // 0x3 + field public static final int SIZE_SMALL = 2; // 0x2 + field public static final int SIZE_XSMALL = 1; // 0x1 + field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff + } + public class NotificationManager { method public void cancel(int); method public void cancel(java.lang.String, int); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index dfd927f..6e23b11 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -35,6 +35,7 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; +import android.view.Gravity; import android.view.View; import android.widget.ProgressBar; import android.widget.RemoteViews; @@ -46,7 +47,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; /** * A class that represents how a persistent notification is to be presented to @@ -767,7 +770,7 @@ public class Notification implements Parcelable */ public static class Action implements Parcelable { private final Bundle mExtras; - private RemoteInput[] mRemoteInputs; + private final RemoteInput[] mRemoteInputs; /** * Small icon representing the action. @@ -910,25 +913,12 @@ public class Notification implements Parcelable * Apply an extender to this action builder. Extenders may be used to add * metadata or change options on this builder. */ - public Builder apply(Extender extender) { - extender.applyTo(this); + public Builder extend(Extender extender) { + extender.extend(this); return this; } /** - * Extender interface for use with {@link #apply}. Extenders may be used to add - * metadata or change options on this builder. - */ - public interface Extender { - /** - * Apply this extender to a notification action builder. - * @param builder the builder to be modified. - * @return the build object for chaining. - */ - public Builder applyTo(Builder builder); - } - - /** * Combine all of the options that have been set and return a new {@link Action} * object. * @return the built action @@ -975,6 +965,121 @@ public class Notification implements Parcelable return new Action[size]; } }; + + /** + * Extender interface for use with {@link Builder#extend}. Extenders may be used to add + * metadata or change options on an action builder. + */ + public interface Extender { + /** + * Apply this extender to a notification action builder. + * @param builder the builder to be modified. + * @return the build object for chaining. + */ + public Builder extend(Builder builder); + } + + /** + * Wearable extender for notification actions. To add extensions to an action, + * create a new {@link android.app.Notification.Action.WearableExtender} object using + * the {@code WearableExtender()} constructor and apply it to a + * {@link android.app.Notification.Action.Builder} using + * {@link android.app.Notification.Action.Builder#extend}. + * + * <pre class="prettyprint"> + * Notification.Action action = new Notification.Action.Builder( + * R.drawable.archive_all, "Archive all", actionIntent) + * .apply(new Notification.Action.WearableExtender() + * .setAvailableOffline(false)) + * .build(); + * </pre> + */ + public static final class WearableExtender implements Extender { + /** Notification action extra which contains wearable extensions */ + private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; + + private static final String KEY_FLAGS = "flags"; + + // Flags bitwise-ored to mFlags + private static final int FLAG_AVAILABLE_OFFLINE = 0x1; + + // Default value for flags integer + private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE; + + private int mFlags = DEFAULT_FLAGS; + + /** + * Create a {@link android.app.Notification.Action.WearableExtender} with default + * options. + */ + public WearableExtender() { + } + + /** + * Create a {@link android.app.Notification.Action.WearableExtender} by reading + * wearable options present in an existing notification action. + * @param action the notification action to inspect. + */ + public WearableExtender(Action action) { + Bundle wearableBundle = action.getExtras().getBundle(EXTRA_WEARABLE_EXTENSIONS); + if (wearableBundle != null) { + mFlags = wearableBundle.getInt(KEY_FLAGS, DEFAULT_FLAGS); + } + } + + /** + * Apply wearable extensions to a notification action that is being built. This is + * typically called by the {@link android.app.Notification.Action.Builder#extend} + * method of {@link android.app.Notification.Action.Builder}. + */ + @Override + public Action.Builder extend(Action.Builder builder) { + Bundle wearableBundle = new Bundle(); + + if (mFlags != DEFAULT_FLAGS) { + wearableBundle.putInt(KEY_FLAGS, mFlags); + } + + builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle); + return builder; + } + + @Override + public WearableExtender clone() { + WearableExtender that = new WearableExtender(); + that.mFlags = this.mFlags; + return that; + } + + /** + * Set whether this action is available when the wearable device is not connected to + * a companion device. The user can still trigger this action when the wearable device is + * offline, but a visual hint will indicate that the action may not be available. + * Defaults to true. + */ + public WearableExtender setAvailableOffline(boolean availableOffline) { + setFlag(FLAG_AVAILABLE_OFFLINE, availableOffline); + return this; + } + + /** + * Get whether this action is available when the wearable device is not connected to + * a companion device. The user can still trigger this action when the wearable device is + * offline, but a visual hint will indicate that the action may not be available. + * Defaults to true. + */ + public boolean isAvailableOffline() { + return (mFlags & FLAG_AVAILABLE_OFFLINE) != 0; + } + + private void setFlag(int mask, boolean value) { + if (value) { + mFlags |= mask; + } else { + mFlags &= ~mask; + } + } + } } /** @@ -2169,24 +2274,11 @@ public class Notification implements Parcelable * Apply an extender to this notification builder. Extenders may be used to add * metadata or change options on this builder. */ - public Builder apply(Extender extender) { - extender.applyTo(this); + public Builder extend(Extender extender) { + extender.extend(this); return this; } - /** - * Extender interface for use with {@link #apply}. Extenders may be used to add - * metadata or change options on this builder. - */ - public interface Extender { - /** - * Apply this extender to a notification builder. - * @param builder the builder to be modified. - * @return the build object for chaining. - */ - public Builder applyTo(Builder builder); - } - private void setFlag(int mask, boolean value) { if (value) { mFlags |= mask; @@ -3163,4 +3255,634 @@ public class Notification implements Parcelable return big; } } + + /** + * Extender interface for use with {@link Builder#extend}. Extenders may be used to add + * metadata or change options on a notification builder. + */ + public interface Extender { + /** + * Apply this extender to a notification builder. + * @param builder the builder to be modified. + * @return the build object for chaining. + */ + public Builder extend(Builder builder); + } + + /** + * Helper class to add wearable extensions to notifications. + * <p class="note"> See + * <a href="{@docRoot}wear/notifications/creating.html">Creating Notifications + * for Android Wear</a> for more information on how to use this class. + * <p> + * To create a notification with wearable extensions: + * <ol> + * <li>Create a {@link android.app.Notification.Builder}, setting any desired + * properties. + * <li>Create a {@link android.app.Notification.WearableExtender}. + * <li>Set wearable-specific properties using the + * {@code add} and {@code set} methods of {@link android.app.Notification.WearableExtender}. + * <li>Call {@link android.app.Notification.Builder#extend} to apply the extensions to a + * notification. + * <li>Post the notification to the notification system with the + * {@code NotificationManager.notify(...)} methods. + * </ol> + * + * <pre class="prettyprint"> + * Notification notif = new Notification.Builder(mContext) + * .setContentTitle("New mail from " + sender.toString()) + * .setContentText(subject) + * .setSmallIcon(R.drawable.new_mail) + * .extend(new Notification.WearableExtender() + * .setContentIcon(R.drawable.new_mail)) + * .build(); + * NotificationManager notificationManger = + * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + * notificationManger.notify(0, notif);</pre> + * + * <p>Wearable extensions can be accessed on an existing notification by using the + * {@code WearableExtender(Notification)} constructor, + * and then using the {@code get} methods to access values. + * + * <pre class="prettyprint"> + * Notification.WearableExtender wearableExtender = new Notification.WearableExtender( + * notification); + * List<Notification> pages = wearableExtender.getPages(); + * </pre> + */ + public static final class WearableExtender implements Extender { + /** + * Sentinel value for an action index that is unset. + */ + public static final int UNSET_ACTION_INDEX = -1; + + /** + * Size value for use with {@link #setCustomSizePreset} to show this notification with + * default sizing. + * <p>For custom display notifications created using {@link #setDisplayIntent}, + * the default is {@link #SIZE_LARGE}. All other notifications size automatically based + * on their content. + */ + public static final int SIZE_DEFAULT = 0; + + /** + * Size value for use with {@link #setCustomSizePreset} to show this notification + * with an extra small size. + * <p>This value is only applicable for custom display notifications created using + * {@link #setDisplayIntent}. + */ + public static final int SIZE_XSMALL = 1; + + /** + * Size value for use with {@link #setCustomSizePreset} to show this notification + * with a small size. + * <p>This value is only applicable for custom display notifications created using + * {@link #setDisplayIntent}. + */ + public static final int SIZE_SMALL = 2; + + /** + * Size value for use with {@link #setCustomSizePreset} to show this notification + * with a medium size. + * <p>This value is only applicable for custom display notifications created using + * {@link #setDisplayIntent}. + */ + public static final int SIZE_MEDIUM = 3; + + /** + * Size value for use with {@link #setCustomSizePreset} to show this notification + * with a large size. + * <p>This value is only applicable for custom display notifications created using + * {@link #setDisplayIntent}. + */ + public static final int SIZE_LARGE = 4; + + /** Notification extra which contains wearable extensions */ + private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; + + // Keys within EXTRA_WEARABLE_OPTIONS for wearable options. + private static final String KEY_ACTIONS = "actions"; + private static final String KEY_FLAGS = "flags"; + private static final String KEY_DISPLAY_INTENT = "displayIntent"; + private static final String KEY_PAGES = "pages"; + private static final String KEY_BACKGROUND = "background"; + private static final String KEY_CONTENT_ICON = "contentIcon"; + private static final String KEY_CONTENT_ICON_GRAVITY = "contentIconGravity"; + private static final String KEY_CONTENT_ACTION_INDEX = "contentActionIndex"; + private static final String KEY_CUSTOM_SIZE_PRESET = "customSizePreset"; + private static final String KEY_CUSTOM_CONTENT_HEIGHT = "customContentHeight"; + private static final String KEY_GRAVITY = "gravity"; + + // Flags bitwise-ored to mFlags + private static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 0x1; + private static final int FLAG_HINT_HIDE_ICON = 1 << 1; + private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2; + private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3; + + // Default value for flags integer + private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE; + + private static final int DEFAULT_CONTENT_ICON_GRAVITY = Gravity.END; + private static final int DEFAULT_GRAVITY = Gravity.BOTTOM; + + private ArrayList<Action> mActions = new ArrayList<Action>(); + private int mFlags = DEFAULT_FLAGS; + private PendingIntent mDisplayIntent; + private ArrayList<Notification> mPages = new ArrayList<Notification>(); + private Bitmap mBackground; + private int mContentIcon; + private int mContentIconGravity = DEFAULT_CONTENT_ICON_GRAVITY; + private int mContentActionIndex = UNSET_ACTION_INDEX; + private int mCustomSizePreset = SIZE_DEFAULT; + private int mCustomContentHeight; + private int mGravity = DEFAULT_GRAVITY; + + /** + * Create a {@link android.app.Notification.WearableExtender} with default + * options. + */ + public WearableExtender() { + } + + public WearableExtender(Notification notif) { + Bundle wearableBundle = notif.extras.getBundle(EXTRA_WEARABLE_EXTENSIONS); + if (wearableBundle != null) { + List<Action> actions = wearableBundle.getParcelableArrayList(KEY_ACTIONS); + if (actions != null) { + mActions.addAll(actions); + } + + mFlags = wearableBundle.getInt(KEY_FLAGS, DEFAULT_FLAGS); + mDisplayIntent = wearableBundle.getParcelable(KEY_DISPLAY_INTENT); + + Notification[] pages = getNotificationArrayFromBundle( + wearableBundle, KEY_PAGES); + if (pages != null) { + Collections.addAll(mPages, pages); + } + + mBackground = wearableBundle.getParcelable(KEY_BACKGROUND); + mContentIcon = wearableBundle.getInt(KEY_CONTENT_ICON); + mContentIconGravity = wearableBundle.getInt(KEY_CONTENT_ICON_GRAVITY, + DEFAULT_CONTENT_ICON_GRAVITY); + mContentActionIndex = wearableBundle.getInt(KEY_CONTENT_ACTION_INDEX, + UNSET_ACTION_INDEX); + mCustomSizePreset = wearableBundle.getInt(KEY_CUSTOM_SIZE_PRESET, + SIZE_DEFAULT); + mCustomContentHeight = wearableBundle.getInt(KEY_CUSTOM_CONTENT_HEIGHT); + mGravity = wearableBundle.getInt(KEY_GRAVITY, DEFAULT_GRAVITY); + } + } + + /** + * Apply wearable extensions to a notification that is being built. This is typically + * called by the {@link android.app.Notification.Builder#extend} method of + * {@link android.app.Notification.Builder}. + */ + @Override + public Notification.Builder extend(Notification.Builder builder) { + Bundle wearableBundle = new Bundle(); + + if (!mActions.isEmpty()) { + wearableBundle.putParcelableArrayList(KEY_ACTIONS, mActions); + } + if (mFlags != DEFAULT_FLAGS) { + wearableBundle.putInt(KEY_FLAGS, mFlags); + } + if (mDisplayIntent != null) { + wearableBundle.putParcelable(KEY_DISPLAY_INTENT, mDisplayIntent); + } + if (!mPages.isEmpty()) { + wearableBundle.putParcelableArray(KEY_PAGES, mPages.toArray( + new Notification[mPages.size()])); + } + if (mBackground != null) { + wearableBundle.putParcelable(KEY_BACKGROUND, mBackground); + } + if (mContentIcon != 0) { + wearableBundle.putInt(KEY_CONTENT_ICON, mContentIcon); + } + if (mContentIconGravity != DEFAULT_CONTENT_ICON_GRAVITY) { + wearableBundle.putInt(KEY_CONTENT_ICON_GRAVITY, mContentIconGravity); + } + if (mContentActionIndex != UNSET_ACTION_INDEX) { + wearableBundle.putInt(KEY_CONTENT_ACTION_INDEX, + mContentActionIndex); + } + if (mCustomSizePreset != SIZE_DEFAULT) { + wearableBundle.putInt(KEY_CUSTOM_SIZE_PRESET, mCustomSizePreset); + } + if (mCustomContentHeight != 0) { + wearableBundle.putInt(KEY_CUSTOM_CONTENT_HEIGHT, mCustomContentHeight); + } + if (mGravity != DEFAULT_GRAVITY) { + wearableBundle.putInt(KEY_GRAVITY, mGravity); + } + + builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle); + return builder; + } + + @Override + public WearableExtender clone() { + WearableExtender that = new WearableExtender(); + that.mActions = new ArrayList<Action>(this.mActions); + that.mFlags = this.mFlags; + that.mDisplayIntent = this.mDisplayIntent; + that.mPages = new ArrayList<Notification>(this.mPages); + that.mBackground = this.mBackground; + that.mContentIcon = this.mContentIcon; + that.mContentIconGravity = this.mContentIconGravity; + that.mContentActionIndex = this.mContentActionIndex; + that.mCustomSizePreset = this.mCustomSizePreset; + that.mCustomContentHeight = this.mCustomContentHeight; + that.mGravity = this.mGravity; + return that; + } + + /** + * Add a wearable action to this notification. + * + * <p>When wearable actions are added using this method, the set of actions that + * show on a wearable device splits from devices that only show actions added + * using {@link android.app.Notification.Builder#addAction}. This allows for customization + * of which actions display on different devices. + * + * @param action the action to add to this notification + * @return this object for method chaining + * @see android.app.Notification.Action + */ + public WearableExtender addAction(Action action) { + mActions.add(action); + return this; + } + + /** + * Adds wearable actions to this notification. + * + * <p>When wearable actions are added using this method, the set of actions that + * show on a wearable device splits from devices that only show actions added + * using {@link android.app.Notification.Builder#addAction}. This allows for customization + * of which actions display on different devices. + * + * @param actions the actions to add to this notification + * @return this object for method chaining + * @see android.app.Notification.Action + */ + public WearableExtender addActions(List<Action> actions) { + mActions.addAll(actions); + return this; + } + + /** + * Clear all wearable actions present on this builder. + * @return this object for method chaining. + * @see #addAction + */ + public WearableExtender clearActions() { + mActions.clear(); + return this; + } + + /** + * Get the wearable actions present on this notification. + */ + public List<Action> getActions() { + return mActions; + } + + /** + * Set an intent to launch inside of an activity view when displaying + * this notification. This {@link PendingIntent} should be for an activity. + * + * @param intent the {@link PendingIntent} for an activity + * @return this object for method chaining + * @see android.app.Notification.WearableExtender#getDisplayIntent + */ + public WearableExtender setDisplayIntent(PendingIntent intent) { + mDisplayIntent = intent; + return this; + } + + /** + * Get the intent to launch inside of an activity view when displaying this + * notification. This {@code PendingIntent} should be for an activity. + */ + public PendingIntent getDisplayIntent() { + return mDisplayIntent; + } + + /** + * Add an additional page of content to display with this notification. The current + * notification forms the first page, and pages added using this function form + * subsequent pages. This field can be used to separate a notification into multiple + * sections. + * + * @param page the notification to add as another page + * @return this object for method chaining + * @see android.app.Notification.WearableExtender#getPages + */ + public WearableExtender addPage(Notification page) { + mPages.add(page); + return this; + } + + /** + * Add additional pages of content to display with this notification. The current + * notification forms the first page, and pages added using this function form + * subsequent pages. This field can be used to separate a notification into multiple + * sections. + * + * @param pages a list of notifications + * @return this object for method chaining + * @see android.app.Notification.WearableExtender#getPages + */ + public WearableExtender addPages(List<Notification> pages) { + mPages.addAll(pages); + return this; + } + + /** + * Clear all additional pages present on this builder. + * @return this object for method chaining. + * @see #addPage + */ + public WearableExtender clearPages() { + mPages.clear(); + return this; + } + + /** + * Get the array of additional pages of content for displaying this notification. The + * current notification forms the first page, and elements within this array form + * subsequent pages. This field can be used to separate a notification into multiple + * sections. + * @return the pages for this notification + */ + public List<Notification> getPages() { + return mPages; + } + + /** + * Set a background image to be displayed behind the notification content. + * Contrary to the {@link android.app.Notification.BigPictureStyle}, this background + * will work with any notification style. + * + * @param background the background bitmap + * @return this object for method chaining + * @see android.app.Notification.WearableExtender#getBackground + */ + public WearableExtender setBackground(Bitmap background) { + mBackground = background; + return this; + } + + /** + * Get a background image to be displayed behind the notification content. + * Contrary to the {@link android.app.Notification.BigPictureStyle}, this background + * will work with any notification style. + * + * @return the background image + * @see android.app.Notification.WearableExtender#setBackground + */ + public Bitmap getBackground() { + return mBackground; + } + + /** + * Set an icon that goes with the content of this notification. + */ + public WearableExtender setContentIcon(int icon) { + mContentIcon = icon; + return this; + } + + /** + * Get an icon that goes with the content of this notification. + */ + public int getContentIcon() { + return mContentIcon; + } + + /** + * Set the gravity that the content icon should have within the notification display. + * Supported values include {@link android.view.Gravity#START} and + * {@link android.view.Gravity#END}. The default value is {@link android.view.Gravity#END}. + * @see #setContentIcon + */ + public WearableExtender setContentIconGravity(int contentIconGravity) { + mContentIconGravity = contentIconGravity; + return this; + } + + /** + * Get the gravity that the content icon should have within the notification display. + * Supported values include {@link android.view.Gravity#START} and + * {@link android.view.Gravity#END}. The default value is {@link android.view.Gravity#END}. + * @see #getContentIcon + */ + public int getContentIconGravity() { + return mContentIconGravity; + } + + /** + * Set an action from this notification's actions to be clickable with the content of + * this notification page. This action will no longer display separately from the + * notification content. This action's icon will display with optional subtext provided + * by the action's title. + * @param actionIndex The index of the action to hoist on the current notification page. + * If wearable actions are present, this index will apply to that list, + * otherwise it will apply to the main notification's actions list. + */ + public WearableExtender setContentAction(int actionIndex) { + mContentActionIndex = actionIndex; + return this; + } + + /** + * Get the action index of an action from this notification to show as clickable with + * the content of this notification page. When the user clicks this notification page, + * this action will trigger. This action will no longer display separately from the + * notification content. The action's icon will display with optional subtext provided + * by the action's title. + * + * <p>If wearable specific actions are present, this index will apply to that list, + * otherwise it will apply to the main notification's actions list. + */ + public int getContentAction() { + return mContentActionIndex; + } + + /** + * Set the gravity that this notification should have within the available viewport space. + * Supported values include {@link android.view.Gravity#TOP}, + * {@link android.view.Gravity#CENTER_VERTICAL} and {@link android.view.Gravity#BOTTOM}. + * The default value is {@link android.view.Gravity#BOTTOM}. + */ + public WearableExtender setGravity(int gravity) { + mGravity = gravity; + return this; + } + + /** + * Get the gravity that this notification should have within the available viewport space. + * Supported values include {@link android.view.Gravity#TOP}, + * {@link android.view.Gravity#CENTER_VERTICAL} and {@link android.view.Gravity#BOTTOM}. + * The default value is {@link android.view.Gravity#BOTTOM}. + */ + public int getGravity() { + return mGravity; + } + + /** + * Set the custom size preset for the display of this notification out of the available + * presets found in {@link android.app.Notification.WearableExtender}, e.g. + * {@link #SIZE_LARGE}. + * <p>Some custom size presets are only applicable for custom display notifications created + * using {@link android.app.Notification.WearableExtender#setDisplayIntent}. Check the + * documentation for the preset in question. See also + * {@link #setCustomContentHeight} and {@link #getCustomSizePreset}. + */ + public WearableExtender setCustomSizePreset(int sizePreset) { + mCustomSizePreset = sizePreset; + return this; + } + + /** + * Get the custom size preset for the display of this notification out of the available + * presets found in {@link android.app.Notification.WearableExtender}, e.g. + * {@link #SIZE_LARGE}. + * <p>Some custom size presets are only applicable for custom display notifications created + * using {@link #setDisplayIntent}. Check the documentation for the preset in question. + * See also {@link #setCustomContentHeight} and {@link #setCustomSizePreset}. + */ + public int getCustomSizePreset() { + return mCustomSizePreset; + } + + /** + * Set the custom height in pixels for the display of this notification's content. + * <p>This option is only available for custom display notifications created + * using {@link android.app.Notification.WearableExtender#setDisplayIntent}. See also + * {@link android.app.Notification.WearableExtender#setCustomSizePreset} and + * {@link #getCustomContentHeight}. + */ + public WearableExtender setCustomContentHeight(int height) { + mCustomContentHeight = height; + return this; + } + + /** + * Get the custom height in pixels for the display of this notification's content. + * <p>This option is only available for custom display notifications created + * using {@link #setDisplayIntent}. See also {@link #setCustomSizePreset} and + * {@link #setCustomContentHeight}. + */ + public int getCustomContentHeight() { + return mCustomContentHeight; + } + + /** + * Set whether the scrolling position for the contents of this notification should start + * at the bottom of the contents instead of the top when the contents are too long to + * display within the screen. Default is false (start scroll at the top). + */ + public WearableExtender setStartScrollBottom(boolean startScrollBottom) { + setFlag(FLAG_START_SCROLL_BOTTOM, startScrollBottom); + return this; + } + + /** + * Get whether the scrolling position for the contents of this notification should start + * at the bottom of the contents instead of the top when the contents are too long to + * display within the screen. Default is false (start scroll at the top). + */ + public boolean getStartScrollBottom() { + return (mFlags & FLAG_START_SCROLL_BOTTOM) != 0; + } + + /** + * Set whether the content intent is available when the wearable device is not connected + * to a companion device. The user can still trigger this intent when the wearable device + * is offline, but a visual hint will indicate that the content intent may not be available. + * Defaults to true. + */ + public WearableExtender setContentIntentAvailableOffline( + boolean contentIntentAvailableOffline) { + setFlag(FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE, contentIntentAvailableOffline); + return this; + } + + /** + * Get whether the content intent is available when the wearable device is not connected + * to a companion device. The user can still trigger this intent when the wearable device + * is offline, but a visual hint will indicate that the content intent may not be available. + * Defaults to true. + */ + public boolean getContentIntentAvailableOffline() { + return (mFlags & FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE) != 0; + } + + /** + * Set a hint that this notification's icon should not be displayed. + * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise. + * @return this object for method chaining + */ + public WearableExtender setHintHideIcon(boolean hintHideIcon) { + setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon); + return this; + } + + /** + * Get a hint that this notification's icon should not be displayed. + * @return {@code true} if this icon should not be displayed, false otherwise. + * The default value is {@code false} if this was never set. + */ + public boolean getHintHideIcon() { + return (mFlags & FLAG_HINT_HIDE_ICON) != 0; + } + + /** + * Set a visual hint that only the background image of this notification should be + * displayed, and other semantic content should be hidden. This hint is only applicable + * to sub-pages added using {@link #addPage}. + */ + public WearableExtender setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) { + setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly); + return this; + } + + /** + * Get a visual hint that only the background image of this notification should be + * displayed, and other semantic content should be hidden. This hint is only applicable + * to sub-pages added using {@link android.app.Notification.WearableExtender#addPage}. + */ + public boolean getHintShowBackgroundOnly() { + return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0; + } + + private void setFlag(int mask, boolean value) { + if (value) { + mFlags |= mask; + } else { + mFlags &= ~mask; + } + } + } + + /** + * Get an array of Notification objects from a parcelable array bundle field. + * Update the bundle to have a typed array so fetches in the future don't need + * to do an array copy. + */ + private static Notification[] getNotificationArrayFromBundle(Bundle bundle, String key) { + Parcelable[] array = bundle.getParcelableArray(key); + if (array instanceof Notification[] || array == null) { + return (Notification[]) array; + } + Notification[] typedArray = Arrays.copyOf(array, array.length, + Notification[].class); + bundle.putParcelableArray(key, typedArray); + return typedArray; + } } diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java index 9cfc541..11420c5 100644 --- a/core/java/android/app/RemoteInput.java +++ b/core/java/android/app/RemoteInput.java @@ -64,18 +64,24 @@ public final class RemoteInput implements Parcelable { /** Extra added to a clip data intent object to hold the results bundle. */ public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData"; + // Flags bitwise-ored to mFlags + private static final int FLAG_ALLOW_FREE_FORM_INPUT = 0x1; + + // Default value for flags integer + private static final int DEFAULT_FLAGS = FLAG_ALLOW_FREE_FORM_INPUT; + private final String mResultKey; private final CharSequence mLabel; private final CharSequence[] mChoices; - private final boolean mAllowFreeFormInput; + private final int mFlags; private final Bundle mExtras; private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices, - boolean allowFreeFormInput, Bundle extras) { + int flags, Bundle extras) { this.mResultKey = resultKey; this.mLabel = label; this.mChoices = choices; - this.mAllowFreeFormInput = allowFreeFormInput; + this.mFlags = flags; this.mExtras = extras; } @@ -108,7 +114,7 @@ public final class RemoteInput implements Parcelable { * if you set this to false and {@link #getChoices} returns {@code null} or empty. */ public boolean getAllowFreeFormInput() { - return mAllowFreeFormInput; + return (mFlags & FLAG_ALLOW_FREE_FORM_INPUT) != 0; } /** @@ -125,7 +131,7 @@ public final class RemoteInput implements Parcelable { private final String mResultKey; private CharSequence mLabel; private CharSequence[] mChoices; - private boolean mAllowFreeFormInput = true; + private int mFlags = DEFAULT_FLAGS; private Bundle mExtras = new Bundle(); /** @@ -178,7 +184,7 @@ public final class RemoteInput implements Parcelable { * @return this object for method chaining */ public Builder setAllowFreeFormInput(boolean allowFreeFormInput) { - mAllowFreeFormInput = allowFreeFormInput; + setFlag(mFlags, allowFreeFormInput); return this; } @@ -205,12 +211,20 @@ public final class RemoteInput implements Parcelable { return mExtras; } + private void setFlag(int mask, boolean value) { + if (value) { + mFlags |= mask; + } else { + mFlags &= ~mask; + } + } + /** * Combine all of the options that have been set and return a new {@link RemoteInput} * object. */ public RemoteInput build() { - return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras); + return new RemoteInput(mResultKey, mLabel, mChoices, mFlags, mExtras); } } @@ -218,7 +232,7 @@ public final class RemoteInput implements Parcelable { mResultKey = in.readString(); mLabel = in.readCharSequence(); mChoices = in.readCharSequenceArray(); - mAllowFreeFormInput = in.readInt() != 0; + mFlags = in.readInt(); mExtras = in.readBundle(); } @@ -279,7 +293,7 @@ public final class RemoteInput implements Parcelable { out.writeString(mResultKey); out.writeCharSequence(mLabel); out.writeCharSequenceArray(mChoices); - out.writeInt(mAllowFreeFormInput ? 1 : 0); + out.writeInt(mFlags); out.writeBundle(mExtras); } diff --git a/core/java/android/app/wearable/WearableActionExtensions.java b/core/java/android/app/wearable/WearableActionExtensions.java deleted file mode 100644 index c296ef2..0000000 --- a/core/java/android/app/wearable/WearableActionExtensions.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app.wearable; - -import android.app.Notification; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Wearable extensions to notification actions. To add extensions to an action, - * create a new {@link WearableActionExtensions} object using - * {@link WearableActionExtensions.Builder} and apply it to a - * {@link android.app.Notification.Action.Builder}. - * - * <pre class="prettyprint"> - * Notification.Action action = new Notification.Action.Builder( - * R.drawable.archive_all, "Archive all", actionIntent) - * .apply(new WearableActionExtensions.Builder() - * .setAvailableOffline(false) - * .build()) - * .build(); - * </pre> - */ -public final class WearableActionExtensions implements Notification.Action.Builder.Extender, - Parcelable { - /** Notification action extra which contains wearable extensions */ - private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; - - // Flags bitwise-ored to mFlags - private static final int FLAG_AVAILABLE_OFFLINE = 1 << 0; - - // Default value for flags integer - private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE; - - private final int mFlags; - - private WearableActionExtensions(int flags) { - mFlags = flags; - } - - private WearableActionExtensions(Parcel in) { - mFlags = in.readInt(); - } - - /** - * Create a {@link WearableActionExtensions} by reading wearable extensions present on an - * existing notification action. - * @param action the notification action to inspect. - * @return a new {@link WearableActionExtensions} object. - */ - public static WearableActionExtensions from(Notification.Action action) { - WearableActionExtensions extensions = action.getExtras().getParcelable( - EXTRA_WEARABLE_EXTENSIONS); - if (extensions != null) { - return extensions; - } else { - // Return a WearableActionExtensions with default values. - return new Builder().build(); - } - } - - /** - * Get whether this action is available when the wearable device is not connected to - * a companion device. The user can still trigger this action when the wearable device is - * offline, but a visual hint will indicate that the action may not be available. - * Defaults to true. - */ - public boolean isAvailableOffline() { - return (mFlags & FLAG_AVAILABLE_OFFLINE) != 0; - } - - @Override - public Notification.Action.Builder applyTo(Notification.Action.Builder builder) { - builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this); - return builder; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeInt(mFlags); - } - - /** - * Builder for {@link WearableActionExtensions} objects, which adds wearable extensions to - * notification actions. To extend an action, create an instance of this class, call the set - * methods present, call {@link #build}, and finally apply the options to a - * {@link Notification.Action.Builder} using its - * {@link android.app.Notification.Action.Builder#apply} method. - */ - public static final class Builder { - private int mFlags = DEFAULT_FLAGS; - - /** - * Construct a builder to be used for adding wearable extensions to notification actions. - * - * <pre class="prettyprint"> - * Notification.Action action = new Notification.Action.Builder( - * R.drawable.archive_all, "Archive all", actionIntent) - * .apply(new WearableActionExtensions.Builder() - * .setAvailableOffline(false) - * .build()) - * .build();</pre> - */ - public Builder() { - } - - /** - * Create a {@link Builder} by reading wearable extensions present on an - * existing {@code WearableActionExtensions} object. - * @param other the existing extensions to inspect. - */ - public Builder(WearableActionExtensions other) { - mFlags = other.mFlags; - } - - /** - * Set whether this action is available when the wearable device is not connected to - * a companion device. The user can still trigger this action when the wearable device is - * offline, but a visual hint will indicate that the action may not be available. - * Defaults to true. - */ - public Builder setAvailableOffline(boolean availableOffline) { - setFlag(FLAG_AVAILABLE_OFFLINE, availableOffline); - return this; - } - - /** - * Build a new {@link WearableActionExtensions} object with the extensions - * currently present on this builder. - * @return the extensions object. - */ - public WearableActionExtensions build() { - return new WearableActionExtensions(mFlags); - } - - private void setFlag(int mask, boolean value) { - if (value) { - mFlags |= mask; - } else { - mFlags &= ~mask; - } - } - } - - public static final Creator<WearableActionExtensions> CREATOR = - new Creator<WearableActionExtensions>() { - @Override - public WearableActionExtensions createFromParcel(Parcel in) { - return new WearableActionExtensions(in); - } - - @Override - public WearableActionExtensions[] newArray(int size) { - return new WearableActionExtensions[size]; - } - }; -} diff --git a/core/java/android/app/wearable/WearableNotificationExtensions.java b/core/java/android/app/wearable/WearableNotificationExtensions.java deleted file mode 100644 index d433613..0000000 --- a/core/java/android/app/wearable/WearableNotificationExtensions.java +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app.wearable; - -import android.app.Notification; -import android.app.PendingIntent; -import android.graphics.Bitmap; -import android.os.Parcel; -import android.os.Parcelable; -import android.view.Gravity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Helper class that contains wearable extensions for notifications. - * <p class="note"> See - * <a href="{@docRoot}wear/notifications/creating.html">Creating Notifications - * for Android Wear</a> for more information on how to use this class. - * <p> - * To create a notification with wearable extensions: - * <ol> - * <li>Create a {@link Notification.Builder}, setting any desired - * properties. - * <li>Create a {@link WearableNotificationExtensions.Builder}. - * <li>Set wearable-specific properties using the - * {@code add} and {@code set} methods of {@link WearableNotificationExtensions.Builder}. - * <li>Call {@link WearableNotificationExtensions.Builder#build} to build the extensions - * object. - * <li>Call {@link Notification.Builder#apply} to apply the extensions to a notification. - * <li>Post the notification to the notification system with the - * {@code NotificationManager.notify(...)} methods. - * </ol> - * - * <pre class="prettyprint"> - * Notification notif = new Notification.Builder(mContext) - * .setContentTitle("New mail from " + sender.toString()) - * .setContentText(subject) - * .setSmallIcon(R.drawable.new_mail) - * .apply(new new WearableNotificationExtensions.Builder() - * .setContentIcon(R.drawable.new_mail) - * .build()) - * .build(); - * NotificationManager notificationManger = - * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - * notificationManger.notify(0, notif);</pre> - * - * <p>Wearable extensions can be accessed on an existing notification by using the - * {@link WearableNotificationExtensions#from} function. - * - * <pre class="prettyprint"> - * WearableNotificationExtensions wearableExtensions = WearableNotificationExtensions.from( - * notification); - * Notification[] pages = wearableExtensions.getPages(); - * </pre> - */ -public final class WearableNotificationExtensions implements Notification.Builder.Extender, - Parcelable { - /** - * Sentinel value for an action index that is unset. - */ - public static final int UNSET_ACTION_INDEX = -1; - - /** - * Size value for use with {@link Builder#setCustomSizePreset} to show this notification with - * default sizing. - * <p>For custom display notifications created using {@link Builder#setDisplayIntent}, - * the default is {@link #SIZE_LARGE}. All other notifications size automatically based - * on their content. - */ - public static final int SIZE_DEFAULT = 0; - - /** - * Size value for use with {@link Builder#setCustomSizePreset} to show this notification - * with an extra small size. - * <p>This value is only applicable for custom display notifications created using - * {@link Builder#setDisplayIntent}. - */ - public static final int SIZE_XSMALL = 1; - - /** - * Size value for use with {@link Builder#setCustomSizePreset} to show this notification - * with a small size. - * <p>This value is only applicable for custom display notifications created using - * {@link Builder#setDisplayIntent}. - */ - public static final int SIZE_SMALL = 2; - - /** - * Size value for use with {@link Builder#setCustomSizePreset} to show this notification - * with a medium size. - * <p>This value is only applicable for custom display notifications created using - * {@link Builder#setDisplayIntent}. - */ - public static final int SIZE_MEDIUM = 3; - - /** - * Size value for use with {@link Builder#setCustomSizePreset} to show this notification - * with a large size. - * <p>This value is only applicable for custom display notifications created using - * {@link Builder#setDisplayIntent}. - */ - public static final int SIZE_LARGE = 4; - - /** Notification extra which contains wearable extensions */ - static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; - - // Flags bitwise-ored to mFlags - static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 1 << 0; - static final int FLAG_HINT_HIDE_ICON = 1 << 1; - static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2; - static final int FLAG_START_SCROLL_BOTTOM = 1 << 3; - - // Default value for flags integer - static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE; - - private final Notification.Action[] mActions; - private final int mFlags; - private final PendingIntent mDisplayIntent; - private final Notification[] mPages; - private final Bitmap mBackground; - private final int mContentIcon; - private final int mContentIconGravity; - private final int mContentActionIndex; - private final int mCustomSizePreset; - private final int mCustomContentHeight; - private final int mGravity; - - private WearableNotificationExtensions(Notification.Action[] actions, int flags, - PendingIntent displayIntent, Notification[] pages, Bitmap background, - int contentIcon, int contentIconGravity, int contentActionIndex, - int customSizePreset, int customContentHeight, int gravity) { - mActions = actions; - mFlags = flags; - mDisplayIntent = displayIntent; - mPages = pages; - mBackground = background; - mContentIcon = contentIcon; - mContentIconGravity = contentIconGravity; - mContentActionIndex = contentActionIndex; - mCustomSizePreset = customSizePreset; - mCustomContentHeight = customContentHeight; - mGravity = gravity; - } - - private WearableNotificationExtensions(Parcel in) { - mActions = in.createTypedArray(Notification.Action.CREATOR); - mFlags = in.readInt(); - mDisplayIntent = in.readParcelable(PendingIntent.class.getClassLoader()); - mPages = in.createTypedArray(Notification.CREATOR); - mBackground = in.readParcelable(Bitmap.class.getClassLoader()); - mContentIcon = in.readInt(); - mContentIconGravity = in.readInt(); - mContentActionIndex = in.readInt(); - mCustomSizePreset = in.readInt(); - mCustomContentHeight = in.readInt(); - mGravity = in.readInt(); - } - - /** - * Create a {@link WearableNotificationExtensions} by reading wearable extensions present on an - * existing notification. - * @param notif the notification to inspect. - * @return a new {@link WearableNotificationExtensions} object. - */ - public static WearableNotificationExtensions from(Notification notif) { - WearableNotificationExtensions extensions = notif.extras.getParcelable( - EXTRA_WEARABLE_EXTENSIONS); - if (extensions != null) { - return extensions; - } else { - // Return a WearableNotificationExtensions with default values. - return new Builder().build(); - } - } - - /** - * Apply wearable extensions to a notification that is being built. This is typically - * called by {@link Notification.Builder#apply} method of {@link Notification.Builder}. - */ - @Override - public Notification.Builder applyTo(Notification.Builder builder) { - builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this); - return builder; - } - - /** - * Get the number of wearable actions present on this notification. - * - * @return the number of wearable actions for this notification - */ - public int getActionCount() { - return mActions.length; - } - - /** - * Get a {@link Notification.Action} for the wearable action at {@code actionIndex}. - * @param actionIndex the index of the desired wearable action - */ - public Notification.Action getAction(int actionIndex) { - return mActions[actionIndex]; - } - - /** - * Get the wearable actions present on this notification. - */ - public Notification.Action[] getActions() { - return mActions; - } - - /** - * Get the intent to launch inside of an activity view when displaying this - * notification. This {@code PendingIntent} should be for an activity. - */ - public PendingIntent getDisplayIntent() { - return mDisplayIntent; - } - - /** - * Get the array of additional pages of content for displaying this notification. The - * current notification forms the first page, and elements within this array form - * subsequent pages. This field can be used to separate a notification into multiple - * sections. - * @return the pages for this notification - */ - public Notification[] getPages() { - return mPages; - } - - /** - * Get a background image to be displayed behind the notification content. - * Contrary to the {@link Notification.BigPictureStyle}, this background - * will work with any notification style. - * - * @return the background image - * @see Builder#setBackground - */ - public Bitmap getBackground() { - return mBackground; - } - - /** - * Get an icon that goes with the content of this notification. - */ - public int getContentIcon() { - return mContentIcon; - } - - /** - * Get the gravity that the content icon should have within the notification display. - * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default - * value is {@link android.view.Gravity#END}. - * @see #getContentIcon - */ - public int getContentIconGravity() { - return mContentIconGravity; - } - - /** - * Get the action index of an action from this notification to show as clickable with - * the content of this notification page. When the user clicks this notification page, - * this action will trigger. This action will no longer display separately from the - * notification content. The action's icon will display with optional subtext provided - * by the action's title. - * - * <p>If wearable specific actions are present, this index will apply to that list, - * otherwise it will apply to the main notification's actions list. - */ - public int getContentAction() { - return mContentActionIndex; - } - - /** - * Get the gravity that this notification should have within the available viewport space. - * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and - * {@link android.view.Gravity#BOTTOM}. The default value is - * {@link android.view.Gravity#BOTTOM}. - */ - public int getGravity() { - return mGravity; - } - - /** - * Get the custom size preset for the display of this notification out of the available - * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}. - * <p>Some custom size presets are only applicable for custom display notifications created - * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in question. - * See also {@link Builder#setCustomContentHeight} and {@link Builder#setCustomSizePreset}. - */ - public int getCustomSizePreset() { - return mCustomSizePreset; - } - - /** - * Get the custom height in pixels for the display of this notification's content. - * <p>This option is only available for custom display notifications created - * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and - * {@link Builder#setCustomContentHeight}. - */ - public int getCustomContentHeight() { - return mCustomContentHeight; - } - - /** - * Get whether the scrolling position for the contents of this notification should start - * at the bottom of the contents instead of the top when the contents are too long to - * display within the screen. Default is false (start scroll at the top). - */ - public boolean getStartScrollBottom() { - return (mFlags & FLAG_START_SCROLL_BOTTOM) != 0; - } - - /** - * Get whether the content intent is available when the wearable device is not connected - * to a companion device. The user can still trigger this intent when the wearable device is - * offline, but a visual hint will indicate that the content intent may not be available. - * Defaults to true. - */ - public boolean getContentIntentAvailableOffline() { - return (mFlags & FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE) != 0; - } - - /** - * Get a hint that this notification's icon should not be displayed. - * @return {@code true} if this icon should not be displayed, false otherwise. - * The default value is {@code false} if this was never set. - */ - public boolean getHintHideIcon() { - return (mFlags & FLAG_HINT_HIDE_ICON) != 0; - } - - /** - * Get a visual hint that only the background image of this notification should be - * displayed, and other semantic content should be hidden. This hint is only applicable - * to sub-pages added using {@link Builder#addPage}. - */ - public boolean getHintShowBackgroundOnly() { - return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeTypedArray(mActions, flags); - out.writeInt(mFlags); - out.writeParcelable(mDisplayIntent, flags); - out.writeTypedArray(mPages, flags); - out.writeParcelable(mBackground, flags); - out.writeInt(mContentIcon); - out.writeInt(mContentIconGravity); - out.writeInt(mContentActionIndex); - out.writeInt(mCustomSizePreset); - out.writeInt(mCustomContentHeight); - out.writeInt(mGravity); - } - - /** - * Builder to apply wearable notification extensions to a {@link Notification.Builder} - * object. - * - * <p>You can chain the "set" methods for this builder in any order, - * but you must call the {@link #build} method and then the {@link Notification.Builder#apply} - * method to apply your extensions to a notification. - * - * <pre class="prettyprint"> - * Notification notif = new Notification.Builder(mContext) - * .setContentTitle("New mail from " + sender.toString()) - * .setContentText(subject) - * .setSmallIcon(R.drawable.new_mail); - * .apply(new WearableNotificationExtensions.Builder() - * .setContentIcon(R.drawable.new_mail) - * .build()) - * .build(); - * NotificationManager notificationManger = - * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - * notificationManager.notify(0, notif);</pre> - */ - public static final class Builder { - private final List<Notification.Action> mActions = - new ArrayList<Notification.Action>(); - private int mFlags = DEFAULT_FLAGS; - private PendingIntent mDisplayIntent; - private final List<Notification> mPages = new ArrayList<Notification>(); - private Bitmap mBackground; - private int mContentIcon; - private int mContentIconGravity = Gravity.END; - private int mContentActionIndex = UNSET_ACTION_INDEX; - private int mCustomContentHeight; - private int mCustomSizePreset = SIZE_DEFAULT; - private int mGravity = Gravity.BOTTOM; - - /** - * Construct a builder to be used for adding wearable extensions to notifications. - * - * <pre class="prettyprint"> - * Notification notif = new Notification.Builder(mContext) - * .setContentTitle("New mail from " + sender.toString()) - * .setContentText(subject) - * .setSmallIcon(R.drawable.new_mail); - * .apply(new WearableNotificationExtensions.Builder() - * .setContentIcon(R.drawable.new_mail) - * .build()) - * .build(); - * NotificationManager notificationManger = - * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - * notificationManager.notify(0, notif);</pre> - */ - public Builder() { - } - - /** - * Create a {@link Builder} by reading wearable extensions present on an - * existing {@code WearableNotificationExtensions} object. - * @param other the existing extensions to inspect. - */ - public Builder(WearableNotificationExtensions other) { - Collections.addAll(mActions, other.mActions); - mFlags = other.mFlags; - mDisplayIntent = other.mDisplayIntent; - Collections.addAll(mPages, other.mPages); - mBackground = other.mBackground; - mContentIcon = other.mContentIcon; - mContentIconGravity = other.mContentIconGravity; - mContentActionIndex = other.mContentActionIndex; - mCustomContentHeight = other.mCustomContentHeight; - mCustomSizePreset = other.mCustomSizePreset; - mGravity = other.mGravity; - } - - /** - * Add a wearable action to this notification. - * - * <p>When wearable actions are added using this method, the set of actions that - * show on a wearable device splits from devices that only show actions added - * using {@link android.app.Notification.Builder#addAction}. This allows for customization - * of which actions display on different devices. - * - * @param action the action to add to this notification - * @return this object for method chaining - * @see Notification.Action - */ - public Builder addAction(Notification.Action action) { - mActions.add(action); - return this; - } - - /** - * Adds wearable actions to this notification. - * - * <p>When wearable actions are added using this method, the set of actions that - * show on a wearable device splits from devices that only show actions added - * using {@link android.app.Notification.Builder#addAction}. This allows for customization - * of which actions display on different devices. - * - * @param actions the actions to add to this notification - * @return this object for method chaining - * @see Notification.Action - */ - public Builder addActions(List<Notification.Action> actions) { - mActions.addAll(actions); - return this; - } - - /** - * Clear all wearable actions present on this builder. - * @return this object for method chaining. - * @see #addAction - */ - public Builder clearActions() { - mActions.clear(); - return this; - } - - /** - * Set an intent to launch inside of an activity view when displaying - * this notification. This {@link android.app.PendingIntent} should be for an activity. - * - * @param intent the {@link android.app.PendingIntent} for an activity - * @return this object for method chaining - * @see WearableNotificationExtensions#getDisplayIntent - */ - public Builder setDisplayIntent(PendingIntent intent) { - mDisplayIntent = intent; - return this; - } - - /** - * Add an additional page of content to display with this notification. The current - * notification forms the first page, and pages added using this function form - * subsequent pages. This field can be used to separate a notification into multiple - * sections. - * - * @param page the notification to add as another page - * @return this object for method chaining - * @see WearableNotificationExtensions#getPages - */ - public Builder addPage(Notification page) { - mPages.add(page); - return this; - } - - /** - * Add additional pages of content to display with this notification. The current - * notification forms the first page, and pages added using this function form - * subsequent pages. This field can be used to separate a notification into multiple - * sections. - * - * @param pages a list of notifications - * @return this object for method chaining - * @see WearableNotificationExtensions#getPages - */ - public Builder addPages(List<Notification> pages) { - mPages.addAll(pages); - return this; - } - - /** - * Clear all additional pages present on this builder. - * @return this object for method chaining. - * @see #addPage - */ - public Builder clearPages() { - mPages.clear(); - return this; - } - - /** - * Set a background image to be displayed behind the notification content. - * Contrary to the {@link Notification.BigPictureStyle}, this background - * will work with any notification style. - * - * @param background the background bitmap - * @return this object for method chaining - * @see WearableNotificationExtensions#getBackground - */ - public Builder setBackground(Bitmap background) { - mBackground = background; - return this; - } - - /** - * Set an icon that goes with the content of this notification. - */ - public Builder setContentIcon(int icon) { - mContentIcon = icon; - return this; - } - - /** - * Set the gravity that the content icon should have within the notification display. - * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default - * value is {@link android.view.Gravity#END}. - * @see #setContentIcon - */ - public Builder setContentIconGravity(int contentIconGravity) { - mContentIconGravity = contentIconGravity; - return this; - } - - /** - * Set an action from this notification's actions to be clickable with the content of - * this notification page. This action will no longer display separately from the - * notification content. This action's icon will display with optional subtext provided - * by the action's title. - * @param actionIndex The index of the action to hoist on the current notification page. - * If wearable actions are present, this index will apply to that list, - * otherwise it will apply to the main notification's actions list. - */ - public Builder setContentAction(int actionIndex) { - mContentActionIndex = actionIndex; - return this; - } - - /** - * Set the gravity that this notification should have within the available viewport space. - * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and - * {@link Gravity#BOTTOM}. The default value is {@link Gravity#BOTTOM}. - */ - public Builder setGravity(int gravity) { - mGravity = gravity; - return this; - } - - /** - * Set the custom size preset for the display of this notification out of the available - * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}. - * <p>Some custom size presets are only applicable for custom display notifications created - * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in - * question. See also {@link Builder#setCustomContentHeight} and - * {@link #getCustomSizePreset}. - */ - public Builder setCustomSizePreset(int sizePreset) { - mCustomSizePreset = sizePreset; - return this; - } - - /** - * Set the custom height in pixels for the display of this notification's content. - * <p>This option is only available for custom display notifications created - * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and - * {@link #getCustomContentHeight}. - */ - public Builder setCustomContentHeight(int height) { - mCustomContentHeight = height; - return this; - } - - /** - * Set whether the scrolling position for the contents of this notification should start - * at the bottom of the contents instead of the top when the contents are too long to - * display within the screen. Default is false (start scroll at the top). - */ - public Builder setStartScrollBottom(boolean startScrollBottom) { - setFlag(FLAG_START_SCROLL_BOTTOM, startScrollBottom); - return this; - } - - /** - * Set whether the content intent is available when the wearable device is not connected - * to a companion device. The user can still trigger this intent when the wearable device - * is offline, but a visual hint will indicate that the content intent may not be available. - * Defaults to true. - */ - public Builder setContentIntentAvailableOffline(boolean contentIntentAvailableOffline) { - setFlag(FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE, contentIntentAvailableOffline); - return this; - } - - /** - * Set a hint that this notification's icon should not be displayed. - * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise. - * @return this object for method chaining - */ - public Builder setHintHideIcon(boolean hintHideIcon) { - setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon); - return this; - } - - /** - * Set a visual hint that only the background image of this notification should be - * displayed, and other semantic content should be hidden. This hint is only applicable - * to sub-pages added using {@link #addPage}. - */ - public Builder setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) { - setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly); - return this; - } - - /** - * Build a new {@link WearableNotificationExtensions} object with the extensions - * currently present on this builder. - * @return the extensions object. - */ - public WearableNotificationExtensions build() { - return new WearableNotificationExtensions( - mActions.toArray(new Notification.Action[mActions.size()]), mFlags, - mDisplayIntent, mPages.toArray(new Notification[mPages.size()]), - mBackground, mContentIcon, mContentIconGravity, mContentActionIndex, - mCustomSizePreset, mCustomContentHeight, mGravity); - } - - private void setFlag(int mask, boolean value) { - if (value) { - mFlags |= mask; - } else { - mFlags &= ~mask; - } - } - } - - public static final Creator<WearableNotificationExtensions> CREATOR = - new Creator<WearableNotificationExtensions>() { - @Override - public WearableNotificationExtensions createFromParcel(Parcel in) { - return new WearableNotificationExtensions(in); - } - - @Override - public WearableNotificationExtensions[] newArray(int size) { - return new WearableNotificationExtensions[size]; - } - }; -} |