深入理解Android Notifiction机制

framework/base/core/java/android/app/NotificationManager.java

                framework/base/services/java/com/android/server/NotificationManagerService.java{@hide} extends INotificationManager.Stub

                framework/base/services/java/com/android/server/StatusBarManagerService.java  extends IStatusBarService.Stub



                framework/base/core/java/com/android/internal/statusbar/StatusBarNotification  implements Parcelable

                framework/base/core/java/com/android/internal/statusbar/IStatusBar.aidl

                framework/base/core/java/com/android/internal/statusbar/IStatusBarService.aidl

                framework/base/core/java/com/android/internal/statusbar/StatusBarNotification.aidl

               


                framework/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java extends Service implements CommandQueue.Callbacks

                framework/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java extends IStatusBar.Stub

1>.系统启动的时候:framework/base/services/java/com/android/server/SystemServer.java中:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
try {  
         Slog.i(TAG, "Status Bar" );    
         statusBar = new StatusBarManagerService(context);  
         ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);  
} catch (Throwable e) {  
          Slog.e(TAG, "Failure starting StatusBarManagerService" , e);  
}  
            
try {  
         Slog.i(TAG, "Notification Manager" );  
          notification = new NotificationManagerService(context, statusBar, lights);  
                          
          ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);  
} catch (Throwable e) {  
          Slog.e(TAG, "Failure starting Notification Manager" , e);  
}  

这段代码是 注册状态栏管理和通知管理这两个服务。

2>.在StatusBarManagerService.java中,有addNotification,removeNotification,updateNotification等方法用于管理传递给他的通知对象。这个类是一些管理方法,实际执行相关动作的是在IStatusBar.java里面,这个是framework/base/core/java/com/android/internal/statusbar/IStatusBar.aidl自动生成的用于IPC的类。

                拿addNotification方法示范:


?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
public IBinder addNotification(StatusBarNotification notification) {  
                synchronized (mNotifications) {  
                IBinder key = new Binder();  
                mNotifications.put(key, notification);  
                if (mBar != null ) {  
                try {  
                     mBar.addNotification(key, notification);  
                   } catch (RemoteException ex) {  
                }  
             }  
             return key;  
         }  
       }  

这里的mBar其实就是IStatusBar的实例
?
代码片段,双击复制
01
volatile IStatusBar mBar;  

为了防止NPE,每次使用mBar都先判断是否为null,mBar是在方法registerStatusBar中传递进来的。
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,  
             List<IBinder> notificationKeys, List<StatusBarNotification> notifications) {  
         enforceStatusBarService();  
    
         Slog.i(TAG, "registerStatusBar bar=" + bar);  
         mBar = bar;  
         synchronized (mIcons) {  
             iconList.copyFrom(mIcons);  
         }  
         synchronized (mNotifications) {  
             for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {  
                notificationKeys.add(e.getKey());  
                notifications.add(e.getValue());  
             }  
         }  
         }  

framework/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java实现IStatusBar.java接口,

framework/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java提供IStatusBar相关服务。

                CommandQueue.java中,IStatusBar.java里面对应的方法是用callback的形式调用的,callback的实现当然就在对应的服务提供类也就是StatusBarService.java中提供的啦。

                CommandQueue.java中:


?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
public void addNotification(IBinder key, StatusBarNotification notification) {  
         synchronized (mList) {  
             NotificationQueueEntry ne = new NotificationQueueEntry();  
             ne.key = key;  
             ne.notification = notification;  
             mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0 , 0 , ne).sendToTarget();  
                //这句话对应的mHandler执行语句是:  
                //  final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;  
             // mCallbacks.addNotification(ne.key, ne.notification);  
                //也就是调用回调函数里面的addNotification。  
         }  
    }     

在StatusBarService.java中:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
mCommandQueue = new CommandQueue( this , iconList); //StatusBarService实现了CommandQueue中的CommandQueue.Callbacks接口  
         mBarService = IStatusBarService.Stub.asInterface(  
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));  
         try {  
                //将IStatusBar实现类的对象传递到StatusBarManagerService.java中,这里的mCommandQueue就是上面对应的mBar啦。  
             mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications);  
         } catch (RemoteException ex) {  
             // If the system process isn't there we're doomed anyway.  
         }  

最终执行状态栏更新通知等事件都是在实现的CommandQueue.Callbacks里面执行。还是以addNotification为例:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
public void addNotification(IBinder key, StatusBarNotification notification) {  
         boolean shouldTick = true ;  
         if (notification.notification.fullScreenIntent != null ) {  
             shouldTick = false ;  
             Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent" );  
             try {  
                notification.notification.fullScreenIntent.send();  
             } catch (PendingIntent.CanceledException e) {  
             }  
         }   
    
         StatusBarIconView iconView = addNotificationViews(key, notification);  
         if (iconView == null ) return ;  
          //。。。以下省略N字。  

大致流程就是:调用StatusBarManagerService.java中的addNotification方法->(mBar不为空的话)执行mBar.addNotification(key, notification);->对应的是CommandQueue中的addNotification(IBinder key, StatusBarNotification notification)->CommandQueue中的mCallbacks.addNotification(ne.key, ne.notification);->StatusBarService中的addNotification。

3>.上面是提供相关功能的一些类,具体的notification的管理类是framework/base/services/java/com/android/server/NotificationManagerService.java,从该类的定义public class NotificationManagerService extends INotificationManager.Stub可以知道

他是用来实现接口中INotificationManager中定义的相关方法并向外部提供服务的类。主要向外提供public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,int[] idOut)方法。该方法实际上是调用public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,String tag, int id, Notification notification, int[] idOut),他里面提供了notification的具体处理方法。

                摘取部分代码片段看看:


?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
if (notification.icon != 0 ) {  
                StatusBarNotification n = new StatusBarNotification(pkg, id, tag,  
                         r.uid, r.initialPid, notification);  
                if (old != null && old.statusBarKey != null ) {  
                     r.statusBarKey = old.statusBarKey;  
                     long identity = Binder.clearCallingIdentity();  
                     try {  
                         mStatusBar.updateNotification(r.statusBarKey, n);  
                     }  
                     finally {  
                         Binder.restoreCallingIdentity(identity);  
                     }  
                } else {  
                     //省略。。。  

当判断好需要更新通知的时候调用mStatusBar.updateNotification(r.statusBarKey, n);方法,这个就是StatusBarManagerService.java中的addNotification方法,这样就进入上面所说的处理流程了。

4>. 在3中的NotificationManagerService.java是管理notification的服务,服务嘛就是用来调用的,调用他的就是大家熟悉的NotificationManager了。

在NotificationManager.java中,有一个隐藏方法,用来得到INotificationManager接口对应的服务提供类,也就是NotificationManagerService了。


?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
/** @hide */  
    static public INotificationManager getService()  
    {  
         if (sService != null ) {  
             return sService;  
         }  
         IBinder b = ServiceManager.getService( "notification" );  
         sService = INotificationManager.Stub.asInterface(b);  
         return sService;  
    }  

再看看更熟悉的notify方法,其实是执行:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
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.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);  
             if (id != idOut[ 0 ]) {  
                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[ 0 ]);  
             }  
         } catch (RemoteException e) {  
         }  
    }  

ervice.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);也就是3中提到的那个对外公开的服务方法了,这样就进入了上面提到的处理流程了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值