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