summaryrefslogtreecommitdiff
path: root/core/java/android/app/Notification.java
diff options
context:
space:
mode:
authorMady Mellor <madym@google.com>2020-03-17 10:34:20 -0700
committerMady Mellor <madym@google.com>2020-03-19 10:21:34 -0700
commitaa9ce17fa28484780f4334ce5481ca701beb1f90 (patch)
tree339478a0887df091e5d0fb1ce3e3f36ff10d330a /core/java/android/app/Notification.java
parent18dd476b0c93b4d0666cc7d2d130a6065b5fea6d (diff)
Bubbles API council feedback
* un-deprecate getIntent/getIcon/setIntent/setIcon * deprecate createIntentBubble & createShortcutBubble and make them constructor methods & deprecate existing constructor * clarify when intent / icon / shortcut id will be null or not * use NPE instead of illegal argument exception * use illegal state exception when using setIcon/setIntent on a builder created with shortcut method * updates usages of getBubbleIntent/getBubbleIcon to be getIntent/getIcon * updates builder constructor usages as well Fixes: 149911930 Test: treehugger Change-Id: Ic85a475d463cb22cea7d7939fea4cf72465491b4
Diffstat (limited to 'core/java/android/app/Notification.java')
-rw-r--r--core/java/android/app/Notification.java201
1 files changed, 132 insertions, 69 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 864af3d4ae4d..4dd295dbbe1e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -34,6 +34,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -2533,8 +2534,8 @@ public class Notification implements Parcelable
}
}
- if (mBubbleMetadata != null && mBubbleMetadata.getBubbleIcon() != null) {
- final Icon icon = mBubbleMetadata.getBubbleIcon();
+ if (mBubbleMetadata != null && mBubbleMetadata.getIcon() != null) {
+ final Icon icon = mBubbleMetadata.getIcon();
final int iconType = icon.getType();
if (iconType == TYPE_URI_ADAPTIVE_BITMAP || iconType == TYPE_URI) {
visitor.accept(icon.getUri());
@@ -3596,15 +3597,14 @@ public class Notification implements Parcelable
* notification content, or don't show {@link android.content.pm.ShortcutManager shortcuts}.
*
* If this notification has {@link BubbleMetadata} attached that was created with
- * {@link BubbleMetadata.Builder#createShortcutBubble(String)} a check will be performed
- * to ensure the shortcutId supplied to bubble metadata matches the shortcutId set here,
- * if one was set. If the shortcutId's were specified but do not match, an exception
- * is thrown.
+ * a shortcutId a check will be performed to ensure the shortcutId supplied to bubble
+ * metadata matches the shortcutId set here, if one was set. If the shortcutId's were
+ * specified but do not match, an exception is thrown.
*
* @param shortcutId the {@link ShortcutInfo#getId() id} of the shortcut this notification
* supersedes
*
- * @see BubbleMetadata.Builder#createShortcutBubble(String)
+ * @see Notification.BubbleMetadata.Builder#Builder(String)
*/
@NonNull
public Builder setShortcutId(String shortcutId) {
@@ -5962,12 +5962,11 @@ public class Notification implements Parcelable
* object.
*
* If this notification has {@link BubbleMetadata} attached that was created with
- * {@link BubbleMetadata.Builder#createShortcutBubble(String)} a check will be performed
- * to ensure the shortcutId supplied to bubble metadata matches the shortcutId set on the
- * notification builder, if one was set. If the shortcutId's were specified but do not
- * match, an exception is thrown here.
+ * a shortcutId a check will be performed to ensure the shortcutId supplied to bubble
+ * metadata matches the shortcutId set on the notification builder, if one was set.
+ * If the shortcutId's were specified but do not match, an exception is thrown here.
*
- * @see BubbleMetadata.Builder#createShortcutBubble(String)
+ * @see Notification.BubbleMetadata.Builder#Builder(String)
* @see #setShortcutId(String)
*/
@NonNull
@@ -8669,9 +8668,8 @@ public class Notification implements Parcelable
* <p>A bubble is used to display app content in a floating window over the existing
* foreground activity. A bubble has a collapsed state represented by an icon and an
* expanded state that displays an activity. These may be defined via
- * {@link BubbleMetadata.Builder#createIntentBubble(PendingIntent, Icon)} or they may
- * be definied via an existing shortcut using
- * {@link BubbleMetadata.Builder#createShortcutBubble(String)}.
+ * {@link Builder#Builder(PendingIntent, Icon)} or they may
+ * be defined via an existing shortcut using {@link Builder#Builder(String)}.
* </p>
*
* <b>Notifications with a valid and allowed bubble will display in collapsed state
@@ -8692,8 +8690,7 @@ public class Notification implements Parcelable
/**
* If set and the app creating the bubble is in the foreground, the bubble will be posted
- * in its expanded state, with the contents of {@link #getBubbleIntent()} in a floating
- * window.
+ * in its expanded state.
*
* <p>This flag has no effect if the app posting the bubble is not in the foreground.
* The app is considered foreground if it is visible and on the screen, note that
@@ -8759,7 +8756,9 @@ public class Notification implements Parcelable
}
/**
- * @return the shortcut id used to populate the bubble, if it exists.
+ * @return the shortcut id used for this bubble if created via
+ * {@link Builder#Builder(String)} or null if created
+ * via {@link Builder#Builder(PendingIntent, Icon)}.
*/
@Nullable
public String getShortcutId() {
@@ -8767,20 +8766,20 @@ public class Notification implements Parcelable
}
/**
- * @deprecated use {@link #getBubbleIntent()} or use {@link #getShortcutId()} if created
- * with a valid shortcut instead.
+ * @return the pending intent used to populate the floating window for this bubble, or
+ * null if this bubble is created via {@link Builder#Builder(String)}.
*/
- @Deprecated
- @NonNull
+ @SuppressLint("InvalidNullConversion")
+ @Nullable
public PendingIntent getIntent() {
return mPendingIntent;
}
/**
- * @return the pending intent used to populate the floating window for this bubble, or
- * null if this bubble is shortcut based.
+ * @deprecated use {@link #getIntent()} instead.
*/
@Nullable
+ @Deprecated
public PendingIntent getBubbleIntent() {
return mPendingIntent;
}
@@ -8794,27 +8793,27 @@ public class Notification implements Parcelable
}
/**
- * @deprecated use {@link #getBubbleIcon()} or use {@link #getShortcutId()} if created
- * with a valid shortcut instead.
+ * @return the icon that will be displayed for this bubble when it is collapsed, or null
+ * if the bubble is created via {@link Builder#Builder(String)}.
*/
- @Deprecated
- @NonNull
+ @SuppressLint("InvalidNullConversion")
+ @Nullable
public Icon getIcon() {
return mIcon;
}
/**
- * @return the icon that will be displayed for this bubble when it is collapsed, or null
- * if the bubble is shortcut based.
+ * @deprecated use {@link #getIcon()} instead.
*/
@Nullable
+ @Deprecated
public Icon getBubbleIcon() {
return mIcon;
}
/**
* @return the ideal height, in DPs, for the floating window that app content defined by
- * {@link #getBubbleIntent()} for this bubble. A value of 0 indicates a desired height has
+ * {@link #getIntent()} for this bubble. A value of 0 indicates a desired height has
* not been set.
*/
@Dimension(unit = DP)
@@ -8824,7 +8823,7 @@ public class Notification implements Parcelable
/**
* @return the resId of ideal height for the floating window that app content defined by
- * {@link #getBubbleIntent()} for this bubble. A value of 0 indicates a res value has not
+ * {@link #getIntent()} for this bubble. A value of 0 indicates a res value has not
* been provided for the desired height.
*/
@DimenRes
@@ -8938,15 +8937,20 @@ public class Notification implements Parcelable
private String mShortcutId;
/**
- * Constructs a new builder object.
+ * @deprecated use {@link Builder#Builder(String)} for a bubble created via a
+ * {@link ShortcutInfo} or {@link Builder#Builder(PendingIntent, Icon)} for a bubble
+ * created via a {@link PendingIntent}.
*/
+ @Deprecated
public Builder() {
}
/**
- * Creates a {@link BubbleMetadata.Builder} based on a shortcut. Only
- * {@link android.content.pm.ShortcutManager#addDynamicShortcuts(List)} shortcuts are
- * supported.
+ * Creates a {@link BubbleMetadata.Builder} based on a {@link ShortcutInfo}. To create
+ * a shortcut bubble, ensure that the shortcut associated with the provided
+ * {@param shortcutId} is published as a dynamic shortcut that was built with
+ * {@link ShortcutInfo.Builder#setLongLived(boolean)} being true, otherwise your
+ * notification will not be able to bubble.
*
* <p>The shortcut icon will be used to represent the bubble when it is collapsed.</p>
*
@@ -8957,19 +8961,17 @@ public class Notification implements Parcelable
* no bubble will be produced. If the shortcut is deleted while the bubble is active,
* the bubble will be removed.</p>
*
- * <p>Calling this method will clear the contents of
- * {@link #createIntentBubble(PendingIntent, Icon)} if it was previously called on
- * this builder.</p>
+ * @throws NullPointerException if shortcutId is null.
+ *
+ * @see ShortcutInfo
+ * @see ShortcutInfo.Builder#setLongLived(boolean)
+ * @see android.content.pm.ShortcutManager#addDynamicShortcuts(List)
*/
- @NonNull
- public BubbleMetadata.Builder createShortcutBubble(@NonNull String shortcutId) {
- if (!TextUtils.isEmpty(shortcutId)) {
- // If shortcut id is set, we don't use these if they were previously set.
- mPendingIntent = null;
- mIcon = null;
+ public Builder(@NonNull String shortcutId) {
+ if (TextUtils.isEmpty(shortcutId)) {
+ throw new NullPointerException("Bubble requires a non-null shortcut id");
}
mShortcutId = shortcutId;
- return this;
}
/**
@@ -8980,16 +8982,49 @@ public class Notification implements Parcelable
* multiple bubbles, the icon should be unique for each of them.</p>
*
* <p>The intent that will be used when the bubble is expanded. This will display the
- * app content in a floating window over the existing foreground activity.</p>
- *
- * <p>Calling this method will clear the contents of
- * {@link #createShortcutBubble(String)} if it was previously called on this builder.
- * </p>
+ * app content in a floating window over the existing foreground activity. The intent
+ * should point to a resizable activity. </p>
*
- * @throws IllegalArgumentException if intent is null.
- * @throws IllegalArgumentException if icon is null.
+ * @throws NullPointerException if intent is null.
+ * @throws NullPointerException if icon is null.
+ */
+ public Builder(@NonNull PendingIntent intent, @NonNull Icon icon) {
+ if (intent == null) {
+ throw new NullPointerException("Bubble requires non-null pending intent");
+ }
+ if (icon == null) {
+ throw new NullPointerException("Bubbles require non-null icon");
+ }
+ if (icon.getType() != TYPE_URI_ADAPTIVE_BITMAP
+ && icon.getType() != TYPE_URI) {
+ Log.w(TAG, "Bubbles work best with icons of TYPE_URI or "
+ + "TYPE_URI_ADAPTIVE_BITMAP. "
+ + "In the future, using an icon of this type will be required.");
+ }
+ mPendingIntent = intent;
+ mIcon = icon;
+ }
+
+ /**
+ * @deprecated use {@link Builder#Builder(String)} instead.
*/
@NonNull
+ @Deprecated
+ public BubbleMetadata.Builder createShortcutBubble(@NonNull String shortcutId) {
+ if (!TextUtils.isEmpty(shortcutId)) {
+ // If shortcut id is set, we don't use these if they were previously set.
+ mPendingIntent = null;
+ mIcon = null;
+ }
+ mShortcutId = shortcutId;
+ return this;
+ }
+
+ /**
+ * @deprecated use {@link Builder#Builder(PendingIntent, Icon)} instead.
+ */
+ @NonNull
+ @Deprecated
public BubbleMetadata.Builder createIntentBubble(@NonNull PendingIntent intent,
@NonNull Icon icon) {
if (intent == null) {
@@ -9011,31 +9046,61 @@ public class Notification implements Parcelable
}
/**
- * @deprecated use {@link #createIntentBubble(PendingIntent, Icon)}
- * or {@link #createShortcutBubble(String)} instead.
+ * Sets the intent for the bubble.
+ *
+ * <p>The intent that will be used when the bubble is expanded. This will display the
+ * app content in a floating window over the existing foreground activity. The intent
+ * should point to a resizable activity. </p>
+ *
+ * @throws NullPointerException if intent is null.
+ * @throws IllegalStateException if this builder was created via
+ * {@link Builder#Builder(String)}.
*/
- @Deprecated
@NonNull
public BubbleMetadata.Builder setIntent(@NonNull PendingIntent intent) {
+ if (mShortcutId != null) {
+ throw new IllegalStateException("Created as a shortcut bubble, cannot set a "
+ + "PendingIntent. Consider using "
+ + "BubbleMetadata.Builder(PendingIntent,Icon) instead.");
+ }
if (intent == null) {
- throw new IllegalArgumentException("Bubble requires non-null pending intent");
+ throw new NullPointerException("Bubble requires non-null pending intent");
}
- mShortcutId = null;
mPendingIntent = intent;
return this;
}
/**
- * @deprecated use {@link #createIntentBubble(PendingIntent, Icon)}
- * or {@link #createShortcutBubble(String)} instead.
+ * Sets the icon for the bubble. Can only be used if the bubble was created
+ * via {@link Builder#Builder(PendingIntent, Icon)}.
+ *
+ * <p>The icon will be used to represent the bubble when it is collapsed. An icon
+ * should be representative of the content within the bubble. If your app produces
+ * multiple bubbles, the icon should be unique for each of them.</p>
+ *
+ * <p>It is recommended to use an {@link Icon} of type {@link Icon#TYPE_URI}
+ * or {@link Icon#TYPE_URI_ADAPTIVE_BITMAP}</p>
+ *
+ * @throws NullPointerException if icon is null.
+ * @throws IllegalStateException if this builder was created via
+ * {@link Builder#Builder(String)}.
*/
- @Deprecated
@NonNull
public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
+ if (mShortcutId != null) {
+ throw new IllegalStateException("Created as a shortcut bubble, cannot set an "
+ + "Icon. Consider using "
+ + "BubbleMetadata.Builder(PendingIntent,Icon) instead.");
+ }
if (icon == null) {
- throw new IllegalArgumentException("Bubbles require non-null icon");
+ throw new NullPointerException("Bubbles require non-null icon");
+ }
+ if (icon.getType() != TYPE_URI_ADAPTIVE_BITMAP
+ && icon.getType() != TYPE_URI) {
+ Log.w(TAG, "Bubbles work best with icons of TYPE_URI or "
+ + "TYPE_URI_ADAPTIVE_BITMAP. "
+ + "In the future, using an icon of this type will be required.");
}
- mShortcutId = null;
mIcon = icon;
return this;
}
@@ -9084,8 +9149,7 @@ public class Notification implements Parcelable
}
/**
- * Sets whether the bubble will be posted in its expanded state (with the contents of
- * {@link #getBubbleIntent()} in a floating window).
+ * Sets whether the bubble will be posted in its expanded state.
*
* <p>This flag has no effect if the app posting the bubble is not in the foreground.
* The app is considered foreground if it is visible and on the screen, note that
@@ -9138,17 +9202,16 @@ public class Notification implements Parcelable
/**
* Creates the {@link BubbleMetadata} defined by this builder.
*
- * @throws IllegalStateException if neither {@link #createShortcutBubble(String)} or
- * {@link #createIntentBubble(PendingIntent, Icon)} have been called on this builder.
+ * @throws NullPointerException if required elements have not been set.
*/
@NonNull
public BubbleMetadata build() {
if (mShortcutId == null && mPendingIntent == null) {
- throw new IllegalStateException(
+ throw new NullPointerException(
"Must supply pending intent or shortcut to bubble");
}
if (mShortcutId == null && mIcon == null) {
- throw new IllegalStateException(
+ throw new NullPointerException(
"Must supply an icon or shortcut for the bubble");
}
BubbleMetadata data = new BubbleMetadata(mPendingIntent, mDeleteIntent,