mobile/android/base/NotificationHandler.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/NotificationHandler.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,194 @@
     1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +package org.mozilla.gecko;
    1.10 +
    1.11 +import org.mozilla.gecko.gfx.BitmapUtils;
    1.12 +
    1.13 +import android.app.Notification;
    1.14 +import android.app.NotificationManager;
    1.15 +import android.app.PendingIntent;
    1.16 +import android.content.Context;
    1.17 +import android.net.Uri;
    1.18 +import android.util.Log;
    1.19 +
    1.20 +import java.util.concurrent.ConcurrentHashMap;
    1.21 +
    1.22 +public class NotificationHandler {
    1.23 +    private final ConcurrentHashMap<Integer, Notification>
    1.24 +            mNotifications = new ConcurrentHashMap<Integer, Notification>();
    1.25 +    private final Context mContext;
    1.26 +    private final NotificationManager mNotificationManager;
    1.27 +
    1.28 +    /**
    1.29 +     * Notification associated with this service's foreground state.
    1.30 +     *
    1.31 +     * {@link android.app.Service#startForeground(int, android.app.Notification)}
    1.32 +     * associates the foreground with exactly one notification from the service.
    1.33 +     * To keep Fennec alive during downloads (and to make sure it can be killed
    1.34 +     * once downloads are complete), we make sure that the foreground is always
    1.35 +     * associated with an active progress notification if and only if at least
    1.36 +     * one download is in progress.
    1.37 +     */
    1.38 +    private Notification mForegroundNotification;
    1.39 +    private int mForegroundNotificationId;
    1.40 +
    1.41 +    public NotificationHandler(Context context) {
    1.42 +        mContext = context;
    1.43 +        mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    1.44 +    }
    1.45 +
    1.46 +    /**
    1.47 +     * Adds a notification.
    1.48 +     *
    1.49 +     * @param notificationID the unique ID of the notification
    1.50 +     * @param aImageUrl      URL of the image to use
    1.51 +     * @param aAlertTitle    title of the notification
    1.52 +     * @param aAlertText     text of the notification
    1.53 +     * @param contentIntent  Intent used when the notification is clicked
    1.54 +     * @param clearIntent    Intent used when the notification is removed
    1.55 +     */
    1.56 +    public void add(int notificationID, String aImageUrl, String aAlertTitle,
    1.57 +                    String aAlertText, PendingIntent contentIntent) {
    1.58 +        // Remove the old notification with the same ID, if any
    1.59 +        remove(notificationID);
    1.60 +
    1.61 +        Uri imageUri = Uri.parse(aImageUrl);
    1.62 +        int icon = BitmapUtils.getResource(imageUri, R.drawable.ic_status_logo);
    1.63 +        final AlertNotification notification = new AlertNotification(mContext, notificationID,
    1.64 +                icon, aAlertTitle, aAlertText, System.currentTimeMillis(), imageUri);
    1.65 +
    1.66 +        notification.setLatestEventInfo(mContext, aAlertTitle, aAlertText, contentIntent);
    1.67 +
    1.68 +        mNotificationManager.notify(notificationID, notification);
    1.69 +        mNotifications.put(notificationID, notification);
    1.70 +    }
    1.71 +
    1.72 +    /**
    1.73 +     * Adds a notification.
    1.74 +     *
    1.75 +     * @param id             the unique ID of the notification
    1.76 +     * @param aNotification  the Notification to add
    1.77 +     */
    1.78 +    public void add(int id, Notification notification) {
    1.79 +        mNotificationManager.notify(id, notification);
    1.80 +        mNotifications.put(id, notification);
    1.81 +
    1.82 +        if (mForegroundNotification == null && isOngoing(notification)) {
    1.83 +            setForegroundNotification(id, notification);
    1.84 +        }
    1.85 +    }
    1.86 +
    1.87 +    /**
    1.88 +     * Updates a notification.
    1.89 +     *
    1.90 +     * @param notificationID ID of existing notification
    1.91 +     * @param aProgress      progress of item being updated
    1.92 +     * @param aProgressMax   max progress of item being updated
    1.93 +     * @param aAlertText     text of the notification
    1.94 +     */
    1.95 +    public void update(int notificationID, long aProgress, long aProgressMax, String aAlertText) {
    1.96 +        final Notification notification = mNotifications.get(notificationID);
    1.97 +        if (notification == null) {
    1.98 +            return;
    1.99 +        }
   1.100 +
   1.101 +        if (notification instanceof AlertNotification) {
   1.102 +            AlertNotification alert = (AlertNotification)notification;
   1.103 +            alert.updateProgress(aAlertText, aProgress, aProgressMax);
   1.104 +        }
   1.105 +
   1.106 +        if (mForegroundNotification == null && isOngoing(notification)) {
   1.107 +            setForegroundNotification(notificationID, notification);
   1.108 +        }
   1.109 +    }
   1.110 +
   1.111 +    /**
   1.112 +     * Removes a notification.
   1.113 +     *
   1.114 +     * @param notificationID ID of existing notification
   1.115 +     */
   1.116 +    public void remove(int notificationID) {
   1.117 +        final Notification notification = mNotifications.remove(notificationID);
   1.118 +        if (notification != null) {
   1.119 +            updateForegroundNotification(notificationID, notification);
   1.120 +        }
   1.121 +        mNotificationManager.cancel(notificationID);
   1.122 +    }
   1.123 +
   1.124 +    /**
   1.125 +     * Determines whether the service is done.
   1.126 +     *
   1.127 +     * The service is considered finished when all notifications have been
   1.128 +     * removed.
   1.129 +     *
   1.130 +     * @return whether all notifications have been removed
   1.131 +     */
   1.132 +    public boolean isDone() {
   1.133 +        return mNotifications.isEmpty();
   1.134 +    }
   1.135 +
   1.136 +    /**
   1.137 +     * Determines whether a notification should hold a foreground service to keep Gecko alive
   1.138 +     *
   1.139 +     * @param notificationID the id of the notification to check
   1.140 +     * @return               whether the notification is ongoing
   1.141 +     */
   1.142 +    public boolean isOngoing(int notificationID) {
   1.143 +        final Notification notification = mNotifications.get(notificationID);
   1.144 +        return isOngoing(notification);
   1.145 +    }
   1.146 +
   1.147 +    /**
   1.148 +     * Determines whether a notification should hold a foreground service to keep Gecko alive
   1.149 +     *
   1.150 +     * @param notification   the notification to check
   1.151 +     * @return               whether the notification is ongoing
   1.152 +     */
   1.153 +    public boolean isOngoing(Notification notification) {
   1.154 +        if (notification != null && (isProgressStyle(notification) || ((notification.flags & Notification.FLAG_ONGOING_EVENT) > 0))) {
   1.155 +            return true;
   1.156 +        }
   1.157 +        return false;
   1.158 +    }
   1.159 +
   1.160 +    /**
   1.161 +     * Helper method to determines whether a notification is an AlertNotification that is showing progress
   1.162 +     * This method will be deprecated when AlertNotifications are removed (bug 893289). 
   1.163 +     *
   1.164 +     * @param notification   the notification to check
   1.165 +     * @return               whether the notification is an AlertNotification showing progress.
   1.166 +     */
   1.167 +    private boolean isProgressStyle(Notification notification) {
   1.168 +        if (notification != null && notification instanceof AlertNotification) {
   1.169 +            return ((AlertNotification)notification).isProgressStyle();
   1.170 +        }
   1.171 +        return false;
   1.172 +    }
   1.173 +
   1.174 +    protected void setForegroundNotification(int id, Notification notification) {
   1.175 +        mForegroundNotificationId = id;
   1.176 +        mForegroundNotification = notification;
   1.177 +    }
   1.178 +
   1.179 +    private void updateForegroundNotification(int oldId, Notification oldNotification) {
   1.180 +        if (mForegroundNotificationId == oldId) {
   1.181 +            // If we're removing the notification associated with the
   1.182 +            // foreground, we need to pick another active notification to act
   1.183 +            // as the foreground notification.
   1.184 +            Notification foregroundNotification = null;
   1.185 +            int foregroundId = 0;
   1.186 +            for (final Integer id : mNotifications.keySet()) {
   1.187 +                final Notification notification = mNotifications.get(id);
   1.188 +                if (isOngoing(notification)) {
   1.189 +                    foregroundNotification = notification;
   1.190 +                    foregroundId = id;
   1.191 +                    break;
   1.192 +                }
   1.193 +            }
   1.194 +            setForegroundNotification(foregroundId, foregroundNotification);
   1.195 +        }
   1.196 +    }
   1.197 +}

mercurial