From e458aa8dbd515548bd31458216d6ae203dfcfba3 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Tue, 8 Dec 2015 16:17:19 -0800 Subject: [PATCH] Add reply text section to notifications Also fixes a potential NPE in the failed inflation logging in SystemUI. Bug: 22452379 Change-Id: I829c332f7f708de8374740f6d02a2bc10a33386b --- api/current.txt | 2 + api/system-current.txt | 2 + api/test-current.txt | 2 + core/java/android/app/Notification.java | 93 ++++++++++++++++++- .../notification_material_reply_text.xml | 61 ++++++++++++ ...otification_template_material_big_base.xml | 5 + ...fication_template_material_big_picture.xml | 7 ++ ...otification_template_material_big_text.xml | 7 ++ core/res/res/values/styles_material.xml | 2 + core/res/res/values/symbols.xml | 5 + .../systemui/statusbar/BaseStatusBar.java | 3 +- 11 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 core/res/res/layout/notification_material_reply_text.xml diff --git a/api/current.txt b/api/current.txt index df6c473a3a662..8594236740983 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4851,6 +4851,7 @@ package android.app { field public static final java.lang.String EXTRA_PROGRESS = "android.progress"; field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate"; field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax"; + field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory"; field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer"; field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen"; field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon"; @@ -5017,6 +5018,7 @@ package android.app { method public android.app.Notification.Builder setPriority(int); method public android.app.Notification.Builder setProgress(int, int, boolean); method public android.app.Notification.Builder setPublicVersion(android.app.Notification); + method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]); method public android.app.Notification.Builder setShowWhen(boolean); method public android.app.Notification.Builder setSmallIcon(int); method public android.app.Notification.Builder setSmallIcon(int, int); diff --git a/api/system-current.txt b/api/system-current.txt index 3b585146074ec..91337c7991f70 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4971,6 +4971,7 @@ package android.app { field public static final java.lang.String EXTRA_PROGRESS = "android.progress"; field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate"; field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax"; + field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory"; field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer"; field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen"; field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon"; @@ -5137,6 +5138,7 @@ package android.app { method public android.app.Notification.Builder setPriority(int); method public android.app.Notification.Builder setProgress(int, int, boolean); method public android.app.Notification.Builder setPublicVersion(android.app.Notification); + method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]); method public android.app.Notification.Builder setShowWhen(boolean); method public android.app.Notification.Builder setSmallIcon(int); method public android.app.Notification.Builder setSmallIcon(int, int); diff --git a/api/test-current.txt b/api/test-current.txt index c4948957cb521..728bd7976bb9d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4851,6 +4851,7 @@ package android.app { field public static final java.lang.String EXTRA_PROGRESS = "android.progress"; field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate"; field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax"; + field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory"; field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer"; field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen"; field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon"; @@ -5017,6 +5018,7 @@ package android.app { method public android.app.Notification.Builder setPriority(int); method public android.app.Notification.Builder setProgress(int, int, boolean); method public android.app.Notification.Builder setPublicVersion(android.app.Notification); + method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]); method public android.app.Notification.Builder setShowWhen(boolean); method public android.app.Notification.Builder setSmallIcon(int); method public android.app.Notification.Builder setSmallIcon(int, int); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 620ab508045cb..8056cb7777f43 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -144,6 +144,11 @@ public class Notification implements Parcelable */ private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024; + /** + * Maximum entries of reply text that are accepted by Builder and friends. + */ + private static final int MAX_REPLY_HISTORY = 5; + /** * A timestamp related to this notification, in milliseconds since the epoch. * @@ -744,6 +749,12 @@ public class Notification implements Parcelable */ public static final String EXTRA_SUB_TEXT = "android.subText"; + /** + * {@link #extras} key: this is the remote input history, as supplied to + * {@link Builder#setRemoteInputHistory(CharSequence[])}. + */ + public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory"; + /** * {@link #extras} key: this is a small piece of additional text as supplied to * {@link Builder#setContentInfo(CharSequence)}. @@ -2323,6 +2334,34 @@ public class Notification implements Parcelable return this; } + /** + * Set the remote input history. + * + * This should be set to the most recent inputs that have been sent + * through a {@link RemoteInput} of this Notification and cleared once the it is no + * longer relevant (e.g. for chat notifications once the other party has responded). + * + * The most recent input must be stored at the 0 index, the second most recent at the + * 1 index, etc. Note that the system will limit both how far back the inputs will be shown + * and how much of each individual input is shown. + * + *

Note: The reply text will only be shown on notifications that have least one action + * with a {@code RemoteInput}.

+ */ + public Builder setRemoteInputHistory(CharSequence[] text) { + if (text == null) { + mN.extras.putCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY, null); + } else { + final int N = Math.min(MAX_REPLY_HISTORY, text.length); + CharSequence[] safe = new CharSequence[N]; + for (int i = 0; i < N; i++) { + safe[i] = safeCharSequence(text[i]); + } + mN.extras.putCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY, safe); + } + return this; + } + /** * Set the large number at the right-hand side of the notification. This is * equivalent to setContentInfo, although it might show the number in a different @@ -3214,6 +3253,14 @@ public class Notification implements Parcelable private void resetStandardTemplateWithActions(RemoteViews big) { big.setViewVisibility(R.id.actions, View.GONE); big.removeAllViews(R.id.actions); + + big.setViewVisibility(R.id.notification_material_reply_container, View.GONE); + big.setTextViewText(R.id.notification_material_reply_text_1, null); + + big.setViewVisibility(R.id.notification_material_reply_text_2, View.GONE); + big.setTextViewText(R.id.notification_material_reply_text_2, null); + big.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE); + big.setTextViewText(R.id.notification_material_reply_text_3, null); } private RemoteViews applyStandardTemplateWithActions(int layoutId) { @@ -3221,18 +3268,62 @@ public class Notification implements Parcelable resetStandardTemplateWithActions(big); + boolean validRemoteInput = false; + int N = mActions.size(); if (N > 0) { big.setViewVisibility(R.id.actions, View.VISIBLE); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; for (int i=0; i 0 && !TextUtils.isEmpty(replyText[0])) { + big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE); + big.setTextViewText(R.id.notification_material_reply_text_1, replyText[0]); + + if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])) { + big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE); + big.setTextViewText(R.id.notification_material_reply_text_2, replyText[1]); + + if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2])) { + big.setViewVisibility( + R.id.notification_material_reply_text_3, View.VISIBLE); + big.setTextViewText(R.id.notification_material_reply_text_3, replyText[2]); + } + } + } + return big; } + private boolean hasValidRemoteInput(Action action) { + if (TextUtils.isEmpty(action.title) || action.actionIntent == null) { + // Weird actions + return false; + } + + RemoteInput[] remoteInputs = action.getRemoteInputs(); + if (remoteInputs == null) { + return false; + } + + for (RemoteInput r : remoteInputs) { + CharSequence[] choices = r.getChoices(); + if (r.getAllowFreeFormInput() || (choices != null && choices.length != 0)) { + return true; + } + } + return false; + } + /** * Construct a RemoteViews for the final 1U notification layout. In order: * 1. Custom contentView from the caller diff --git a/core/res/res/layout/notification_material_reply_text.xml b/core/res/res/layout/notification_material_reply_text.xml new file mode 100644 index 0000000000000..bc22eb49cf57f --- /dev/null +++ b/core/res/res/layout/notification_material_reply_text.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml index eb02e8b8cf745..c50f534ebf86b 100644 --- a/core/res/res/layout/notification_template_material_big_base.xml +++ b/core/res/res/layout/notification_template_material_big_base.xml @@ -55,6 +55,11 @@ + + diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml index 9e010f20b0ca3..9c96fbcdec924 100644 --- a/core/res/res/layout/notification_template_material_big_text.xml +++ b/core/res/res/layout/notification_template_material_big_text.xml @@ -62,6 +62,13 @@ android:contentDescription="@string/notification_work_profile_content_description" /> + diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index 74ebf266910a2..8485e59be5a9b 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -432,6 +432,8 @@ please see styles_device_defaults.xml. @dimen/notification_text_size +