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.app.RemoteInput; 22import android.content.Context; 23import android.graphics.Bitmap; 24import android.os.Bundle; 25import android.os.Parcelable; 26import android.widget.RemoteViews; 27 28import java.util.ArrayList; 29 30class NotificationCompatApi20 { 31 public static class Builder implements NotificationBuilderWithBuilderAccessor, 32 NotificationBuilderWithActions { 33 private Notification.Builder b; 34 private Bundle mExtras; 35 private RemoteViews mContentView; 36 private RemoteViews mBigContentView; 37 38 public Builder(Context context, Notification n, 39 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, 40 RemoteViews tickerView, int number, 41 PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, 42 int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, 43 boolean useChronometer, int priority, CharSequence subText, boolean localOnly, 44 ArrayList<String> people, Bundle extras, String groupKey, boolean groupSummary, 45 String sortKey, RemoteViews contentView, RemoteViews bigContentView) { 46 b = new Notification.Builder(context) 47 .setWhen(n.when) 48 .setShowWhen(showWhen) 49 .setSmallIcon(n.icon, n.iconLevel) 50 .setContent(n.contentView) 51 .setTicker(n.tickerText, tickerView) 52 .setSound(n.sound, n.audioStreamType) 53 .setVibrate(n.vibrate) 54 .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) 55 .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) 56 .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) 57 .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) 58 .setDefaults(n.defaults) 59 .setContentTitle(contentTitle) 60 .setContentText(contentText) 61 .setSubText(subText) 62 .setContentInfo(contentInfo) 63 .setContentIntent(contentIntent) 64 .setDeleteIntent(n.deleteIntent) 65 .setFullScreenIntent(fullScreenIntent, 66 (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) 67 .setLargeIcon(largeIcon) 68 .setNumber(number) 69 .setUsesChronometer(useChronometer) 70 .setPriority(priority) 71 .setProgress(progressMax, progress, progressIndeterminate) 72 .setLocalOnly(localOnly) 73 .setGroup(groupKey) 74 .setGroupSummary(groupSummary) 75 .setSortKey(sortKey); 76 mExtras = new Bundle(); 77 if (extras != null) { 78 mExtras.putAll(extras); 79 } 80 if (people != null && !people.isEmpty()) { 81 mExtras.putStringArray(Notification.EXTRA_PEOPLE, 82 people.toArray(new String[people.size()])); 83 } 84 mContentView = contentView; 85 mBigContentView = bigContentView; 86 } 87 88 @Override 89 public void addAction(NotificationCompatBase.Action action) { 90 NotificationCompatApi20.addAction(b, action); 91 } 92 93 @Override 94 public Notification.Builder getBuilder() { 95 return b; 96 } 97 98 @Override 99 public Notification build() { 100 b.setExtras(mExtras); 101 Notification notification = b.build(); 102 if (mContentView != null) { 103 notification.contentView = mContentView; 104 } 105 if (mBigContentView != null) { 106 notification.bigContentView = mBigContentView; 107 } 108 return notification; 109 } 110 } 111 112 public static void addAction(Notification.Builder b, NotificationCompatBase.Action action) { 113 Notification.Action.Builder actionBuilder = new Notification.Action.Builder( 114 action.getIcon(), action.getTitle(), action.getActionIntent()); 115 if (action.getRemoteInputs() != null) { 116 for (RemoteInput remoteInput : RemoteInputCompatApi20.fromCompat( 117 action.getRemoteInputs())) { 118 actionBuilder.addRemoteInput(remoteInput); 119 } 120 } 121 Bundle actionExtras; 122 if (action.getExtras() != null) { 123 actionExtras = new Bundle(action.getExtras()); 124 } else { 125 actionExtras = new Bundle(); 126 } 127 actionExtras.putBoolean(NotificationCompatJellybean.EXTRA_ALLOW_GENERATED_REPLIES, 128 action.getAllowGeneratedReplies()); 129 actionBuilder.addExtras(actionExtras); 130 b.addAction(actionBuilder.build()); 131 } 132 133 public static NotificationCompatBase.Action getAction(Notification notif, 134 int actionIndex, NotificationCompatBase.Action.Factory actionFactory, 135 RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 136 return getActionCompatFromAction(notif.actions[actionIndex], actionFactory, remoteInputFactory); 137 } 138 139 private static NotificationCompatBase.Action getActionCompatFromAction( 140 Notification.Action action, NotificationCompatBase.Action.Factory actionFactory, 141 RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 142 RemoteInputCompatBase.RemoteInput[] remoteInputs = RemoteInputCompatApi20.toCompat( 143 action.getRemoteInputs(), remoteInputFactory); 144 boolean allowGeneratedReplies = action.getExtras().getBoolean( 145 NotificationCompatJellybean.EXTRA_ALLOW_GENERATED_REPLIES); 146 return actionFactory.build(action.icon, action.title, action.actionIntent, 147 action.getExtras(), remoteInputs, allowGeneratedReplies); 148 } 149 150 private static Notification.Action getActionFromActionCompat( 151 NotificationCompatBase.Action actionCompat) { 152 Notification.Action.Builder actionBuilder = new Notification.Action.Builder( 153 actionCompat.getIcon(), actionCompat.getTitle(), actionCompat.getActionIntent()) 154 .addExtras(actionCompat.getExtras()); 155 RemoteInputCompatBase.RemoteInput[] remoteInputCompats = actionCompat.getRemoteInputs(); 156 if (remoteInputCompats != null) { 157 RemoteInput[] remoteInputs = RemoteInputCompatApi20.fromCompat(remoteInputCompats); 158 for (RemoteInput remoteInput : remoteInputs) { 159 actionBuilder.addRemoteInput(remoteInput); 160 } 161 } 162 return actionBuilder.build(); 163 } 164 165 /** 166 * Get a list of notification compat actions by parsing actions stored within a list of 167 * parcelables using the {@link Bundle#getParcelableArrayList} function in the same 168 * manner that framework code would do so. In API20, Using Action parcelable directly 169 * is correct. 170 */ 171 public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList( 172 ArrayList<Parcelable> parcelables, 173 NotificationCompatBase.Action.Factory actionFactory, 174 RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 175 if (parcelables == null) { 176 return null; 177 } 178 NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size()); 179 for (int i = 0; i < actions.length; i++) { 180 Notification.Action action = (Notification.Action) parcelables.get(i); 181 actions[i] = getActionCompatFromAction(action, actionFactory, remoteInputFactory); 182 } 183 return actions; 184 } 185 186 /** 187 * Get an array list of parcelables, suitable for {@link Bundle#putParcelableArrayList}, 188 * that matches what framework code would do to store an actions list in this way. In API20, 189 * action parcelables were directly placed as entries in the array list. 190 */ 191 public static ArrayList<Parcelable> getParcelableArrayListForActions( 192 NotificationCompatBase.Action[] actions) { 193 if (actions == null) { 194 return null; 195 } 196 ArrayList<Parcelable> parcelables = new ArrayList<Parcelable>(actions.length); 197 for (NotificationCompatBase.Action action : actions) { 198 parcelables.add(getActionFromActionCompat(action)); 199 } 200 return parcelables; 201 } 202 203 public static boolean getLocalOnly(Notification notif) { 204 return (notif.flags & Notification.FLAG_LOCAL_ONLY) != 0; 205 } 206 207 public static String getGroup(Notification notif) { 208 return notif.getGroup(); 209 } 210 211 public static boolean isGroupSummary(Notification notif) { 212 return (notif.flags & Notification.FLAG_GROUP_SUMMARY) != 0; 213 } 214 215 public static String getSortKey(Notification notif) { 216 return notif.getSortKey(); 217 } 218} 219