Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 package org.mozilla.gecko;
8 import org.mozilla.gecko.gfx.BitmapUtils;
10 import android.app.Notification;
11 import android.app.NotificationManager;
12 import android.app.PendingIntent;
13 import android.content.Context;
14 import android.net.Uri;
15 import android.util.Log;
17 import java.util.concurrent.ConcurrentHashMap;
19 public class NotificationHandler {
20 private final ConcurrentHashMap<Integer, Notification>
21 mNotifications = new ConcurrentHashMap<Integer, Notification>();
22 private final Context mContext;
23 private final NotificationManager mNotificationManager;
25 /**
26 * Notification associated with this service's foreground state.
27 *
28 * {@link android.app.Service#startForeground(int, android.app.Notification)}
29 * associates the foreground with exactly one notification from the service.
30 * To keep Fennec alive during downloads (and to make sure it can be killed
31 * once downloads are complete), we make sure that the foreground is always
32 * associated with an active progress notification if and only if at least
33 * one download is in progress.
34 */
35 private Notification mForegroundNotification;
36 private int mForegroundNotificationId;
38 public NotificationHandler(Context context) {
39 mContext = context;
40 mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
41 }
43 /**
44 * Adds a notification.
45 *
46 * @param notificationID the unique ID of the notification
47 * @param aImageUrl URL of the image to use
48 * @param aAlertTitle title of the notification
49 * @param aAlertText text of the notification
50 * @param contentIntent Intent used when the notification is clicked
51 * @param clearIntent Intent used when the notification is removed
52 */
53 public void add(int notificationID, String aImageUrl, String aAlertTitle,
54 String aAlertText, PendingIntent contentIntent) {
55 // Remove the old notification with the same ID, if any
56 remove(notificationID);
58 Uri imageUri = Uri.parse(aImageUrl);
59 int icon = BitmapUtils.getResource(imageUri, R.drawable.ic_status_logo);
60 final AlertNotification notification = new AlertNotification(mContext, notificationID,
61 icon, aAlertTitle, aAlertText, System.currentTimeMillis(), imageUri);
63 notification.setLatestEventInfo(mContext, aAlertTitle, aAlertText, contentIntent);
65 mNotificationManager.notify(notificationID, notification);
66 mNotifications.put(notificationID, notification);
67 }
69 /**
70 * Adds a notification.
71 *
72 * @param id the unique ID of the notification
73 * @param aNotification the Notification to add
74 */
75 public void add(int id, Notification notification) {
76 mNotificationManager.notify(id, notification);
77 mNotifications.put(id, notification);
79 if (mForegroundNotification == null && isOngoing(notification)) {
80 setForegroundNotification(id, notification);
81 }
82 }
84 /**
85 * Updates a notification.
86 *
87 * @param notificationID ID of existing notification
88 * @param aProgress progress of item being updated
89 * @param aProgressMax max progress of item being updated
90 * @param aAlertText text of the notification
91 */
92 public void update(int notificationID, long aProgress, long aProgressMax, String aAlertText) {
93 final Notification notification = mNotifications.get(notificationID);
94 if (notification == null) {
95 return;
96 }
98 if (notification instanceof AlertNotification) {
99 AlertNotification alert = (AlertNotification)notification;
100 alert.updateProgress(aAlertText, aProgress, aProgressMax);
101 }
103 if (mForegroundNotification == null && isOngoing(notification)) {
104 setForegroundNotification(notificationID, notification);
105 }
106 }
108 /**
109 * Removes a notification.
110 *
111 * @param notificationID ID of existing notification
112 */
113 public void remove(int notificationID) {
114 final Notification notification = mNotifications.remove(notificationID);
115 if (notification != null) {
116 updateForegroundNotification(notificationID, notification);
117 }
118 mNotificationManager.cancel(notificationID);
119 }
121 /**
122 * Determines whether the service is done.
123 *
124 * The service is considered finished when all notifications have been
125 * removed.
126 *
127 * @return whether all notifications have been removed
128 */
129 public boolean isDone() {
130 return mNotifications.isEmpty();
131 }
133 /**
134 * Determines whether a notification should hold a foreground service to keep Gecko alive
135 *
136 * @param notificationID the id of the notification to check
137 * @return whether the notification is ongoing
138 */
139 public boolean isOngoing(int notificationID) {
140 final Notification notification = mNotifications.get(notificationID);
141 return isOngoing(notification);
142 }
144 /**
145 * Determines whether a notification should hold a foreground service to keep Gecko alive
146 *
147 * @param notification the notification to check
148 * @return whether the notification is ongoing
149 */
150 public boolean isOngoing(Notification notification) {
151 if (notification != null && (isProgressStyle(notification) || ((notification.flags & Notification.FLAG_ONGOING_EVENT) > 0))) {
152 return true;
153 }
154 return false;
155 }
157 /**
158 * Helper method to determines whether a notification is an AlertNotification that is showing progress
159 * This method will be deprecated when AlertNotifications are removed (bug 893289).
160 *
161 * @param notification the notification to check
162 * @return whether the notification is an AlertNotification showing progress.
163 */
164 private boolean isProgressStyle(Notification notification) {
165 if (notification != null && notification instanceof AlertNotification) {
166 return ((AlertNotification)notification).isProgressStyle();
167 }
168 return false;
169 }
171 protected void setForegroundNotification(int id, Notification notification) {
172 mForegroundNotificationId = id;
173 mForegroundNotification = notification;
174 }
176 private void updateForegroundNotification(int oldId, Notification oldNotification) {
177 if (mForegroundNotificationId == oldId) {
178 // If we're removing the notification associated with the
179 // foreground, we need to pick another active notification to act
180 // as the foreground notification.
181 Notification foregroundNotification = null;
182 int foregroundId = 0;
183 for (final Integer id : mNotifications.keySet()) {
184 final Notification notification = mNotifications.get(id);
185 if (isOngoing(notification)) {
186 foregroundNotification = notification;
187 foregroundId = id;
188 break;
189 }
190 }
191 setForegroundNotification(foregroundId, foregroundNotification);
192 }
193 }
194 }