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

时间: 2024-12-14 19:38:43

android systemUI--Notification 整理的相关文章

【转】android SystemUI 流程分析

android4 SystemUI 流程分析 什么是SystemUI? 对于Phone来说SystemUI指的是:StatusBar(状态栏).NavigationBar(导航栏).而对于Tablet或者是TV来说SystemUI指的是:CombinedBar(包括了StatusBar和NavigationBar). 启动后Phone界面上的信号,蓝牙标志,Wifi标志等等这些状态显示标志都会在StatusBar上显示.当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的Sys

Android通知Notification

一个小demo.点击 发送通知 按钮,则发送通知到设备的通知栏.点击 清除通知 则清除通知栏上的消息通知. package zhangphil.notification; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.app.Activity; import android.app.Notification; import android.app.N

【Android进阶】Android面试题目整理与讲解

这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的增加,如果答案有错误,希望大家可以指正 1.简述Activity的生命周期 当Activity开始启动的时候,首先调用onCreate(),onStart(),onResume()方法,此时Activity对用户来说,是可见的状态 当Activity从可见状态变为被Dialog遮挡的状态的时候,会调用onPause()方法,此时的Activity对用户可见,但是不能相 应用户的点击事件 当Activity从可见状态变为被其他

Android Push Notification实现信息推送使用

本贴在http://www.cnblogs.com/hanyonglu/archive/2012/03/16/2399655.html下略为改动. Apndroid Push Notification的特点:  快速集成:提供一种比C2DM更加快捷的使用方式,避免各种限制. 无需架设服务器:通过使用"云服务",减少额外服务器负担. 可以同时推送消息到网站页面,android 手机 耗电少,占用流量少. 具体配置过程:  首先, 我们需要下载androidpn-client-0.5.0.

Android通知Notification详解

Notification的使用大体步骤 Notification简介 PendingIntent简介 使用RemoteViews自定义Notification 更新与移除通知 设定提示响应 附录 Notification的使用大体步骤: 1. 获取状态通知栏管理 2. 实例化通知栏构造器 3. 设置NotificationCompat.Builder 4. 设置PendingIntent 5. 显示 因为Android的快速发展,而Android的版本也快速的升级导致了一些兼容性的问题.对于No

Android笔记(七十三) Android权限问题整理 非常全面

Android权限系统非常庞大,我们在Android系统中做任何操作都需要首先获取Android系统权限,本文记录了所有的Android权限问题,整理一下分享给大家. 访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permission.ACCESS_COARSE_LOCATION通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~150

Android Intent 使用整理

在一个Android应用中,主要是由一些组件组成,(Activity,Service,ContentProvider,etc.)在这些组件之间的通讯中,由Intent协助完成. 正如网上一些人解析所说,Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用.Intent在这里起着实现调用者与被调用者之间的解耦作用.Intent传递过程中,要找到目标消费者(另一个Act

【Android进阶】Android面试题目整理与讲解(二)

今天真机调试的时候莫名其妙遇到了这样的一个问题: This product type must be built using a provisioning profile, however no provisioning profile matching both the identity "iPhone Developer" and the bundle identifier..... 具体如下图所示: 十分蛋疼, 发现不管是从网上下的demo, 还是自己的过程.凡事真机测试的时候都

Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)

在android的应用层中,涉及到很多应用框架,例如:Service框架,Activity管理机制,Broadcast机制,对话框框架,标题栏框架,状态栏框架,通知机制,ActionBar框架等等. 下面就来说说经常会使用到通知机制中的通知栏框架(Notificaiton),它适用于交互事件的通知.它是位于顶层可以展开的通知列表.它会时不时的提醒你什么软件该更新了,什么人发你微信消息了等. (网上看了下,全面介绍的文章不多,所以就萌生了写这篇的念头,随便当作回顾笔记.下面我就通过官方文档.源代码

android通知栏Notification点击,取消,清除响应事件

主要是检测android通知栏的三种状态的响应事件 这次在实现推送需求的时候,要用到android通知栏Notification点击后进入消息页面,因为要实现一个保存推送用户名字的功能,我在点击后处理了这个功能,但是测试发现我点击删除或者滑动清除后这个功能并没有执行,所以才意识到要处理删除和滑动清除的事件: 首先实现一个BroadcastReceiver public class NotificationBroadcastReceiver extends BroadcastReceiver {