1b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen/* 2b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * Copyright (C) 2014 The Android Open Source Project 3b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * 4b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * Licensed under the Apache License, Version 2.0 (the "License"); 5b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * you may not use this file except in compliance with the License. 6b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * You may obtain a copy of the License at 7b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * 8b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * http://www.apache.org/licenses/LICENSE-2.0 9b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * 10b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * Unless required by applicable law or agreed to in writing, software 11b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * distributed under the License is distributed on an "AS IS" BASIS, 12b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * See the License for the specific language governing permissions and 14b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen * limitations under the License. 15b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen */ 16b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 17b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenpackage android.support.v4.app; 18b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 19b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenimport android.app.Notification; 20b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenimport android.app.PendingIntent; 21ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazenimport android.app.RemoteInput; 22b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenimport android.content.Context; 23b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenimport android.graphics.Bitmap; 24b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenimport android.os.Bundle; 252bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazenimport android.os.Parcelable; 26b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenimport android.widget.RemoteViews; 27b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 28334514fd61bd192cee3475b3ba44adb4f54a1f89Chris Wrenimport java.util.ArrayList; 29334514fd61bd192cee3475b3ba44adb4f54a1f89Chris Wren 30b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazenclass NotificationCompatApi20 { 31b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen public static class Builder implements NotificationBuilderWithBuilderAccessor, 32b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen NotificationBuilderWithActions { 33b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen private Notification.Builder b; 3443c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen private Bundle mExtras; 35b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 36b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen public Builder(Context context, Notification n, 37b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, 38b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen RemoteViews tickerView, int number, 39b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, 4048d8878e34b0d9983166418378125b63faac9aabGriff Hazen int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, 41ab78e9b2a147c8de7b5cf231b97aad9d8c4f106cGriff Hazen boolean useChronometer, int priority, CharSequence subText, boolean localOnly, 4243c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen ArrayList<String> people, Bundle extras, String groupKey, boolean groupSummary, 43cd05a19c0775e69e93e4c93b0a48ab044b531d7aGriff Hazen String sortKey) { 44b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen b = new Notification.Builder(context) 45b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setWhen(n.when) 4648d8878e34b0d9983166418378125b63faac9aabGriff Hazen .setShowWhen(showWhen) 47b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setSmallIcon(n.icon, n.iconLevel) 48b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setContent(n.contentView) 49b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setTicker(n.tickerText, tickerView) 50b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setSound(n.sound, n.audioStreamType) 51b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setVibrate(n.vibrate) 52b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) 53b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) 54b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) 55b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) 56b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setDefaults(n.defaults) 57b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setContentTitle(contentTitle) 58b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setContentText(contentText) 59b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setSubText(subText) 60b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setContentInfo(contentInfo) 61b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setContentIntent(contentIntent) 62b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setDeleteIntent(n.deleteIntent) 63b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setFullScreenIntent(fullScreenIntent, 64b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) 65b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setLargeIcon(largeIcon) 66b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setNumber(number) 67b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setUsesChronometer(useChronometer) 68b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen .setPriority(priority) 6943c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen .setProgress(progressMax, progress, progressIndeterminate) 70ab78e9b2a147c8de7b5cf231b97aad9d8c4f106cGriff Hazen .setLocalOnly(localOnly) 71ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen .setGroup(groupKey) 72ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen .setGroupSummary(groupSummary) 73ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen .setSortKey(sortKey); 7443c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen mExtras = new Bundle(); 7543c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen if (extras != null) { 7643c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen mExtras.putAll(extras); 7743c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen } 7843c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen if (people != null && !people.isEmpty()) { 7943c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen mExtras.putStringArray(Notification.EXTRA_PEOPLE, 8043c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen people.toArray(new String[people.size()])); 81334514fd61bd192cee3475b3ba44adb4f54a1f89Chris Wren } 82b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen } 83b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 84b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen @Override 85ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen public void addAction(NotificationCompatBase.Action action) { 8643c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen NotificationCompatApi20.addAction(b, action); 87b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen } 88b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 89b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen @Override 90b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen public Notification.Builder getBuilder() { 91b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen return b; 92b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen } 93b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 94b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen public Notification build() { 9543c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen b.setExtras(mExtras); 96b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen return b.build(); 97b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen } 98b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen } 99b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen 10043c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen public static void addAction(Notification.Builder b, NotificationCompatBase.Action action) { 10143c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen Notification.Action.Builder actionBuilder = new Notification.Action.Builder( 10243c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen action.getIcon(), action.getTitle(), action.getActionIntent()); 10343c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen if (action.getRemoteInputs() != null) { 10443c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen for (RemoteInput remoteInput : RemoteInputCompatApi20.fromCompat( 10543c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen action.getRemoteInputs())) { 10643c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen actionBuilder.addRemoteInput(remoteInput); 10743c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen } 10843c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen } 10943c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen if (action.getExtras() != null) { 11043c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen actionBuilder.addExtras(action.getExtras()); 11143c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen } 11243c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen b.addAction(actionBuilder.build()); 11343c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen } 11443c5718722bab1f836b7c94f2ec0bc19e653037cGriff Hazen 115ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen public static NotificationCompatBase.Action getAction(Notification notif, 1162bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen int actionIndex, NotificationCompatBase.Action.Factory actionFactory, 1172bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 1182bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return getActionCompatFromAction(notif.actions[actionIndex], actionFactory, remoteInputFactory); 1192bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1202bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen 1212bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen private static NotificationCompatBase.Action getActionCompatFromAction( 1222bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen Notification.Action action, NotificationCompatBase.Action.Factory actionFactory, 123ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 124ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen RemoteInputCompatBase.RemoteInput[] remoteInputs = RemoteInputCompatApi20.toCompat( 125ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen action.getRemoteInputs(), remoteInputFactory); 1262bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return actionFactory.build(action.icon, action.title, action.actionIntent, 127ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen action.getExtras(), remoteInputs); 128300ad7c234a0ccfc41ae7fdbdcdd57faece2a8e0Griff Hazen } 129300ad7c234a0ccfc41ae7fdbdcdd57faece2a8e0Griff Hazen 1302bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen private static Notification.Action getActionFromActionCompat( 1312bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen NotificationCompatBase.Action actionCompat) { 1322bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen Notification.Action.Builder actionBuilder = new Notification.Action.Builder( 1332bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen actionCompat.getIcon(), actionCompat.getTitle(), actionCompat.getActionIntent()) 1342bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen .addExtras(actionCompat.getExtras()); 1352bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen RemoteInputCompatBase.RemoteInput[] remoteInputCompats = actionCompat.getRemoteInputs(); 1362bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen if (remoteInputCompats != null) { 1372bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen RemoteInput[] remoteInputs = RemoteInputCompatApi20.fromCompat(remoteInputCompats); 1382bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen for (RemoteInput remoteInput : remoteInputs) { 1392bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen actionBuilder.addRemoteInput(remoteInput); 1402bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1412bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1422bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return actionBuilder.build(); 1432bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1442bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen 1452bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen /** 1462bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * Get a list of notification compat actions by parsing actions stored within a list of 1472bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * parcelables using the {@link Bundle#getParcelableArrayList} function in the same 1482bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * manner that framework code would do so. In API20, Using Action parcelable directly 1492bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * is correct. 1502bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen */ 1512bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList( 1522bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen ArrayList<Parcelable> parcelables, 1532bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen NotificationCompatBase.Action.Factory actionFactory, 1542bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { 1552bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen if (parcelables == null) { 1562bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return null; 1572bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1582bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size()); 1592bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen for (int i = 0; i < actions.length; i++) { 1602bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen Notification.Action action = (Notification.Action) parcelables.get(i); 1612bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen actions[i] = getActionCompatFromAction(action, actionFactory, remoteInputFactory); 1622bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1632bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return actions; 1642bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1652bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen 1662bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen /** 1672bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * Get an array list of parcelables, suitable for {@link Bundle#putParcelableArrayList}, 1682bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * that matches what framework code would do to store an actions list in this way. In API20, 1692bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen * action parcelables were directly placed as entries in the array list. 1702bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen */ 1712bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen public static ArrayList<Parcelable> getParcelableArrayListForActions( 1722bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen NotificationCompatBase.Action[] actions) { 1732bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen if (actions == null) { 1742bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return null; 1752bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1762bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen ArrayList<Parcelable> parcelables = new ArrayList<Parcelable>(actions.length); 1772bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen for (NotificationCompatBase.Action action : actions) { 1782bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen parcelables.add(getActionFromActionCompat(action)); 1792bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1802bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen return parcelables; 1812bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen } 1822bb98d48fdaf79a2bbd9d247da81a2bb9834dfc7Griff Hazen 183b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen public static boolean getLocalOnly(Notification notif) { 184b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen return (notif.flags & Notification.FLAG_LOCAL_ONLY) != 0; 185b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen } 186ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen 187ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen public static String getGroup(Notification notif) { 188ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen return notif.getGroup(); 189ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen } 190ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen 191ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen public static boolean isGroupSummary(Notification notif) { 192ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen return (notif.flags & Notification.FLAG_GROUP_SUMMARY) != 0; 193ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen } 194ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen 195ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen public static String getSortKey(Notification notif) { 196ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen return notif.getSortKey(); 197ce16e4276c2f61109a23b3f6707cfcd87b07c735Griff Hazen } 198b56de0d1a113c71a2808303009ab4d9708ed6e84Griff Hazen} 199