Android5.0如下 源碼分析Notification的notify

分析下Notification的更新機制。java

涉及Service:android

StatusBarManagerService

  NotificationManagerServiceapp

這個兩個service都會在 frameworks/base/services/java/com/android/server/SystemServer.java文件裏面進行啓動的ide

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.post

當在Activity裏面建立一個Notification,並Notifyui

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 方法server

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<IBinder> notificationKeys, List<StatusBarNotification> notifications,
431            int switches[], List<IBinder> 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上面。

相關文章
相關標籤/搜索