展会信息港展会大全

Android 源码分析Notification的notify
来源:互联网   发布日期:2015-10-02 21:46:15   浏览:1100次  

导读:在上一篇文章Android获取第三方音乐播放器的音乐信息的末尾,提到可以通过捕获第三方音乐发送的的Notification,来获取到当前播放的歌曲的信息。先分析下Notification的更新...

在上一篇文章Android获取第三方音乐播放器的音乐信息的末尾,提到可以通过捕获第三方音乐发送的的Notification,来获取到当前播放的歌曲的信息。先分析下Notification的更新机制。

涉及Service:

StatusBarManagerService

NotificationManagerService

这个两个service都会在frameworks/base/services/java/com/android/server/SystemServer.java文件里面进行启动的

class ServerThread extends Thread {

public void run() {

......

StatusBarManagerService statusBar = null;

NotificationManagerService notification = null;

......

statusBar = new StatusBarManagerService(context, wm);

ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);

......

notification = new NotificationManagerService(context, statusBar, lights);

ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);

......

}

}

下面开始跟踪Notification的Notify流程。

1.

当在Activity里面创建一个Notification,并Notify

NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

Notification n = new Notification(R.drawable.chat, "Hello,there!", System.currentTimeMillis());

n.flags = Notification.FLAG_AUTO_CANCEL;

Intent i = new Intent(arg0.getContext(), NotificationShow.class);

i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);

//PendingIntent

PendingIntent contentIntent = PendingIntent.getActivity(

arg0.getContext(),

R.string.app_name,

i,

PendingIntent.FLAG_UPDATE_CURRENT);

n.setLatestEventInfo(

arg0.getContext(),

"Hello,there!",

"Hello,there,I'm john.",

contentIntent);

nm.notify(R.string.app_name, n);

2.调用NotificationManager.notify,进入notify 方法

public void notify(int id, Notification notification)

{

notify(null, id, notification);

}

public void notify(String tag, int id, Notification notification)

{

......

INotificationManager service = getService();

......

service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,

notification, idOut, UserHandle.myUserId());

......

}

3.在调用notify(String tag, int id, Notification notification)时,会调用getService()

static public INotificationManager getService()

78 {

79 if (sService != null) {

80 return sService;

81 }

82 IBinder b = ServiceManager.getService("notification");

83 sService = INotificationManager.Stub.asInterface(b);

84 return sService;

85 }这里发现,会调用ServiceManager.getService("notification"), 这样就会获取到文章刚开始讲的NotificationManagerService 的一个binder对象。获取回到第二步调用service.enqueueNotificationWithTAG.

4.进入NotificationManagerService的enqueueNotificationWithTAG

public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,

1621 Notification notification, int[] idOut, int userId)

1622 {

1623 enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(), Binder.getCallingPid(),

1624 tag, id, notification, idOut, userId);

1625 }

1634 public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,

1635 final int callingPid, final String tag, final int id, final Notification notification,

1636 int[] idOut, int incomingUserId)

1637 {

......

final StatusBarNotification n = new StatusBarNotification(

1755 pkg, id, tag, callingUid, callingPid, score, notification, user);

1792 mStatusBar.updateNotification(r.statusBarKey, n);

1793

......

}在这个方法里,会将前面传递进来的Notification封装成一个StatusBarNotification对象,然后调用mStatusBar.updateNotification去更新,这个mStatusBar是什么?

5. 文章最开始提到会在ServerThread里面添加NotificationManagerService,在创建的NotificationManagerService的时候,会调用它的构造函数

NotificationManagerService(Context context, StatusBarManagerService statusBar,

1291 LightsService lights)

1292 {

.......

}这里面就会传递进来,在ServerThread里刚刚创建的StatusBarManagerService. 所以在第4步的时候我们能够调用mStatusBar.updateNotification()。

6.

StatusBarManagerService 中mStatusBar.updateNotification()方法

public void updateNotification(IBinder key, StatusBarNotification notification) {

512 synchronized (mNotifications) {

516 mNotifications.put(key, notification);

......

519 mBar.updateNotification(key, notification);

......

524 }这里会调用mBar.updateNotification(),mBar是什么?

7. StatusBarManagerService 中 mBar对象

volatile IStatusBar mBar;

// Callbacks from the status bar service.

428 // ================================================================================

429 public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,

430 List notificationKeys, List notifications,

431 int switches[], List binders) {

......

上面发现有个registerStatusBar方法,会传递进来一个IStatusBar 对象,那这个方法会在哪里调用呢?

8. 在StatusBarManagerService中,我们发现调用mBar对象都是去处理StatusBar的UI,那这个StatusBar是哪里的?SystemUI里面的。检索下SystemUI的代码,果然发现在

BaseStatusBar里面:

public void start() {

mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,

250 switches, binders);

}在这里registerStatusBar, 而这个mCommandQueue参数就是前面IStatusBar对象。

9. mCommanQueue变量

protected CommandQueue mCommandQueue;

28/**

29 * This class takes the functions from IStatusBar that come in on

30 * binder pool threads and posts messages to get them onto the main

31 * thread, and calls onto Callbacks. It also takes care of

32 * coalescing these calls so they don't stack up. For the calls

33 * are coalesced, note that they are all idempotent.

34 */

35public class CommandQueue extends IStatusBar.Stub{

/**

78 * These methods are called back on the main thread.

79 */

80 public interface Callbacks {

81 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon);

82 public void updateIcon(String slot, int index, int viewIndex,

83 StatusBarIcon old, StatusBarIcon icon);

84 public void removeIcon(String slot, int index, int viewIndex);

85 public void addNotification(IBinder key, StatusBarNotification notification);

86 public void updateNotification(IBinder key, StatusBarNotification notification);

87 public void removeNotification(IBinder key);

88 public void disable(int state);

89 public void animateExpandNotificationsPanel();

90 public void animateCollapsePanels(int flags);

91 public void animateExpandSettingsPanel();

92 public void setSystemUiVisibility(int vis, int mask);

93 public void topAppWindowChanged(boolean visible);

94 public void setImeWindowStatus(IBinder token, int vis, int backDisposition);

95 public void setHardKeyboardStatus(boolean available, boolean enabled);

96 public void toggleRecentApps();

97 public void preloadRecentApps();

98 public void showSearchPanel();

99 public void hideSearchPanel();

100 public void cancelPreloadRecentApps();

101 public void setNavigationIconHints(int hints);

102 public void setWindowState(int window, int state);

103 }

}

发现这个方法继承IStatusBar.stub,里面有一连串的回调函数。这些回调函数在BaseStatusBar里面实现的

public abstract class BaseStatusBar extends SystemUI implements

79 CommandQueue.Callbacks {

10. 回到第6步,当在StatusBarManagerService中调用mBar.updateNotification时,根据7,8,9的分析,最终会调用在BaseStatusBar里面实现的UpdateNotification方法

updateNotification(IBinder key, StatusBarNotification notification) {

......

}在这里会将Notification显 示在StatusBar上面。

这里面主要涉及到两个NotificationManagerService和StatusBarManager的交互。

第一步。

系统启动时在ServerThread里生成StatusBarManagerService和NotificationManagerService,并将StatusBarManagerService对象作为一个参数传递到NotificationManagerService的构造方法中。

系统加载应用,SystemUI中, BaseStatusBar实现回调函数CommandQueue.Callbacks, 并调用StatusBarManagerService的registerStatusBar方法,将CommandQueue对象传递进去

第二步

Activity里调用notify方法,在NotificationManagerService将Notification封装成StatusBarNotification。

NotificationManagerService调用statusBarManagerService的updateNotification()。

第三步

StatusBarManagerService调用CommandQueue实现的回调函数,最终将Notification显示在SystemUI上面。

下一篇文章会讲怎么实现捕获Notification的内容,从而实现采集第三方播放器播放音乐的信息

赞助本站

人工智能实验室

相关热词: android开发

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港