关于NotificationManagerService的使用推荐参考下面资料,写的不错:
Android4.4 NotificationManagerService使用详解与原理分析(一)、(二):点击打开链接
这里主要分析framework层的源码。
相关文件主要有:
frameworks\base\core\java\android\app\NotificationManager.java;
frameworks\base\services\core\java\com\android\server\notification\NotificationManagerService.java;
frameworks\base\services\core\java\com\android\server\statusbar\StatusBarManagerService.java;
第三方应用发起通知时,调用的是NotificationManager的notify方法,我们就从这里入手。
notify方法表示发送一个显示在状态栏上的通知,代码如下:
/**
* Post a notification to be shown in the status bar. If a notification with
* the same id has already been posted by your application and has not yet been canceled, it
* will be replaced by the updated information.
*
* @param id An identifier for this notification unique within your
* application.
* @param notification A {@link Notification} object describing what to show the user. Must not
* be null.
*/
public void notify(int id, Notification notification)
{
notify(null, id, notification);
}
如果你的第三方应用发送了一个相同id的通知,并且没有被取消,它将被更新的信息所取代。
/**
* Post a notification to be shown in the status bar. If a notification with
* the same tag and id has already been posted by your application and has not yet been
* canceled, it will be replaced by the updated information.
*
* @param tag A string identifier for this notification. May be {@code null}.
* @param id An identifier for this notification. The pair (tag, id) must be unique
* within your application.
* @param notification A {@link Notification} object describing what to
* show the user. Must not be null.
*/
public void notify(String tag, int id, Notification notification)
{
notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId()));
}
如果你的第三方应用发送了一个相同tag和id的通知,并且没有被取消,它将被更新的信息所取代。
/**
* @hide
*/
public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
{
int[] idOut = new int[1];
INotificationManager service = getService();//获取IBinder对象(NotificationManagerService)
String pkg = mContext.getPackageName();
// Fix the notification as best we can.
Notification.addFieldsFromContext(mContext, notification);//"android.appinfo"、"android.originatingUserId"
if (notification.sound != null) {
notification.sound = notification.sound.getCanonicalUri();
if (StrictMode.vmFileUriExposureEnabled()) {
notification.sound.checkFileUriExposed("Notification.sound");
}
}
fixLegacySmallIcon(notification, pkg);
if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (notification.getSmallIcon() == null) {
throw new IllegalArgumentException("Invalid notification (no valid small icon): "
+ notification);
}
}
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
try {
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
copy, idOut, user.getIdentifier());
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- 我们看下Notification的addFieldsFromContext方法做了哪些事情:
/**
* @hide
*/
public static void addFieldsFromContext(Context context, Notification notification) {
addFieldsFromContext(context.getApplicationInfo(), context.getUserId(), notification);
}
/**
* @hide
*/
public static void addFieldsFromContext(ApplicationInfo ai, int userId,
Notification notification) {
notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, ai);//"android.appinfo"
notification.extras.putInt(EXTRA_ORIGINATING_USERID, userId);//"android.originatingUserId"
}
主要是保存了当前应用对应的ApplicationInfo对象和对应的userId。在Android4.4中Notification新增了extras字段,用来保存系统通知的一些具体信息,定义如下:
/**
* Additional semantic data to be carried around with this Notification.
* <p>
* The extras keys defined here are intended to capture the original inputs to {@link Builder}
* APIs, and are intended to be used by
* {@link android.service.notification.NotificationListenerService} implementations to extract
* detailed information from notification objects.
*/
public Bundle extras = new Bundle();
addFieldsFromContext方法主要实现将当前应用的ApplicationInfo对象保存到“android.appinfo”字段,将当前的userId保存到“android.originatingUserId”字段中。
- fixLegacySmalIcon,notify函数会判断notification是否有small icon