PendingIntenthtml
Intent是一個意圖,一個描述了想要啓動一個Activity、Broadcast或是Service的意圖。它主要持有的信息是它想要啓動的組件(Activity、Broadcast或是Service)。java
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。android
參考:http://www.eoeandroid.com/thread-96512-1-1.html數組
NotificationManagerapp
源碼位置:framework/base/core/java/android/app/NotificationManager.java函數
enuqunotificationwithtagui
功能:this
負責「發出」與「取消」 Notification。spa
方法:代理
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進行交互。
1、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);
}
2、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);
}
}
3、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