android systemUI--Notification 整理
PendingIntent
Intent是一个意图,一个描述了想要启动一个Activity、Broadcast或是Service的意图。它主要持有的信息是它想要启动的组件(Activity、Broadcast或是Service)。
PendingIntent可以看作是对Intent的包装。供当前App之外的其他App调用。有点“被动”或是“Callback”的意思,但不是严格意义上的“被动”或是“Callback”。总之,当前App不能用它马上启动它所包裹的Intent。而是在外部App执行这个PendingIntent时,间接地、实际地调用里面的Intent。PendingIntent主要持有的信息是它所包装的Intent和当前App的Context。正由于PendingIntent中保存有当前App的Context,使它赋予外部App一种能力,使得外部App可以如同当前App一样的执行PendingIntent里的Intent,就算在执行时当前App已经不存在了,也能通过存在PendingIntent里的Context照样执行Intent。
参考:http://www.eoeandroid.com/thread-96512-1-1.html
NotificationManager
源码位置:framework/base/core/java/android/app/NotificationManager.java
enuqunotificationwithtag
功能:
负责“发出”与“取消” Notification。
方法:
notify();
cancel();
INotificationManager.Java
frameworks/base/services/java/com/android/server/ NotificationManagerService.java
Notification
SystemServer.java
StatusBarManagerService.java(初始化)
NotificationManagerService.java(statusBarManagerService.setNotificationCallBack)
[systemreadly]
SystemUIService.java----onCreate(); --- for( SystemUI.start() )
StatusBar.java --- start() -- registerStatusBar();
mandQueue.java 通过handler更新ui
./base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java()
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
n = new Notification();
n.flags = Notification.FLAG_ONGOING_EVENT;
n.icon = R.drawable.notify;
n.tickerText = "一个通知";
n.when = System.currentTimeMillis();
nm.notify(id,n);
开机 |
SystemServer |
StatusBarManagerService |
NotificationManagerService |
SystemUIService |
PhoneStatusBar |
CommandQueue |
NotificationManager |
发起Notification |
开机 启动过程 |
通知更新 |
绑定Statusbar |
通知有Notification需要更新 |
通知更新ui |
StatusBar分为两个部分:一是通常在手机界面最上端的未下拉的statusbar;二是下拉状态栏,也就是扩展状态栏。
通过在实际应用中,我们可以发现,statusbar就是一个activity,那么,它的使用自然少不了和service之间的交互。
PhoneStatusBar 通过IStatusBarService来访问StatusBarManagerService,而
StatusBarManagerService通过CommandQueue来和PhoneStatusBar进行交互。
一、StatusBar.java
通过class StatusBar的声明,我们可以看出,它或者其子类实现和StatusBarManagerService进行交互的CommandQueue的回调方法。
public abstract class StatusBar extends SystemUI implements CommandQueue.Callbacks {
public void start() {
View sb = makeStatusBarView();
//创建包括在config.xml中定义要在statusbar上显示的所有icons,那么它包含icons个数在何处初始化?
StatusBarIconList iconList = new StatusBarIconList();
(frameworks\base\core\java\com\android\internal\statusbar)
//保存Notification是以Binder为key的
ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
//保存在statusbar上显示的StatusBarNotification
ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();
//和IStatusBarService进行交互的IBinder
mCommandQueue = new CommandQueue(this, iconList);
//获取StatusBarManagerService的本地实现
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
int[] switches = new int[7];
ArrayList<IBinder> binders = new ArrayList<IBinder>();
try {
//这一步实际上就是将PhoneStatusBar的实现的CommandQueue其中包含
//callbacks传递给StatusbarManagerService使用
mBarService.registerStatusBar(mCommandQueue,
iconList, notificationKeys, notifications,
switches, binders);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
for (int i=0; i<N; i++) {
//这里第一次使用时icon仅仅是开辟一个存储空间,i代表的是数组的index,而viewIndex和i对应
StatusBarIcon icon = iconList.getIcon(i);
if (icon != null) {
addIcon(iconList.getSlot(i), i, viewIndex, icon);
viewIndex++;
}
}
N = notificationKeys.size();
if (N == notifications.size()) {
for (int i=0; i<N; i++) {
addNotification②(notificationKeys.get(i), notifications.get(i));
}
} else {
}
//xml文件中定义的statusbar的height
(frameworks\base\core\res\res\values)
final int height = getStatusBarHeight();
}
//这里将所有的状态栏上的view先初始化
WindowManagerImpl.getDefault().addView(sb, lp);
}
二、PhoneStatusBar.java
public class PhoneStatusBar extends StatusBar {
}
PhoneStatusBar 是StatusBar(extends SystemUI)的子类,真正和StatusBarManagerService交互的实际上就是它。
对于SystemUI,首先启动的是Start();
public void start() {
……
//调用StatusBar的start方法,建立和StatusbarManagerService之间的联系
super.start();//在StatusBar的start中实现makeStatusBarView然后初始化statusbar icon状态
//启动更新Icon的方法
mIconPolicy = new PhoneStatusBarPolicy(mContext);
}
super.start()中我们看到,StatusBar是一个abstract类,真正要建立View是不能够的,必须在子类中创建。
实际上,StatusBar中也这样定义protected abstract View makeStatusBarView()
PhoneStatusBar 中:
protected View makeStatusBarView() {
final Context context = mContext;
Resources res = context.getResources();
//定义Icon的大小,缩放率和彼此间距
loadDimens();
mIconSize =
res.getDimensionPixelSize(com.Android.internal.R.dimen.status_bar_icon_size);
//状态栏下拉时的view
ExpandedView expanded = (ExpandedView)View.inflate(context,
R.layout.status_bar_expanded, null);
//真正显示的statusbar是根据是否是双卡来选择xml文件
PhoneStatusBarView sb;
if (TelephonyManager.getDefault().isMultiSimEnabled()) {
sb = (PhoneStatusBarView)View.inflate(context,
R.layout.msim_status_bar, null);
} else {
sb = (PhoneStatusBarView)View.inflate(context,
R.layout.status_bar, null);
}
//获取statusbar的实例
sb.mService = this;
mStatusBarView = sb;
//显示statusbar icon的view
mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
//显示notification的view
mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
mMoreIcon = sb.findViewById(R.id.moreIcon);
//定义下拉状态栏,显示Notifications
mExpandedDialog = new ExpandedDialog(context);
/*这个expanded就是指layout下的status_bar_expanded.xml解析所得下拉状态栏*/
mExpandedView = expanded;
//显示Notification的控件,NotificationRowLayout是处理函数,
mPile = (NotificationRowLayout)expanded.findViewById(R.id.latestItems);
mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
//Android2.3中显示onGoing等信息的textview,android4.0已经不用了
mNoNotificationsTitle = (TextView)expanded.findViewById(R.id.noNotificationsTitle);
mNoNotificationsTitle.setVisibility(View.GONE);
……
}
在步骤一的函数start()中的标识①处调用的是PhoneStatusBar的函数,在那里初始化status bar icon,
前面说了,在registerStatusBar时获得的iconList是没有icon的
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
//依据config.xml中的config_statusBarIcons定义的字符串创建StatusBarIconView,注意
//mContext是PhoneStatusBar的mContext
StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
//设置显示的icon
view.set(icon);
//添加到msim_status_bar.xml的保存icon的view中去
if (FeatureQuery.FEATURE_ANNUCIATOR_NEW_STATUSBAR_STYLE) {
mStatusIcons.addView(view, viewIndex,
new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, mIconSize));
} else {
mStatusIcons.addView(view, viewIndex,
new LinearLayout.LayoutParams(mIconSize, mIconSize));
}
}
在PhoneStatusBar.java中用到下面这两个类
StatusBarIconsView.java
public class StatusBarIconView extends AnimatedImageView
public StatusBarIconView(Context context, String slot, Notification notification) {
final Resources res = context.getResources();
mSlot = slot;
mNumberPain = new Paint();
mNumberPain.setTextAlign(Paint.Align.CENTER);
mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color));
mNumberPain.setAntiAlias(true);
mNotification = notification;
……
setScaleType(ImageView.ScaleType.CENTER);
}
}
由class的声明可以看出,StatusBarIconView是一个AnimatedImageView,因此,可以显示icon
public boolean set(StatusBarIcon icon) {
final boolean iconEquals = mIcon != null
&& streq(mIcon.iconPackage, icon.iconPackage)
&& mIcon.iconId == icon.iconId;
final boolean levelEquals = iconEquals
&& mIcon.iconLevel == icon.iconLevel;
final boolean visibilityEquals = mIcon != null
&& mIcon.visible == icon.visible;
final boolean numberEquals = mIcon != null
&& mIcon.number == icon.number;
//将icon信息拷贝给mIcon
mIcon = icon.clone();
if (!iconEquals) {
Drawable drawable = getIcon(icon);
if (drawable == null) {
return false;
}
//下面两步就是获取drawable,然后设置到view中去
setImageDrawable(drawable);
}
}
private Drawable getIcon(StatusBarIcon icon) {
//我们在PhoneStatusBar中创建StatusBarIconView时传了mContext,因此这里getContext()
//也是PhoneStatusBar的
return getIcon(getContext(), icon);
}
public static Drawable getIcon(Context context, StatusBarIcon icon) {
……
try {
//获取icon
return r.getDrawable(icon.iconId);
} catch (RuntimeException e) {
}
return null;
}
只有在下面这个类中才正式显示icon在statusbar上
PhoneStatusBarPolicy.java
Context是PhoneStatusBar的mContext
public PhoneStatusBarPolicy(Context context) {
//StatusBarManagerService
mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(
new com.Android.systemui.usb.StorageNotification(context));
// TTY status
mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null);
// Alarm clock
mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
mService.setIconVisibility("alarm_clock", false);
// volume
mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
mService.setIconVisibility("volume", false);
updateVolume();
//headset
mService.setIcon("headset", com.Android.internal.R.drawable.stat_sys_headset, 0, null);
mService.setIconVisibility("headset", false);
}
上面的mService是StatusBarManager,那么setIcon是操作如下:
StatusBarManager.java
public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
try {
//StatusBarManagerService的本地代理service
final IStatusBarService svc = getService();
if (svc != null) {
svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel,
contentDescription);
}
} catch (RemoteException ex) {
// system process is dead anyway.
throw new RuntimeException(ex);
}
}
三、StatusBarManagerService.java
前面,我们启动PhoneStatusBar时会调用StatusBar的start函数,在这里和StatusbarManagerService
建立联系。
StatusBar.java中
mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
switches, binders);
public class StatusBarManagerService extends IStatusBarService.Stub
implements WindowManagerService.OnHardKeyboardStatusChangeListener
{
public StatusBarManagerService(Context context, WindowManagerService windowManager) {
mContext = context;
mWindowManager = windowManager;
mWindowManager.setOnHardKeyboardStatusChangeListener(this);
final Resources res = context.getResources();
//这里,获取config_statusBarIcons.xm中定义的显示icon的数组
mIcons.defineSlots(res.
getStringArray(com.Android.internal.R.array.config_statusBarIcons));
}
}
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
int switches[], List<IBinder> binders) {
//这个bar就是CommandQueue在PhoneStatusbar中的实现callbacks
mBar = bar;
synchronized (mIcons) {
//将初始化这个service时获取的config_statusBarIcons数组中字符串保存到iconList,
//也就是传递给PhoneStatusBar使用了
iconList.copyFrom(mIcons);
}
synchronized (mNotifications) {
for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
notificationKeys.add(e.getKey());
notifications.add(e.getValue());
}
}
……
}
public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
String contentDescription) {
enforceStatusBar();
synchronized (mIcons) {
//也就是当前这个slot在数组中的index
int index = mIcons.getSlotIndex(slot);
//如果没有定义的slot,就报异常
if (index < 0) {
throw new SecurityException("invalid status bar icon slot: " + slot);
}
//这才正式创建StatusBarIcon,iconPackage是PhoneStatusBar的,iconId就是我们设置的
StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel, 0,
contentDescription);
//数组中对应的index设置了icon
mIcons.setIcon(index, icon);
if (mBar != null) {
try {
mBar.setIcon(index, icon);
} catch (RemoteException ex) {
}
}
}
}
CommandQueue.java
public void setIcon(int index, StatusBarIcon icon) {
synchronized (mList) {
//mList用的也是StatusBarManagerService中初始化的iconList
int what = MSG_ICON | index;
mHandler.removeMessages(what);
mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
}
}
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
switch (what) {
case MSG_ICON: {
final int index = msg.what & INDEX_MASK;
final int viewIndex = mList.getViewIndex(index);
switch (msg.arg1) {
case OP_SET_ICON: {
StatusBarIcon icon = (StatusBarIcon)msg.obj;
//mList
StatusBarIcon old = mList.getIcon(index);
if (old == null) {
mList.setIcon(index, icon);
mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
} else {
mList.setIcon(index, icon);
mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
old, icon);
}
break;
}
}
}
最后就是调用PhoneStatusBar的addIcon。至此,就用StatusBar显示了icon
android systemUI--Notification 整理的更多相关文章
- 【转】android SystemUI 流程分析
android4 SystemUI 流程分析 什么是SystemUI? 对于Phone来说SystemUI指的是:StatusBar(状态栏).NavigationBar(导航栏).而对于Tablet ...
- Android之Notification介绍
Notification就是在桌面的状态通知栏.这主要涉及三个主要类: Notification:设置通知的各个属性. NotificationManager:负责发送通知和取消通知 Notifica ...
- Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)
在android的应用层中,涉及到很多应用框架,例如:Service框架,Activity管理机制,Broadcast机制,对话框框架,标题栏框架,状态栏框架,通知机制,ActionBar框架等等. ...
- android通知栏Notification点击,取消,清除响应事件
主要是检测android通知栏的三种状态的响应事件 这次在实现推送需求的时候,要用到android通知栏Notification点击后进入消息页面,因为要实现一个保存推送用户名字的功能,我在点击后处理 ...
- android通知-Notification
android中,当app需要向发送一些通知,让使用者注意到你想要告知的信息时,可以用Notification.下面,就来讨论一下,Notification的用法,我们从实际的小例子来进行学习. 1. ...
- Android --通知栏Notification
参考博客:Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它) //创建一个通知栏的Builder构造类 (Create a Notification Bui ...
- Android之Notification的多种用法(转)
我们在用手机的时候,如果来了短信,而我们没有点击查看的话,是不是在手机的最上边的状态栏里有一个短信的小图标提示啊?你是不是也想实现这种功能呢?今天的Notification就是解决这个问题的. 我们也 ...
- 【转】can't find referenced method 'android.app.RemoteInput[] getRemoteInputs()' in class android.app.Notification$Action
原文网址:http://stackoverflow.com/questions/25508735/cant-find-referenced-method-android-app-remoteinput ...
- 【转】GitHub平台最火Android开源项目整理——2013-08-25 17
http://game.dapps.net/news/developer/9199.html GitHub在中国的火爆程度无需多言,越来越多的开源项目迁移到GitHub平台上.更何况,基于不要重复造轮 ...
- Android之Notification的多种用法
我们在用手机的时候,如果来了短信,而我们没有点击查看的话,是不是在手机的最上边的状态栏里有一个短信的小图标提示啊?你是不是也想实现这种功能呢?今天的Notification就是解决这个问题的. 我们也 ...
随机推荐
- tar解压
tar在linux上是常用的打包.压缩.加压缩工具,他的参数很多,折里仅仅列举常用的压缩与解压缩参数 参数: -c :create 建立压缩档案的参数:-x : 解压缩压缩档案的参数:-z : 是否需 ...
- 关于微信分享功能开发的一些bug
wx.onMenuShareTimeline({//onMenuShareTimeline title: (h('#mainForm').children('.content').inf('value ...
- utf8 文件 错误保存为gbk 中文乱码 解决方法
用zend studio 将utf-8 格式的文件 保存为 gbk 了,之后无论怎么装换 中文都是乱码 用 beyond compare(文件比较工具 对编码支持的比较强大) 打开,改下编码,中文就 ...
- listview前几个item的图片怎么是空白的、listview更新了ui不起作用、在handler里更新了UI不起作用
不是不起作用,不信你可以在更新ui代码附近加输出的log,说明程序是跑到那里了.但是未达到我们的想要的效果. 我们知道在listview里更新UI,listview的适配器Adapter里有个getV ...
- A*搜寻算法(A星算法)
A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...
- Linux 查硬件配置
一:查看cpu more /proc/cpuinfo | grep "model name" grep "model name" /proc/cpuinfo 如 ...
- OSPF 原理
关于OSPF的数据结构Link-State Protocol Data Structures链路状态路由器与距离矢量路由器,可以知道关于整个网络的更多信息Neighbor table:also kno ...
- 8.1 sikuli报错: 提示没有对应的javaw
对于sikuli,需要安装32位的jdk且不能高于1.7的版本. 对于64位系统的C盘,Program Files文件夹是64位的,Program File(x86)文件夹是32位的 需要安装一个32 ...
- eclipse的调试方法的简单介绍
声明:本文不是自己 作为编程人员,程序的调试是一项基本功.在不使用IDE的时候,程序的调试多数是通过日志或者输入语句(System.out.println)的方式.可以把程序运行的轨迹或者程序运行过程 ...
- new thoughts over function pointers
Previous works do not relate to function pointers, but reading some documents reading and learning S ...