add a optional String to the key of notifications to allow users
to scope them
diff --git a/api/current.xml b/api/current.xml
index 3612104e..54cff8d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -23166,6 +23166,21 @@
<parameter name="id" type="int">
</parameter>
</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"
return="void"
abstract="false"
@@ -23192,6 +23207,23 @@
<parameter name="notification" type="android.app.Notification">
</parameter>
</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 name="PendingIntent"
extends="java.lang.Object"
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c1035b6..4d5238c 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -24,11 +24,15 @@
/** {@hide} */
interface INotificationManager
{
+ /** @deprecated use {@link #enqueueNotificationWithTag} instead */
void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived);
+ /** @deprecated use {@link #cancelNotificationWithTag} instead */
void cancelNotification(String pkg, int id);
void cancelAllNotifications(String pkg);
void enqueueToast(String pkg, ITransientNotification callback, int duration);
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);
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 7b51fdf..6fe12fc 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -87,12 +87,27 @@
*/
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];
INotificationManager service = getService();
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
try {
- service.enqueueNotification(pkg, id, notification, idOut);
+ service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
@@ -107,11 +122,21 @@
*/
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();
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
try {
- service.cancelNotification(pkg, id);
+ service.cancelNotificationWithTag(pkg, tag, id);
} catch (RemoteException e) {
}
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 696ef31..ff23a13 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -30,7 +30,6 @@
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -103,7 +102,8 @@
private boolean mAdbNotificationShown = false;
private Notification mAdbNotification;
- private ArrayList<NotificationRecord> mNotificationList;
+ private final ArrayList<NotificationRecord> mNotificationList =
+ new ArrayList<NotificationRecord>();
private ArrayList<ToastRecord> mToastQueue;
@@ -152,20 +152,22 @@
private static final class NotificationRecord
{
- String pkg;
- int id;
+ final String pkg;
+ final String tag;
+ final int id;
ITransientNotification callback;
int duration;
- Notification notification;
+ final Notification notification;
IBinder statusBarKey;
- NotificationRecord(String pkg, int id, Notification notification)
+ NotificationRecord(String pkg, String tag, int id, Notification notification)
{
this.pkg = pkg;
+ this.tag = tag;
this.id = id;
this.notification = notification;
}
-
+
void dump(PrintWriter pw, String prefix, Context baseContext) {
pw.println(prefix + this);
pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon)
@@ -189,7 +191,8 @@
return "NotificationRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " pkg=" + pkg
- + " id=" + Integer.toHexString(id) + "}";
+ + " id=" + Integer.toHexString(id)
+ + " tag=" + tag + "}";
}
}
@@ -258,8 +261,8 @@
cancelAll();
}
- public void onNotificationClick(String pkg, int id) {
- cancelNotification(pkg, id, Notification.FLAG_AUTO_CANCEL,
+ public void onNotificationClick(String pkg, String tag, int id) {
+ cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
Notification.FLAG_FOREGROUND_SERVICE);
}
@@ -369,7 +372,6 @@
mSound = new AsyncPlayer(TAG);
mSound.setUsesWakeLock(context);
mToastQueue = new ArrayList<ToastRecord>();
- mNotificationList = new ArrayList<NotificationRecord>();
mHandler = new WorkerHandler();
mStatusBarService = statusBar;
statusBar.setNotificationCallbacks(mNotificationCallbacks);
@@ -583,6 +585,12 @@
// ============================================================================
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);
// This conditional is a dirty hack to limit the logging done on
@@ -608,10 +616,10 @@
}
synchronized (mNotificationList) {
- NotificationRecord r = new NotificationRecord(pkg, id, notification);
+ NotificationRecord r = new NotificationRecord(pkg, tag, id, notification);
NotificationRecord old = null;
- int index = indexOfNotificationLocked(pkg, id);
+ int index = indexOfNotificationLocked(pkg, tag, id);
if (index < 0) {
mNotificationList.add(r);
} else {
@@ -645,17 +653,18 @@
}
NotificationData n = new NotificationData();
- n.id = id;
- n.pkg = pkg;
- n.when = notification.when;
- n.tickerText = truncatedTicker;
- n.ongoingEvent = (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
- if (!n.ongoingEvent && (notification.flags & Notification.FLAG_NO_CLEAR) == 0) {
- n.clearable = true;
- }
- n.contentView = notification.contentView;
- n.contentIntent = notification.contentIntent;
- n.deleteIntent = notification.deleteIntent;
+ n.pkg = pkg;
+ n.tag = tag;
+ n.id = id;
+ n.when = notification.when;
+ n.tickerText = truncatedTicker;
+ n.ongoingEvent = (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
+ if (!n.ongoingEvent && (notification.flags & Notification.FLAG_NO_CLEAR) == 0) {
+ n.clearable = true;
+ }
+ n.contentView = notification.contentView;
+ n.contentIntent = notification.contentIntent;
+ n.deleteIntent = notification.deleteIntent;
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity();
@@ -828,16 +837,14 @@
* Cancels a notification ONLY if it has all of the {@code mustHaveFlags}
* 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) {
EventLog.writeEvent(EVENT_LOG_CANCEL, pkg, id, mustHaveFlags);
synchronized (mNotificationList) {
- NotificationRecord r = null;
-
- int index = indexOfNotificationLocked(pkg, id);
+ int index = indexOfNotificationLocked(pkg, tag, id);
if (index >= 0) {
- r = mNotificationList.get(index);
+ NotificationRecord r = mNotificationList.get(index);
if ((r.notification.flags & mustHaveFlags) != mustHaveFlags) {
return;
@@ -888,9 +895,13 @@
public void cancelNotification(String pkg, int id) {
+ cancelNotificationWithTag(pkg, null /* tag */, id);
+ }
+
+ public void cancelNotificationWithTag(String pkg, String tag, int id) {
checkIncomingCall(pkg);
// Don't allow client applications to cancel foreground service notis.
- cancelNotification(pkg, id, 0,
+ cancelNotification(pkg, tag, id, 0,
Binder.getCallingUid() == Process.SYSTEM_UID
? 0 : Notification.FLAG_FOREGROUND_SERVICE);
}
@@ -999,12 +1010,21 @@
}
// lock on mNotificationList
- private int indexOfNotificationLocked(String pkg, int id)
+ private int indexOfNotificationLocked(String pkg, String tag, int id)
{
ArrayList<NotificationRecord> list = mNotificationList;
final int len = list.size();
for (int i=0; i<len; 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)) {
return i;
}
diff --git a/services/java/com/android/server/status/NotificationData.java b/services/java/com/android/server/status/NotificationData.java
index 63a7d70..0a3411a1 100644
--- a/services/java/com/android/server/status/NotificationData.java
+++ b/services/java/com/android/server/status/NotificationData.java
@@ -5,6 +5,7 @@
public class NotificationData {
public String pkg;
+ public String tag;
public int id;
public CharSequence tickerText;
@@ -17,9 +18,6 @@
public PendingIntent deleteIntent;
- public NotificationData() {
- }
-
public String toString() {
return "NotificationData(package=" + pkg + " tickerText=" + tickerText
+ " ongoingEvent=" + ongoingEvent + " contentIntent=" + contentIntent
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 83552dd..9929498 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -126,7 +126,7 @@
public interface NotificationCallbacks {
void onSetDisabled(int status);
void onClearAll();
- void onNotificationClick(String pkg, int id);
+ void onNotificationClick(String pkg, String tag, int id);
void onPanelRevealed();
}
@@ -833,7 +833,7 @@
content.setOnFocusChangeListener(mFocusChangeListener);
PendingIntent contentIntent = n.contentIntent;
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;
@@ -896,7 +896,7 @@
com.android.internal.R.id.content);
PendingIntent contentIntent = n.contentIntent;
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) {
@@ -1248,11 +1248,13 @@
private class Launcher implements View.OnClickListener {
private PendingIntent mIntent;
private String mPkg;
+ private String mTag;
private int mId;
- Launcher(PendingIntent intent, String pkg, int id) {
+ Launcher(PendingIntent intent, String pkg, String tag, int id) {
mIntent = intent;
mPkg = pkg;
+ mTag = tag;
mId = id;
}
@@ -1267,7 +1269,7 @@
}
try {
mIntent.send();
- mNotificationCallbacks.onNotificationClick(mPkg, mId);
+ mNotificationCallbacks.onNotificationClick(mPkg, mTag, mId);
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here. Just log the exception message.
Log.w(TAG, "Sending contentIntent failed: " + e);