2013-03-21 20:32:11 +00:00
|
|
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
package org.mozilla.gecko;
|
|
|
|
|
2013-06-11 19:14:43 +00:00
|
|
|
import org.mozilla.gecko.gfx.BitmapUtils;
|
|
|
|
|
2013-07-18 23:35:34 +00:00
|
|
|
import android.app.Notification;
|
|
|
|
import android.app.NotificationManager;
|
2013-03-21 20:32:11 +00:00
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.net.Uri;
|
2013-07-18 23:35:34 +00:00
|
|
|
import android.util.Log;
|
2013-03-21 20:32:11 +00:00
|
|
|
|
2013-04-08 07:51:56 +00:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
2013-03-21 20:32:11 +00:00
|
|
|
public class NotificationHandler {
|
2013-07-18 23:35:34 +00:00
|
|
|
private final ConcurrentHashMap<Integer, Notification>
|
|
|
|
mNotifications = new ConcurrentHashMap<Integer, Notification>();
|
2013-03-21 20:32:11 +00:00
|
|
|
private final Context mContext;
|
2013-07-18 23:35:34 +00:00
|
|
|
private final NotificationManager mNotificationManager;
|
2013-03-21 20:32:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Notification associated with this service's foreground state.
|
|
|
|
*
|
|
|
|
* {@link android.app.Service#startForeground(int, android.app.Notification)}
|
|
|
|
* associates the foreground with exactly one notification from the service.
|
|
|
|
* To keep Fennec alive during downloads (and to make sure it can be killed
|
|
|
|
* once downloads are complete), we make sure that the foreground is always
|
|
|
|
* associated with an active progress notification if and only if at least
|
|
|
|
* one download is in progress.
|
|
|
|
*/
|
2013-07-18 23:35:34 +00:00
|
|
|
private Notification mForegroundNotification;
|
2013-10-14 20:38:57 +00:00
|
|
|
private int mForegroundNotificationId;
|
2013-03-21 20:32:11 +00:00
|
|
|
|
|
|
|
public NotificationHandler(Context context) {
|
|
|
|
mContext = context;
|
2013-07-18 23:35:34 +00:00
|
|
|
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a notification.
|
|
|
|
*
|
|
|
|
* @param notificationID the unique ID of the notification
|
|
|
|
* @param aImageUrl URL of the image to use
|
|
|
|
* @param aAlertTitle title of the notification
|
|
|
|
* @param aAlertText text of the notification
|
|
|
|
* @param contentIntent Intent used when the notification is clicked
|
|
|
|
* @param clearIntent Intent used when the notification is removed
|
|
|
|
*/
|
|
|
|
public void add(int notificationID, String aImageUrl, String aAlertTitle,
|
|
|
|
String aAlertText, PendingIntent contentIntent) {
|
|
|
|
// Remove the old notification with the same ID, if any
|
|
|
|
remove(notificationID);
|
|
|
|
|
|
|
|
Uri imageUri = Uri.parse(aImageUrl);
|
2013-06-11 19:14:43 +00:00
|
|
|
int icon = BitmapUtils.getResource(imageUri, R.drawable.ic_status_logo);
|
2013-03-21 20:32:11 +00:00
|
|
|
final AlertNotification notification = new AlertNotification(mContext, notificationID,
|
|
|
|
icon, aAlertTitle, aAlertText, System.currentTimeMillis(), imageUri);
|
|
|
|
|
|
|
|
notification.setLatestEventInfo(mContext, aAlertTitle, aAlertText, contentIntent);
|
|
|
|
|
2013-07-18 23:35:34 +00:00
|
|
|
mNotificationManager.notify(notificationID, notification);
|
|
|
|
mNotifications.put(notificationID, notification);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a notification.
|
|
|
|
*
|
|
|
|
* @param id the unique ID of the notification
|
|
|
|
* @param aNotification the Notification to add
|
|
|
|
*/
|
|
|
|
public void add(int id, Notification notification) {
|
|
|
|
mNotificationManager.notify(id, notification);
|
|
|
|
mNotifications.put(id, notification);
|
|
|
|
|
|
|
|
if (mForegroundNotification == null && isOngoing(notification)) {
|
|
|
|
setForegroundNotification(id, notification);
|
|
|
|
}
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates a notification.
|
|
|
|
*
|
|
|
|
* @param notificationID ID of existing notification
|
|
|
|
* @param aProgress progress of item being updated
|
|
|
|
* @param aProgressMax max progress of item being updated
|
|
|
|
* @param aAlertText text of the notification
|
|
|
|
*/
|
|
|
|
public void update(int notificationID, long aProgress, long aProgressMax, String aAlertText) {
|
2013-07-18 23:35:34 +00:00
|
|
|
final Notification notification = mNotifications.get(notificationID);
|
2013-03-21 20:32:11 +00:00
|
|
|
if (notification == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-18 23:35:34 +00:00
|
|
|
if (notification instanceof AlertNotification) {
|
|
|
|
AlertNotification alert = (AlertNotification)notification;
|
|
|
|
alert.updateProgress(aAlertText, aProgress, aProgressMax);
|
|
|
|
}
|
2013-03-21 20:32:11 +00:00
|
|
|
|
2013-07-18 23:35:34 +00:00
|
|
|
if (mForegroundNotification == null && isOngoing(notification)) {
|
|
|
|
setForegroundNotification(notificationID, notification);
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes a notification.
|
|
|
|
*
|
|
|
|
* @param notificationID ID of existing notification
|
|
|
|
*/
|
|
|
|
public void remove(int notificationID) {
|
2013-07-18 23:35:34 +00:00
|
|
|
final Notification notification = mNotifications.remove(notificationID);
|
2013-03-21 20:32:11 +00:00
|
|
|
if (notification != null) {
|
2013-07-18 23:35:34 +00:00
|
|
|
updateForegroundNotification(notificationID, notification);
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
2013-07-18 23:35:34 +00:00
|
|
|
mNotificationManager.cancel(notificationID);
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines whether the service is done.
|
|
|
|
*
|
|
|
|
* The service is considered finished when all notifications have been
|
|
|
|
* removed.
|
|
|
|
*
|
|
|
|
* @return whether all notifications have been removed
|
|
|
|
*/
|
|
|
|
public boolean isDone() {
|
2013-07-18 23:35:34 +00:00
|
|
|
return mNotifications.isEmpty();
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-07-18 23:35:34 +00:00
|
|
|
* Determines whether a notification should hold a foreground service to keep Gecko alive
|
2013-03-21 20:32:11 +00:00
|
|
|
*
|
2013-07-18 23:35:34 +00:00
|
|
|
* @param notificationID the id of the notification to check
|
|
|
|
* @return whether the notification is ongoing
|
2013-03-21 20:32:11 +00:00
|
|
|
*/
|
2013-07-18 23:35:34 +00:00
|
|
|
public boolean isOngoing(int notificationID) {
|
|
|
|
final Notification notification = mNotifications.get(notificationID);
|
|
|
|
return isOngoing(notification);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines whether a notification should hold a foreground service to keep Gecko alive
|
|
|
|
*
|
|
|
|
* @param notification the notification to check
|
|
|
|
* @return whether the notification is ongoing
|
|
|
|
*/
|
|
|
|
public boolean isOngoing(Notification notification) {
|
|
|
|
if (notification != null && (isProgressStyle(notification) || ((notification.flags & Notification.FLAG_ONGOING_EVENT) > 0))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to determines whether a notification is an AlertNotification that is showing progress
|
|
|
|
* This method will be deprecated when AlertNotifications are removed (bug 893289).
|
|
|
|
*
|
|
|
|
* @param notification the notification to check
|
|
|
|
* @return whether the notification is an AlertNotification showing progress.
|
|
|
|
*/
|
|
|
|
private boolean isProgressStyle(Notification notification) {
|
|
|
|
if (notification != null && notification instanceof AlertNotification) {
|
|
|
|
return ((AlertNotification)notification).isProgressStyle();
|
|
|
|
}
|
|
|
|
return false;
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
|
2013-07-18 23:35:34 +00:00
|
|
|
protected void setForegroundNotification(int id, Notification notification) {
|
2013-10-14 20:38:57 +00:00
|
|
|
mForegroundNotificationId = id;
|
2013-03-21 20:32:11 +00:00
|
|
|
mForegroundNotification = notification;
|
|
|
|
}
|
|
|
|
|
2013-10-14 20:38:57 +00:00
|
|
|
private void updateForegroundNotification(int oldId, Notification oldNotification) {
|
|
|
|
if (mForegroundNotificationId == oldId) {
|
2013-03-21 20:32:11 +00:00
|
|
|
// If we're removing the notification associated with the
|
|
|
|
// foreground, we need to pick another active notification to act
|
|
|
|
// as the foreground notification.
|
2013-07-18 23:35:34 +00:00
|
|
|
Notification foregroundNotification = null;
|
2013-10-14 20:38:57 +00:00
|
|
|
int foregroundId = 0;
|
|
|
|
for (final Integer id : mNotifications.keySet()) {
|
|
|
|
final Notification notification = mNotifications.get(id);
|
2013-07-18 23:35:34 +00:00
|
|
|
if (isOngoing(notification)) {
|
2013-03-21 20:32:11 +00:00
|
|
|
foregroundNotification = notification;
|
2013-10-14 20:38:57 +00:00
|
|
|
foregroundId = id;
|
2013-03-21 20:32:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-10-14 20:38:57 +00:00
|
|
|
setForegroundNotification(foregroundId, foregroundNotification);
|
2013-03-21 20:32:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|