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 android.app.Notification; 20import android.app.PendingIntent; 21import android.content.Context; 22import android.graphics.Bitmap; 23import android.os.Bundle; 24import android.os.Parcelable; 25import android.widget.RemoteViews; 26 27import java.util.ArrayList; 28 29class NotificationCompatApi21 { 30 31 public static final String CATEGORY_CALL = Notification.CATEGORY_CALL; 32 public static final String CATEGORY_MESSAGE = Notification.CATEGORY_MESSAGE; 33 public static final String CATEGORY_EMAIL = Notification.CATEGORY_EMAIL; 34 public static final String CATEGORY_EVENT = Notification.CATEGORY_EVENT; 35 public static final String CATEGORY_PROMO = Notification.CATEGORY_PROMO; 36 public static final String CATEGORY_ALARM = Notification.CATEGORY_ALARM; 37 public static final String CATEGORY_PROGRESS = Notification.CATEGORY_PROGRESS; 38 public static final String CATEGORY_SOCIAL = Notification.CATEGORY_SOCIAL; 39 public static final String CATEGORY_ERROR = Notification.CATEGORY_ERROR; 40 public static final String CATEGORY_TRANSPORT = Notification.CATEGORY_TRANSPORT; 41 public static final String CATEGORY_SYSTEM = Notification.CATEGORY_SYSTEM; 42 public static final String CATEGORY_SERVICE = Notification.CATEGORY_SERVICE; 43 public static final String CATEGORY_RECOMMENDATION = Notification.CATEGORY_RECOMMENDATION; 44 public static final String CATEGORY_STATUS = Notification.CATEGORY_STATUS; 45 46 private static final String KEY_AUTHOR = "author"; 47 private static final String KEY_TEXT = "text"; 48 private static final String KEY_MESSAGES = "messages"; 49 private static final String KEY_REMOTE_INPUT = "remote_input"; 50 private static final String KEY_ON_REPLY = "on_reply"; 51 private static final String KEY_ON_READ = "on_read"; 52 private static final String KEY_PARTICIPANTS = "participants"; 53 private static final String KEY_TIMESTAMP = "timestamp"; 54 55 public static class Builder implements NotificationBuilderWithBuilderAccessor, 56 NotificationBuilderWithActions { 57 private Notification.Builder b; 58 private Bundle mExtras; 59 private RemoteViews mContentView; 60 private RemoteViews mBigContentView; 61 private RemoteViews mHeadsUpContentView; 62 63 public Builder(Context context, Notification n, 64 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, 65 RemoteViews tickerView, int number, 66 PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, 67 int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, 68 boolean useChronometer, int priority, CharSequence subText, boolean localOnly, 69 String category, ArrayList<String> people, Bundle extras, int color, 70 int visibility, Notification publicVersion, String groupKey, boolean groupSummary, 71 String sortKey, RemoteViews contentView, RemoteViews bigContentView, 72 RemoteViews headsUpContentView) { 73 b = new Notification.Builder(context) 74 .setWhen(n.when) 75 .setShowWhen(showWhen) 76 .setSmallIcon(n.icon, n.iconLevel) 77 .setContent(n.contentView) 78 .setTicker(n.tickerText, tickerView) 79 .setSound(n.sound, n.audioStreamType) 80 .setVibrate(n.vibrate) 81 .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) 82 .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) 83 .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) 84 .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) 85 .setDefaults(n.defaults) 86 .setContentTitle(contentTitle) 87 .setContentText(contentText) 88 .setSubText(subText) 89 .setContentInfo(contentInfo) 90 .setContentIntent(contentIntent) 91 .setDeleteIntent(n.deleteIntent) 92 .setFullScreenIntent(fullScreenIntent, 93 (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) 94 .setLargeIcon(largeIcon) 95 .setNumber(number) 96 .setUsesChronometer(useChronometer) 97 .setPriority(priority) 98 .setProgress(progressMax, progress, progressIndeterminate) 99 .setLocalOnly(localOnly) 100 .setGroup(groupKey) 101 .setGroupSummary(groupSummary) 102 .setSortKey(sortKey) 103 .setCategory(category) 104 .setColor(color) 105 .setVisibility(visibility) 106 .setPublicVersion(publicVersion); 107 mExtras = new Bundle(); 108 if (extras != null) { 109 mExtras.putAll(extras); 110 } 111 for (String person: people) { 112 b.addPerson(person); 113 } 114 mContentView = contentView; 115 mBigContentView = bigContentView; 116 mHeadsUpContentView = headsUpContentView; 117 } 118 119 @Override 120 public void addAction(NotificationCompatBase.Action action) { 121 NotificationCompatApi20.addAction(b, action); 122 } 123 124 @Override 125 public Notification.Builder getBuilder() { 126 return b; 127 } 128 129 @Override 130 public Notification build() { 131 b.setExtras(mExtras); 132 Notification notification = b.build(); 133 if (mContentView != null) { 134 notification.contentView = mContentView; 135 } 136 if (mBigContentView != null) { 137 notification.bigContentView = mBigContentView; 138 } 139 if (mHeadsUpContentView != null) { 140 notification.headsUpContentView = mHeadsUpContentView; 141 } 142 return notification; 143 } 144 } 145 146 public static String getCategory(Notification notif) { 147 return notif.category; 148 } 149 150 static Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) { 151 if (uc == null) { 152 return null; 153 } 154 Bundle b = new Bundle(); 155 String author = null; 156 if (uc.getParticipants() != null && uc.getParticipants().length > 1) { 157 author = uc.getParticipants()[0]; 158 } 159 Parcelable[] messages = new Parcelable[uc.getMessages().length]; 160 for (int i = 0; i < messages.length; i++) { 161 Bundle m = new Bundle(); 162 m.putString(KEY_TEXT, uc.getMessages()[i]); 163 m.putString(KEY_AUTHOR, author); 164 messages[i] = m; 165 } 166 b.putParcelableArray(KEY_MESSAGES, messages); 167 RemoteInputCompatBase.RemoteInput remoteInput = uc.getRemoteInput(); 168 if (remoteInput != null) { 169 b.putParcelable(KEY_REMOTE_INPUT, fromCompatRemoteInput(remoteInput)); 170 } 171 b.putParcelable(KEY_ON_REPLY, uc.getReplyPendingIntent()); 172 b.putParcelable(KEY_ON_READ, uc.getReadPendingIntent()); 173 b.putStringArray(KEY_PARTICIPANTS, uc.getParticipants()); 174 b.putLong(KEY_TIMESTAMP, uc.getLatestTimestamp()); 175 return b; 176 } 177 178 static NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle( 179 Bundle b, NotificationCompatBase.UnreadConversation.Factory factory, 180 RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 181 if (b == null) { 182 return null; 183 } 184 Parcelable[] parcelableMessages = b.getParcelableArray(KEY_MESSAGES); 185 String[] messages = null; 186 if (parcelableMessages != null) { 187 String[] tmp = new String[parcelableMessages.length]; 188 boolean success = true; 189 for (int i = 0; i < tmp.length; i++) { 190 if (!(parcelableMessages[i] instanceof Bundle)) { 191 success = false; 192 break; 193 } 194 tmp[i] = ((Bundle) parcelableMessages[i]).getString(KEY_TEXT); 195 if (tmp[i] == null) { 196 success = false; 197 break; 198 } 199 } 200 if (success) { 201 messages = tmp; 202 } else { 203 return null; 204 } 205 } 206 207 PendingIntent onRead = b.getParcelable(KEY_ON_READ); 208 PendingIntent onReply = b.getParcelable(KEY_ON_REPLY); 209 210 android.app.RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT); 211 212 String[] participants = b.getStringArray(KEY_PARTICIPANTS); 213 if (participants == null || participants.length != 1) { 214 return null; 215 } 216 217 218 return factory.build( 219 messages, 220 remoteInput != null ? toCompatRemoteInput(remoteInput, remoteInputFactory) : null, 221 onReply, 222 onRead, 223 participants, b.getLong(KEY_TIMESTAMP)); 224 } 225 226 private static android.app.RemoteInput fromCompatRemoteInput( 227 RemoteInputCompatBase.RemoteInput src) { 228 return new android.app.RemoteInput.Builder(src.getResultKey()) 229 .setLabel(src.getLabel()) 230 .setChoices(src.getChoices()) 231 .setAllowFreeFormInput(src.getAllowFreeFormInput()) 232 .addExtras(src.getExtras()) 233 .build(); 234 } 235 236 private static RemoteInputCompatBase.RemoteInput toCompatRemoteInput( 237 android.app.RemoteInput remoteInput, 238 RemoteInputCompatBase.RemoteInput.Factory factory) { 239 return factory.build(remoteInput.getResultKey(), 240 remoteInput.getLabel(), 241 remoteInput.getChoices(), 242 remoteInput.getAllowFreeFormInput(), 243 remoteInput.getExtras()); 244 } 245} 246