博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解Notification机制
阅读量:5794 次
发布时间:2019-06-18

本文共 8380 字,大约阅读时间需要 27 分钟。

Android蓝牙控制遥控器的源码

基于Android 砸蛋的游戏

Android下浏览其文件系统的工具

 

先贴上这些源码里面相关的文件:

     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中:

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方法示范:

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的实例

volatile IStatusBar mBar;

为了防止NPE,每次使用mBar都先判断是否为null,mBar是在方法registerStatusBar中传递进来的。

public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,               List
notificationKeys, List
notifications) { enforceStatusBarService(); Slog.i(TAG, "registerStatusBar bar=" + bar); mBar = bar; synchronized (mIcons) { iconList.copyFrom(mIcons); } synchronized (mNotifications) { for (Map.Entry
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中:
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中:

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为例:

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的具体处理方法。

 摘取部分代码片段看看:

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了。

/** @hide */      static public INotificationManager getService()       {           if (sService != null) {               return sService;           }           IBinder b = ServiceManager.getService("notification");           sService = INotificationManager.Stub.asInterface(b);           return sService;       }

再看看更熟悉的notify方法,其实是执行:

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中提到的那个对外公开的服务方法了,这样就进入了上面提到的处理流程了。

 

 

 

 

 

 

 

 

 

 

 

转载地址:http://hnffx.baihongyu.com/

你可能感兴趣的文章
iOS:百度长语音识别具体的封装:识别、播放、进度刷新
查看>>
JS获取服务器时间并且计算距离当前指定时间差的函数
查看>>
华为硬件工程师笔试题
查看>>
jquery居中窗口-页面加载直接居中
查看>>
cd及目录快速切换
查看>>
Unity Shaders and Effects Cookbook (3-5) 金属软高光
查看>>
31-hadoop-hbase-mapreduce操作hbase
查看>>
C++ 代码风格准则:POD
查看>>
linux-友好显示文件大小
查看>>
【转】【WPF】WPF中MeasureOverride ArrangeOverride 的理解
查看>>
【转】二叉树的非递归遍历
查看>>
NYOJ283对称排序
查看>>
接连遇到大牛
查看>>
[Cocos2d-x For WP8]矩形碰撞检测
查看>>
自己写spring boot starter
查看>>
花钱删不完负面消息
查看>>
JBPM之JPdl小叙
查看>>
Membership三步曲之进阶篇 - 深入剖析Provider Model
查看>>
struts2中form提交到action中的中文参数乱码问题解决办法(包括取中文路径)
查看>>
25 个精美的手机网站模板
查看>>