1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.app; 18 19import static android.support.v4.app.NotificationCompat.DEFAULT_SOUND; 20import static android.support.v4.app.NotificationCompat.DEFAULT_VIBRATE; 21import static android.support.v4.app.NotificationCompat.FLAG_GROUP_SUMMARY; 22import static android.support.v4.app.NotificationCompat.GROUP_ALERT_ALL; 23import static android.support.v4.app.NotificationCompat.GROUP_ALERT_CHILDREN; 24import static android.support.v4.app.NotificationCompat.GROUP_ALERT_SUMMARY; 25 26import android.app.Notification; 27import android.app.PendingIntent; 28import android.content.Context; 29import android.graphics.Bitmap; 30import android.os.Bundle; 31import android.os.Parcelable; 32import android.support.annotation.RequiresApi; 33import android.widget.RemoteViews; 34 35import java.util.ArrayList; 36 37@RequiresApi(21) 38class NotificationCompatApi21 { 39 40 public static final String CATEGORY_CALL = Notification.CATEGORY_CALL; 41 public static final String CATEGORY_MESSAGE = Notification.CATEGORY_MESSAGE; 42 public static final String CATEGORY_EMAIL = Notification.CATEGORY_EMAIL; 43 public static final String CATEGORY_EVENT = Notification.CATEGORY_EVENT; 44 public static final String CATEGORY_PROMO = Notification.CATEGORY_PROMO; 45 public static final String CATEGORY_ALARM = Notification.CATEGORY_ALARM; 46 public static final String CATEGORY_PROGRESS = Notification.CATEGORY_PROGRESS; 47 public static final String CATEGORY_SOCIAL = Notification.CATEGORY_SOCIAL; 48 public static final String CATEGORY_ERROR = Notification.CATEGORY_ERROR; 49 public static final String CATEGORY_TRANSPORT = Notification.CATEGORY_TRANSPORT; 50 public static final String CATEGORY_SYSTEM = Notification.CATEGORY_SYSTEM; 51 public static final String CATEGORY_SERVICE = Notification.CATEGORY_SERVICE; 52 public static final String CATEGORY_RECOMMENDATION = Notification.CATEGORY_RECOMMENDATION; 53 public static final String CATEGORY_STATUS = Notification.CATEGORY_STATUS; 54 55 private static final String KEY_AUTHOR = "author"; 56 private static final String KEY_TEXT = "text"; 57 private static final String KEY_MESSAGES = "messages"; 58 private static final String KEY_REMOTE_INPUT = "remote_input"; 59 private static final String KEY_ON_REPLY = "on_reply"; 60 private static final String KEY_ON_READ = "on_read"; 61 private static final String KEY_PARTICIPANTS = "participants"; 62 private static final String KEY_TIMESTAMP = "timestamp"; 63 64 public static class Builder implements NotificationBuilderWithBuilderAccessor, 65 NotificationBuilderWithActions { 66 private Notification.Builder b; 67 private Bundle mExtras; 68 private RemoteViews mContentView; 69 private RemoteViews mBigContentView; 70 private RemoteViews mHeadsUpContentView; 71 private int mGroupAlertBehavior; 72 73 public Builder(Context context, Notification n, 74 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, 75 RemoteViews tickerView, int number, 76 PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, 77 int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, 78 boolean useChronometer, int priority, CharSequence subText, boolean localOnly, 79 String category, ArrayList<String> people, Bundle extras, int color, 80 int visibility, Notification publicVersion, String groupKey, boolean groupSummary, 81 String sortKey, RemoteViews contentView, RemoteViews bigContentView, 82 RemoteViews headsUpContentView, int groupAlertBehavior) { 83 b = new Notification.Builder(context) 84 .setWhen(n.when) 85 .setShowWhen(showWhen) 86 .setSmallIcon(n.icon, n.iconLevel) 87 .setContent(n.contentView) 88 .setTicker(n.tickerText, tickerView) 89 .setSound(n.sound, n.audioStreamType) 90 .setVibrate(n.vibrate) 91 .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) 92 .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) 93 .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) 94 .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) 95 .setDefaults(n.defaults) 96 .setContentTitle(contentTitle) 97 .setContentText(contentText) 98 .setSubText(subText) 99 .setContentInfo(contentInfo) 100 .setContentIntent(contentIntent) 101 .setDeleteIntent(n.deleteIntent) 102 .setFullScreenIntent(fullScreenIntent, 103 (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) 104 .setLargeIcon(largeIcon) 105 .setNumber(number) 106 .setUsesChronometer(useChronometer) 107 .setPriority(priority) 108 .setProgress(progressMax, progress, progressIndeterminate) 109 .setLocalOnly(localOnly) 110 .setGroup(groupKey) 111 .setGroupSummary(groupSummary) 112 .setSortKey(sortKey) 113 .setCategory(category) 114 .setColor(color) 115 .setVisibility(visibility) 116 .setPublicVersion(publicVersion); 117 mExtras = new Bundle(); 118 if (extras != null) { 119 mExtras.putAll(extras); 120 } 121 for (String person: people) { 122 b.addPerson(person); 123 } 124 mContentView = contentView; 125 mBigContentView = bigContentView; 126 mHeadsUpContentView = headsUpContentView; 127 mGroupAlertBehavior = groupAlertBehavior; 128 } 129 130 @Override 131 public void addAction(NotificationCompatBase.Action action) { 132 NotificationCompatApi20.addAction(b, action); 133 } 134 135 @Override 136 public Notification.Builder getBuilder() { 137 return b; 138 } 139 140 @Override 141 public Notification build() { 142 b.setExtras(mExtras); 143 Notification notification = b.build(); 144 if (mContentView != null) { 145 notification.contentView = mContentView; 146 } 147 if (mBigContentView != null) { 148 notification.bigContentView = mBigContentView; 149 } 150 if (mHeadsUpContentView != null) { 151 notification.headsUpContentView = mHeadsUpContentView; 152 } 153 154 if (mGroupAlertBehavior != GROUP_ALERT_ALL) { 155 // if is summary and only children should alert 156 if (notification.getGroup() != null 157 && (notification.flags & FLAG_GROUP_SUMMARY) != 0 158 && mGroupAlertBehavior == GROUP_ALERT_CHILDREN) { 159 removeSoundAndVibration(notification); 160 } 161 // if is group child and only summary should alert 162 if (notification.getGroup() != null 163 && (notification.flags & FLAG_GROUP_SUMMARY) == 0 164 && mGroupAlertBehavior == GROUP_ALERT_SUMMARY) { 165 removeSoundAndVibration(notification); 166 } 167 } 168 return notification; 169 } 170 171 private void removeSoundAndVibration(Notification notification) { 172 notification.sound = null; 173 notification.vibrate = null; 174 notification.defaults &= ~DEFAULT_SOUND; 175 notification.defaults &= ~DEFAULT_VIBRATE; 176 } 177 } 178 179 static Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) { 180 if (uc == null) { 181 return null; 182 } 183 Bundle b = new Bundle(); 184 String author = null; 185 if (uc.getParticipants() != null && uc.getParticipants().length > 1) { 186 author = uc.getParticipants()[0]; 187 } 188 Parcelable[] messages = new Parcelable[uc.getMessages().length]; 189 for (int i = 0; i < messages.length; i++) { 190 Bundle m = new Bundle(); 191 m.putString(KEY_TEXT, uc.getMessages()[i]); 192 m.putString(KEY_AUTHOR, author); 193 messages[i] = m; 194 } 195 b.putParcelableArray(KEY_MESSAGES, messages); 196 RemoteInputCompatBase.RemoteInput remoteInput = uc.getRemoteInput(); 197 if (remoteInput != null) { 198 b.putParcelable(KEY_REMOTE_INPUT, fromCompatRemoteInput(remoteInput)); 199 } 200 b.putParcelable(KEY_ON_REPLY, uc.getReplyPendingIntent()); 201 b.putParcelable(KEY_ON_READ, uc.getReadPendingIntent()); 202 b.putStringArray(KEY_PARTICIPANTS, uc.getParticipants()); 203 b.putLong(KEY_TIMESTAMP, uc.getLatestTimestamp()); 204 return b; 205 } 206 207 static NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle( 208 Bundle b, NotificationCompatBase.UnreadConversation.Factory factory, 209 RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 210 if (b == null) { 211 return null; 212 } 213 Parcelable[] parcelableMessages = b.getParcelableArray(KEY_MESSAGES); 214 String[] messages = null; 215 if (parcelableMessages != null) { 216 String[] tmp = new String[parcelableMessages.length]; 217 boolean success = true; 218 for (int i = 0; i < tmp.length; i++) { 219 if (!(parcelableMessages[i] instanceof Bundle)) { 220 success = false; 221 break; 222 } 223 tmp[i] = ((Bundle) parcelableMessages[i]).getString(KEY_TEXT); 224 if (tmp[i] == null) { 225 success = false; 226 break; 227 } 228 } 229 if (success) { 230 messages = tmp; 231 } else { 232 return null; 233 } 234 } 235 236 PendingIntent onRead = b.getParcelable(KEY_ON_READ); 237 PendingIntent onReply = b.getParcelable(KEY_ON_REPLY); 238 239 android.app.RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT); 240 241 String[] participants = b.getStringArray(KEY_PARTICIPANTS); 242 if (participants == null || participants.length != 1) { 243 return null; 244 } 245 246 247 return factory.build( 248 messages, 249 remoteInput != null ? toCompatRemoteInput(remoteInput, remoteInputFactory) : null, 250 onReply, 251 onRead, 252 participants, b.getLong(KEY_TIMESTAMP)); 253 } 254 255 private static android.app.RemoteInput fromCompatRemoteInput( 256 RemoteInputCompatBase.RemoteInput src) { 257 return new android.app.RemoteInput.Builder(src.getResultKey()) 258 .setLabel(src.getLabel()) 259 .setChoices(src.getChoices()) 260 .setAllowFreeFormInput(src.getAllowFreeFormInput()) 261 .addExtras(src.getExtras()) 262 .build(); 263 } 264 265 private static RemoteInputCompatBase.RemoteInput toCompatRemoteInput( 266 android.app.RemoteInput remoteInput, 267 RemoteInputCompatBase.RemoteInput.Factory factory) { 268 return factory.build(remoteInput.getResultKey(), 269 remoteInput.getLabel(), 270 remoteInput.getChoices(), 271 remoteInput.getAllowFreeFormInput(), 272 remoteInput.getExtras(), 273 null /* allowedDataTypes */); 274 } 275} 276