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
59        public Builder(Context context, Notification n,
60                CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
61                RemoteViews tickerView, int number,
62                PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon,
63                int progressMax, int progress, boolean progressIndeterminate, boolean showWhen,
64                boolean useChronometer, int priority, CharSequence subText, boolean localOnly,
65                String category, ArrayList<String> people, Bundle extras, int color,
66                int visibility, Notification publicVersion, String groupKey, boolean groupSummary,
67                String sortKey) {
68            b = new Notification.Builder(context)
69                    .setWhen(n.when)
70                    .setShowWhen(showWhen)
71                    .setSmallIcon(n.icon, n.iconLevel)
72                    .setContent(n.contentView)
73                    .setTicker(n.tickerText, tickerView)
74                    .setSound(n.sound, n.audioStreamType)
75                    .setVibrate(n.vibrate)
76                    .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
77                    .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
78                    .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
79                    .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
80                    .setDefaults(n.defaults)
81                    .setContentTitle(contentTitle)
82                    .setContentText(contentText)
83                    .setSubText(subText)
84                    .setContentInfo(contentInfo)
85                    .setContentIntent(contentIntent)
86                    .setDeleteIntent(n.deleteIntent)
87                    .setFullScreenIntent(fullScreenIntent,
88                            (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
89                    .setLargeIcon(largeIcon)
90                    .setNumber(number)
91                    .setUsesChronometer(useChronometer)
92                    .setPriority(priority)
93                    .setProgress(progressMax, progress, progressIndeterminate)
94                    .setLocalOnly(localOnly)
95                    .setExtras(extras)
96                    .setGroup(groupKey)
97                    .setGroupSummary(groupSummary)
98                    .setSortKey(sortKey)
99                    .setCategory(category)
100                    .setColor(color)
101                    .setVisibility(visibility)
102                    .setPublicVersion(publicVersion);
103            for (String person: people) {
104                b.addPerson(person);
105            }
106        }
107
108        @Override
109        public void addAction(NotificationCompatBase.Action action) {
110            NotificationCompatApi20.addAction(b, action);
111        }
112
113        @Override
114        public Notification.Builder getBuilder() {
115            return b;
116        }
117
118        public Notification build() {
119            return b.build();
120        }
121    }
122
123    public static String getCategory(Notification notif) {
124        return notif.category;
125    }
126
127    static Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) {
128        if (uc == null) {
129            return null;
130        }
131        Bundle b = new Bundle();
132        String author = null;
133        if (uc.getParticipants() != null && uc.getParticipants().length > 1) {
134            author = uc.getParticipants()[0];
135        }
136        Parcelable[] messages = new Parcelable[uc.getMessages().length];
137        for (int i = 0; i < messages.length; i++) {
138            Bundle m = new Bundle();
139            m.putString(KEY_TEXT, uc.getMessages()[i]);
140            m.putString(KEY_AUTHOR, author);
141            messages[i] = m;
142        }
143        b.putParcelableArray(KEY_MESSAGES, messages);
144        RemoteInputCompatBase.RemoteInput remoteInput = uc.getRemoteInput();
145        if (remoteInput != null) {
146            b.putParcelable(KEY_REMOTE_INPUT, fromCompatRemoteInput(remoteInput));
147        }
148        b.putParcelable(KEY_ON_REPLY, uc.getReplyPendingIntent());
149        b.putParcelable(KEY_ON_READ, uc.getReadPendingIntent());
150        b.putStringArray(KEY_PARTICIPANTS, uc.getParticipants());
151        b.putLong(KEY_TIMESTAMP, uc.getLatestTimestamp());
152        return b;
153    }
154
155    static NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle(
156            Bundle b, NotificationCompatBase.UnreadConversation.Factory factory,
157            RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
158        if (b == null) {
159            return null;
160        }
161        Parcelable[] parcelableMessages = b.getParcelableArray(KEY_MESSAGES);
162        String[] messages = null;
163        if (parcelableMessages != null) {
164            String[] tmp = new String[parcelableMessages.length];
165            boolean success = true;
166            for (int i = 0; i < tmp.length; i++) {
167                if (!(parcelableMessages[i] instanceof Bundle)) {
168                    success = false;
169                    break;
170                }
171                tmp[i] = ((Bundle) parcelableMessages[i]).getString(KEY_TEXT);
172                if (tmp[i] == null) {
173                    success = false;
174                    break;
175                }
176            }
177            if (success) {
178                messages = tmp;
179            } else {
180                return null;
181            }
182        }
183
184        PendingIntent onRead = b.getParcelable(KEY_ON_READ);
185        PendingIntent onReply = b.getParcelable(KEY_ON_REPLY);
186
187        android.app.RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT);
188
189        String[] participants = b.getStringArray(KEY_PARTICIPANTS);
190        if (participants == null || participants.length != 1) {
191            return null;
192        }
193
194
195        return factory.build(
196                messages,
197                remoteInput != null ? toCompatRemoteInput(remoteInput, remoteInputFactory) : null,
198                onReply,
199                onRead,
200                participants, b.getLong(KEY_TIMESTAMP));
201    }
202
203    private static android.app.RemoteInput fromCompatRemoteInput(
204            RemoteInputCompatBase.RemoteInput src) {
205        return new android.app.RemoteInput.Builder(src.getResultKey())
206                .setLabel(src.getLabel())
207                .setChoices(src.getChoices())
208                .setAllowFreeFormInput(src.getAllowFreeFormInput())
209                .addExtras(src.getExtras())
210                .build();
211    }
212
213    private static RemoteInputCompatBase.RemoteInput toCompatRemoteInput(
214            android.app.RemoteInput remoteInput,
215            RemoteInputCompatBase.RemoteInput.Factory factory) {
216        return factory.build(remoteInput.getResultKey(),
217                remoteInput.getLabel(),
218                remoteInput.getChoices(),
219                remoteInput.getAllowFreeFormInput(),
220                remoteInput.getExtras());
221    }
222}
223