android systemUI--Notification 整理

importandroid.app.PendingIntent;

importandroid.app.NotificationManager;

importandroid.app.Notification;

 

PendingIntent

Intent是一个意图,一个描述了想要启动一个ActivityBroadcast或是Service的意图。它主要持有的信息是它想要启动的组件(ActivityBroadcast或是Service)。

 

        PendingIntent可以看作是对Intent的包装。供当前App之外的其他App调用。有点被动或是“Callback”的意思,但不是严格意义上的被动或是Callback。总之,当前App不能用它马上启动它所包裹的Intent。而是在外部App执行这个PendingIntent时,间接地、实际地调用里面的IntentPendingIntent主要持有的信息是它所包装的Intent和当前AppContext。正由于PendingIntent中保存有当前AppContext,使它赋予外部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.javastatusBarManagerService.setNotificationCallBack

[systemreadly]

SystemUIService.java----onCreate(); --- for(  SystemUI.start() ) 

 

StatusBar.java --- start() -- registerStatusBar();

mandQueue.java 通过handler 更新ui

通过binder调用

./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();

 

//保存Notification是以Binderkey

 

        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,而viewIndexi对应

 

       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文件中定义的statusbarheight

 

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();//StatusBarstart中实现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 iconview

 

mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);

 

//显示notificationview

 

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等信息的textviewandroid4.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,注意

 

//mContextPhoneStatusBarmContext

 

        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);

 

//设置显示的icon

 

        view.set(icon);

 

//添加到msim_status_bar.xml的保存iconview中去

 

        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;

 

}

 

只有在下面这个类中才正式显示iconstatusbar

 

PhoneStatusBarPolicy.java

 

ContextPhoneStatusBarmContext

 

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);

 

}

 

上面的mServiceStatusBarManager,那么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时会调用StatusBarstart函数,在这里和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就是CommandQueuePhoneStatusbar中的实现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);

 

            }

 

//这才正式创建StatusBarIconiconPackagePhoneStatusBar的,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;

 

         }

 

}

 

}

 

最后就是调用PhoneStatusBaraddIcon。至此,就用StatusBar显示了icon

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值