add a optional String to the key of notifications to allow users

to scope them
This commit is contained in:
Fred Quintana
2009-09-25 14:23:13 -07:00
parent ed7f0955b7
commit 6ecaff1583
6 changed files with 122 additions and 41 deletions

View File

@ -23166,6 +23166,21 @@
<parameter name="id" type="int"> <parameter name="id" type="int">
</parameter> </parameter>
</method> </method>
<method name="cancel"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="tag" type="java.lang.String">
</parameter>
<parameter name="id" type="int">
</parameter>
</method>
<method name="cancelAll" <method name="cancelAll"
return="void" return="void"
abstract="false" abstract="false"
@ -23192,6 +23207,23 @@
<parameter name="notification" type="android.app.Notification"> <parameter name="notification" type="android.app.Notification">
</parameter> </parameter>
</method> </method>
<method name="notify"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="tag" type="java.lang.String">
</parameter>
<parameter name="id" type="int">
</parameter>
<parameter name="notification" type="android.app.Notification">
</parameter>
</method>
</class> </class>
<class name="PendingIntent" <class name="PendingIntent"
extends="java.lang.Object" extends="java.lang.Object"

View File

@ -24,11 +24,15 @@ import android.content.Intent;
/** {@hide} */ /** {@hide} */
interface INotificationManager interface INotificationManager
{ {
/** @deprecated use {@link #enqueueNotificationWithTag} instead */
void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived); void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived);
/** @deprecated use {@link #cancelNotificationWithTag} instead */
void cancelNotification(String pkg, int id); void cancelNotification(String pkg, int id);
void cancelAllNotifications(String pkg); void cancelAllNotifications(String pkg);
void enqueueToast(String pkg, ITransientNotification callback, int duration); void enqueueToast(String pkg, ITransientNotification callback, int duration);
void cancelToast(String pkg, ITransientNotification callback); void cancelToast(String pkg, ITransientNotification callback);
void enqueueNotificationWithTag(String pkg, String tag, int id, in Notification notification, inout int[] idReceived);
void cancelNotificationWithTag(String pkg, String tag, int id);
} }

View File

@ -86,13 +86,28 @@ public class NotificationManager
* notify the user, other than the view you're providing. Must not be null. * notify the user, other than the view you're providing. Must not be null.
*/ */
public void notify(int id, Notification notification) public void notify(int id, Notification notification)
{
notify(null, id, notification);
}
/**
* Persistent notification on the status bar,
*
* @param tag An string identifier for this notification unique within your
* application.
* @param notification A {@link Notification} object describing how to
* notify the user, other than the view you're providing. Must not be null.
* @return the id of the notification that is associated with the string identifier that
* can be used to cancel the notification
*/
public void notify(String tag, int id, Notification notification)
{ {
int[] idOut = new int[1]; int[] idOut = new int[1];
INotificationManager service = getService(); INotificationManager service = getService();
String pkg = mContext.getPackageName(); String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
try { try {
service.enqueueNotification(pkg, id, notification, idOut); service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);
if (id != idOut[0]) { if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]); Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
} }
@ -106,12 +121,22 @@ public class NotificationManager
* bar. * bar.
*/ */
public void cancel(int id) public void cancel(int id)
{
cancel(null, id);
}
/**
* Cancel a previously shown notification. If it's transient, the view
* will be hidden. If it's persistent, it will be removed from the status
* bar.
*/
public void cancel(String tag, int id)
{ {
INotificationManager service = getService(); INotificationManager service = getService();
String pkg = mContext.getPackageName(); String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")"); if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
try { try {
service.cancelNotification(pkg, id); service.cancelNotificationWithTag(pkg, tag, id);
} catch (RemoteException e) { } catch (RemoteException e) {
} }
} }

View File

@ -30,7 +30,6 @@ import android.app.PendingIntent;
import android.app.StatusBarManager; import android.app.StatusBarManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentQueryMap;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -103,7 +102,8 @@ class NotificationManagerService extends INotificationManager.Stub
private boolean mAdbNotificationShown = false; private boolean mAdbNotificationShown = false;
private Notification mAdbNotification; private Notification mAdbNotification;
private ArrayList<NotificationRecord> mNotificationList; private final ArrayList<NotificationRecord> mNotificationList =
new ArrayList<NotificationRecord>();
private ArrayList<ToastRecord> mToastQueue; private ArrayList<ToastRecord> mToastQueue;
@ -152,20 +152,22 @@ class NotificationManagerService extends INotificationManager.Stub
private static final class NotificationRecord private static final class NotificationRecord
{ {
String pkg; final String pkg;
int id; final String tag;
final int id;
ITransientNotification callback; ITransientNotification callback;
int duration; int duration;
Notification notification; final Notification notification;
IBinder statusBarKey; IBinder statusBarKey;
NotificationRecord(String pkg, int id, Notification notification) NotificationRecord(String pkg, String tag, int id, Notification notification)
{ {
this.pkg = pkg; this.pkg = pkg;
this.tag = tag;
this.id = id; this.id = id;
this.notification = notification; this.notification = notification;
} }
void dump(PrintWriter pw, String prefix, Context baseContext) { void dump(PrintWriter pw, String prefix, Context baseContext) {
pw.println(prefix + this); pw.println(prefix + this);
pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon) pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon)
@ -189,7 +191,8 @@ class NotificationManagerService extends INotificationManager.Stub
return "NotificationRecord{" return "NotificationRecord{"
+ Integer.toHexString(System.identityHashCode(this)) + Integer.toHexString(System.identityHashCode(this))
+ " pkg=" + pkg + " pkg=" + pkg
+ " id=" + Integer.toHexString(id) + "}"; + " id=" + Integer.toHexString(id)
+ " tag=" + tag + "}";
} }
} }
@ -258,8 +261,8 @@ class NotificationManagerService extends INotificationManager.Stub
cancelAll(); cancelAll();
} }
public void onNotificationClick(String pkg, int id) { public void onNotificationClick(String pkg, String tag, int id) {
cancelNotification(pkg, id, Notification.FLAG_AUTO_CANCEL, cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
Notification.FLAG_FOREGROUND_SERVICE); Notification.FLAG_FOREGROUND_SERVICE);
} }
@ -369,7 +372,6 @@ class NotificationManagerService extends INotificationManager.Stub
mSound = new AsyncPlayer(TAG); mSound = new AsyncPlayer(TAG);
mSound.setUsesWakeLock(context); mSound.setUsesWakeLock(context);
mToastQueue = new ArrayList<ToastRecord>(); mToastQueue = new ArrayList<ToastRecord>();
mNotificationList = new ArrayList<NotificationRecord>();
mHandler = new WorkerHandler(); mHandler = new WorkerHandler();
mStatusBarService = statusBar; mStatusBarService = statusBar;
statusBar.setNotificationCallbacks(mNotificationCallbacks); statusBar.setNotificationCallbacks(mNotificationCallbacks);
@ -582,6 +584,12 @@ class NotificationManagerService extends INotificationManager.Stub
// Notifications // Notifications
// ============================================================================ // ============================================================================
public void enqueueNotification(String pkg, int id, Notification notification, int[] idOut) public void enqueueNotification(String pkg, int id, Notification notification, int[] idOut)
{
enqueueNotificationWithTag(pkg, null /* tag */, id, notification, idOut);
}
public void enqueueNotificationWithTag(String pkg, String tag, int id,
Notification notification, int[] idOut)
{ {
checkIncomingCall(pkg); checkIncomingCall(pkg);
@ -608,10 +616,10 @@ class NotificationManagerService extends INotificationManager.Stub
} }
synchronized (mNotificationList) { synchronized (mNotificationList) {
NotificationRecord r = new NotificationRecord(pkg, id, notification); NotificationRecord r = new NotificationRecord(pkg, tag, id, notification);
NotificationRecord old = null; NotificationRecord old = null;
int index = indexOfNotificationLocked(pkg, id); int index = indexOfNotificationLocked(pkg, tag, id);
if (index < 0) { if (index < 0) {
mNotificationList.add(r); mNotificationList.add(r);
} else { } else {
@ -645,17 +653,18 @@ class NotificationManagerService extends INotificationManager.Stub
} }
NotificationData n = new NotificationData(); NotificationData n = new NotificationData();
n.id = id; n.pkg = pkg;
n.pkg = pkg; n.tag = tag;
n.when = notification.when; n.id = id;
n.tickerText = truncatedTicker; n.when = notification.when;
n.ongoingEvent = (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0; n.tickerText = truncatedTicker;
if (!n.ongoingEvent && (notification.flags & Notification.FLAG_NO_CLEAR) == 0) { n.ongoingEvent = (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
n.clearable = true; if (!n.ongoingEvent && (notification.flags & Notification.FLAG_NO_CLEAR) == 0) {
} n.clearable = true;
n.contentView = notification.contentView; }
n.contentIntent = notification.contentIntent; n.contentView = notification.contentView;
n.deleteIntent = notification.deleteIntent; n.contentIntent = notification.contentIntent;
n.deleteIntent = notification.deleteIntent;
if (old != null && old.statusBarKey != null) { if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey; r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity(); long identity = Binder.clearCallingIdentity();
@ -828,16 +837,14 @@ class NotificationManagerService extends INotificationManager.Stub
* Cancels a notification ONLY if it has all of the {@code mustHaveFlags} * Cancels a notification ONLY if it has all of the {@code mustHaveFlags}
* and none of the {@code mustNotHaveFlags}. * and none of the {@code mustNotHaveFlags}.
*/ */
private void cancelNotification(String pkg, int id, int mustHaveFlags, private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
int mustNotHaveFlags) { int mustNotHaveFlags) {
EventLog.writeEvent(EVENT_LOG_CANCEL, pkg, id, mustHaveFlags); EventLog.writeEvent(EVENT_LOG_CANCEL, pkg, id, mustHaveFlags);
synchronized (mNotificationList) { synchronized (mNotificationList) {
NotificationRecord r = null; int index = indexOfNotificationLocked(pkg, tag, id);
int index = indexOfNotificationLocked(pkg, id);
if (index >= 0) { if (index >= 0) {
r = mNotificationList.get(index); NotificationRecord r = mNotificationList.get(index);
if ((r.notification.flags & mustHaveFlags) != mustHaveFlags) { if ((r.notification.flags & mustHaveFlags) != mustHaveFlags) {
return; return;
@ -888,9 +895,13 @@ class NotificationManagerService extends INotificationManager.Stub
public void cancelNotification(String pkg, int id) { public void cancelNotification(String pkg, int id) {
cancelNotificationWithTag(pkg, null /* tag */, id);
}
public void cancelNotificationWithTag(String pkg, String tag, int id) {
checkIncomingCall(pkg); checkIncomingCall(pkg);
// Don't allow client applications to cancel foreground service notis. // Don't allow client applications to cancel foreground service notis.
cancelNotification(pkg, id, 0, cancelNotification(pkg, tag, id, 0,
Binder.getCallingUid() == Process.SYSTEM_UID Binder.getCallingUid() == Process.SYSTEM_UID
? 0 : Notification.FLAG_FOREGROUND_SERVICE); ? 0 : Notification.FLAG_FOREGROUND_SERVICE);
} }
@ -999,12 +1010,21 @@ class NotificationManagerService extends INotificationManager.Stub
} }
// lock on mNotificationList // lock on mNotificationList
private int indexOfNotificationLocked(String pkg, int id) private int indexOfNotificationLocked(String pkg, String tag, int id)
{ {
ArrayList<NotificationRecord> list = mNotificationList; ArrayList<NotificationRecord> list = mNotificationList;
final int len = list.size(); final int len = list.size();
for (int i=0; i<len; i++) { for (int i=0; i<len; i++) {
NotificationRecord r = list.get(i); NotificationRecord r = list.get(i);
if (tag == null) {
if (r.tag != null) {
continue;
}
} else {
if (!tag.equals(r.tag)) {
continue;
}
}
if (r.id == id && r.pkg.equals(pkg)) { if (r.id == id && r.pkg.equals(pkg)) {
return i; return i;
} }

View File

@ -5,6 +5,7 @@ import android.widget.RemoteViews;
public class NotificationData { public class NotificationData {
public String pkg; public String pkg;
public String tag;
public int id; public int id;
public CharSequence tickerText; public CharSequence tickerText;
@ -17,9 +18,6 @@ public class NotificationData {
public PendingIntent deleteIntent; public PendingIntent deleteIntent;
public NotificationData() {
}
public String toString() { public String toString() {
return "NotificationData(package=" + pkg + " tickerText=" + tickerText return "NotificationData(package=" + pkg + " tickerText=" + tickerText
+ " ongoingEvent=" + ongoingEvent + " contentIntent=" + contentIntent + " ongoingEvent=" + ongoingEvent + " contentIntent=" + contentIntent

View File

@ -126,7 +126,7 @@ public class StatusBarService extends IStatusBar.Stub
public interface NotificationCallbacks { public interface NotificationCallbacks {
void onSetDisabled(int status); void onSetDisabled(int status);
void onClearAll(); void onClearAll();
void onNotificationClick(String pkg, int id); void onNotificationClick(String pkg, String tag, int id);
void onPanelRevealed(); void onPanelRevealed();
} }
@ -833,7 +833,7 @@ public class StatusBarService extends IStatusBar.Stub
content.setOnFocusChangeListener(mFocusChangeListener); content.setOnFocusChangeListener(mFocusChangeListener);
PendingIntent contentIntent = n.contentIntent; PendingIntent contentIntent = n.contentIntent;
if (contentIntent != null) { if (contentIntent != null) {
content.setOnClickListener(new Launcher(contentIntent, n.pkg, n.id)); content.setOnClickListener(new Launcher(contentIntent, n.pkg, n.tag, n.id));
} }
View child = null; View child = null;
@ -896,7 +896,7 @@ public class StatusBarService extends IStatusBar.Stub
com.android.internal.R.id.content); com.android.internal.R.id.content);
PendingIntent contentIntent = n.contentIntent; PendingIntent contentIntent = n.contentIntent;
if (contentIntent != null) { if (contentIntent != null) {
content.setOnClickListener(new Launcher(contentIntent, n.pkg, n.id)); content.setOnClickListener(new Launcher(contentIntent, n.pkg, n.tag, n.id));
} }
} }
catch (RuntimeException e) { catch (RuntimeException e) {
@ -1248,11 +1248,13 @@ public class StatusBarService extends IStatusBar.Stub
private class Launcher implements View.OnClickListener { private class Launcher implements View.OnClickListener {
private PendingIntent mIntent; private PendingIntent mIntent;
private String mPkg; private String mPkg;
private String mTag;
private int mId; private int mId;
Launcher(PendingIntent intent, String pkg, int id) { Launcher(PendingIntent intent, String pkg, String tag, int id) {
mIntent = intent; mIntent = intent;
mPkg = pkg; mPkg = pkg;
mTag = tag;
mId = id; mId = id;
} }
@ -1267,7 +1269,7 @@ public class StatusBarService extends IStatusBar.Stub
} }
try { try {
mIntent.send(); mIntent.send();
mNotificationCallbacks.onNotificationClick(mPkg, mId); mNotificationCallbacks.onNotificationClick(mPkg, mTag, mId);
} catch (PendingIntent.CanceledException e) { } catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here. Just log the exception message. // the stack trace isn't very helpful here. Just log the exception message.
Log.w(TAG, "Sending contentIntent failed: " + e); Log.w(TAG, "Sending contentIntent failed: " + e);