转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>
NotificationManager支持Toast和Notification两种通知方式,前者相当于一个定时关闭的对话框,后者是在状态栏上显示一条消息。Toast和Notification都可以随时取消。INotificationManager的接口定义如下:
INotificationManager
interface INotificationManager
{
void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived);
void cancelNotification(String pkg, int id);
void cancelAllNotifications(String pkg);
void enqueueToast(String pkg, ITransientNotification callback, int duration);
void cancelToast(String pkg, ITransientNotification callback);
}
Toast
Toast在show时会自动调用enqueueToast:
public void show() {
if (mNextView == null) {
throw new RuntimeException(“setView must have been called”);
}
INotificationManager service = getService();
String pkg = mContext.getPackageName();
TN tn = mTN;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
NotificationManager
NotificationManager对service的接口做了包装:
获取service,并转换成INotificationManager接口:
static private INotificationManager getService()
{
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService(“notification”);
sService = INotificationManager.Stub.asInterface(b);
return sService;
}
发送notification, 会自动填充一些参数,然后调用enqueueNotification。
public void notify(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);
if (id != idOut[0]) {
Log.w(TAG, “notify: id corrupted: sent ” + id + “, got back ” + idOut[0]);
}
} catch (RemoteException e) {
}
}
Notification
Notification主要是存放通知需要的相关数据,比如图标、信息、时间和手机表现方式(如闪烁、声音和震动)以及用户点击之后要打开的URL等。
/**
* Constructs a Notification object with the information needed to
* have a status bar icon without the standard expanded view.
*
* @param icon The resource id of the icon to put in the status bar.
* @param tickerText The text that flows by in the status bar when the notification first
* activates.
* @param when The time to show in the time field. In the System.currentTimeMillis
* timebase.
*/
public Notification(int icon, CharSequence tickerText, long when)
{
this.icon = icon;
this.tickerText = tickerText;
this.when = when;
}
public void setLatestEventInfo(Context context,
CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
RemoteViews contentView = new RemoteViews(context.getPackageName(),
com.android.internal.R.layout.status_bar_latest_event_content);
if (this.icon != 0) {
contentView.setImageViewResource(com.android.internal.R.id.icon, this.icon);
}
if (contentTitle != null) {
contentView.setTextViewText(com.android.internal.R.id.title, contentTitle);
}
if (contentText != null) {
contentView.setTextViewText(com.android.internal.R.id.text, contentText);
}
if (this.when != 0) {
Date date = new Date(when);
CharSequence str =
DateUtils.isToday(when) ? DateFormat.getTimeFormat(context).format(date)
: DateFormat.getDateFormat(context).format(date);
contentView.setTextViewText(com.android.internal.R.id.time, str);
}
this.contentView = contentView;
this.contentIntent = contentIntent;
}
NotificationManagerService
NotificationManagerService则是负责实际的Notification管理了。
里面实现了一个BroadcastReceiver,用来监听电池充电状态和软件包管理的事件。
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
…
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
…
}
}
};
震动调用Vibrator的函数。
播放声音调用AsyncPlayer的函数。
闪光调用HardwareService的函数。
向StatusBarService注册相关事件。
statusBar.setNotificationCallbacks(mNotificationCallbacks);