状态栏其他应用发送消息显示流程总结

以DeskClock为例:
public static void showAlarmNotification(Context context, AlarmInstance instance) {

Notification.Builder notification = new Notification.Builder(context)//构建Notification
.setContentTitle(resources.getText(R.string.menu_alarm)/instance.getLabelOrDefault(context)/)
.setContentText(AlarmUtils.getFormattedTime(context, instance.getAlarmTime()))
.setSmallIcon(R.drawable.stat_notify_alarm)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.alarm_icon_notification))
.setOngoing(true)
.setAutoCancel(false)
.setDefaults(Notification.DEFAULT_LIGHTS)
.setWhen(0);

    // Setup Snooze Action
    Intent snoozeIntent = AlarmStateManager.createStateChangeIntent(context, "SNOOZE_TAG",
            instance, AlarmInstance.SNOOZE_STATE);
    PendingIntent snoozePendingIntent = PendingIntent.getBroadcast(context, instance.hashCode(),
            snoozeIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    notification.addAction(0/*R.drawable.stat_notify_alarm*/,
            resources.getString(R.string.alarm_alert_snooze_text), snoozePendingIntent);
    ...
    nm.cancel(instance.hashCode());
    nm.notify(instance.hashCode(), notification.build());//发送此通知
}

—>nm为NotificationManager对象,调用NotificationManager.notify

—>public void notify(String tag, int id, Notification notification)
{

try {
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
notification, idOut, UserHandle.myUserId());
if (id != idOut[0]) {
Log.w(TAG, “notify: id corrupted: sent ” + id + “, got back ” + idOut[0]);
}
} catch (RemoteException e) {
}
}

—>service为NotificationManagerService对象

—>public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
Notification notification, int[] idOut, int userId)
{
enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(), Binder.getCallingPid(),
tag, id, notification, idOut, userId);
}

—>public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
int[] idOut, int incomingUserId)
{
….
mHandler.post(new Runnable() {
@Override
public void run() {
….
synchronized (mNotificationList) {//同步锁
final StatusBarNotification n = new StatusBarNotification(
pkg, id, tag, callingUid, callingPid, score, notification, user);
NotificationRecord r = new NotificationRecord(n);
NotificationRecord old = null;

                int index = indexOfNotificationLocked(pkg, tag, id, userId);
                if (index < 0) {//消息列表添加新发的消息
                    mNotificationList.add(r);
                } else {//旧消息列表更新
                    old = mNotificationList.remove(index);
                    mNotificationList.add(index, r);
                    // Make sure we don't lose the foreground service state.
                    if (old != null) {
                        notification.flags |=
                            old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;

                        /// M: [ALPS01233835] Reuse old notification time to prevent notifications from jumping
                        notification.when = old.getNotification().when;
                    }
                }

                ........

                if (notification.icon != 0
                    /// M: Do not show notifications if FLAG_HIDE_NOTIFICATION is on
                    && (notification.flags & Notification.FLAG_HIDE_NOTIFICATION) == 0) {
                    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 {
                        long identity = Binder.clearCallingIdentity();
                        try {
                            r.statusBarKey = mStatusBar.addNotification(n);//表示新发的消息
                            if ((n.getNotification().flags & Notification.FLAG_SHOW_LIGHTS) != 0
                                    && canInterrupt) {
                                /*led patch start */
                                //mAttentionLight.pulse();
                                /*led patch end */
                            }
                        }
                        finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    }
                    // Send accessibility events only for the current user.
                    if (currentUser == userId) {
                        sendAccessibilityEvent(notification, pkg);
                    }

                    notifyPostedLocked(r);
                } else {
                    Slog.e(TAG, "Not posting notification with icon==0: " + notification);
                    if (old != null && old.statusBarKey != null) {
                        long identity = Binder.clearCallingIdentity();
                        try {
                            mStatusBar.removeNotification(old.statusBarKey);
                        }
                        finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                        notifyRemovedLocked(r);
                    }
                    // ATTENTION: in a future release we will bail out here
                    // so that we do not play sounds, show lights, etc. for invalid notifications
                    Slog.e(TAG, "WARNING: In a future release this will crash the app: "
                            + n.getPackageName());
                }
                ......
    });
...
}

—>先看新消息的添加mStatusBar.addNotification(n)
—>mStatusBar为StatusBarManagerService类型
—->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(很熟悉,即在registerStatusBar方法时赋值mBar = bar;即BaseStatusBar中创建的CommandQueue对象)

—>跳至PhoneStatusBar中的
public void addNotification(IBinder key, StatusBarNotification notification) {
if (DEBUG) Log.d(TAG, “addNotification score=” + notification.getScore());
Entry shadeEntry = createNotificationViews(key, notification);
if (shadeEntry == null) {
return;
}
/// M: [ALPS00512845] Handle SD Swap Condition.
if (SUPPORT_SD_SWAP) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(notification.getPackageName(), 0);
if ((applicationInfo.flags & applicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
if (mAvoidSDAppAddNotification) {
return;
}
if (!mNeedRemoveKeys.contains(key)) {
mNeedRemoveKeys.add(key);
}
Log.d(TAG, “addNotification, applicationInfo pkg = ” + notification.getPackageName() + ” to remove notification key = ” + key);
}
} catch (NameNotFoundException e1) {
e1.printStackTrace();
}
}

                ........

                addNotificationViews(shadeEntry);

                // Recalculate the position of the sliding windows and the titles.
                setAreThereNotifications();
                updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
            }

—>首先调用父类BaseStatusBar中的createNotificationViews方法:
protected NotificationData.Entry createNotificationViews(IBinder key,
StatusBarNotification notification) {

// Construct the expanded view.
NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
if (!inflateViews(entry, mPile)) {
handleNotificationError(key, notification, “Couldn’t expand RemoteViews for: ”
+ notification);
return null;
}
return entry;
}
—>判断条件中执行inflateViews(entry, mPile)

—>public boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
int minHeight =
mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height);
int maxHeight =
mContext.getResources().getDimensionPixelSize(R.dimen.notification_max_height);
StatusBarNotification sbn = entry.notification;
RemoteViews contentView = sbn.getNotification().contentView;
RemoteViews bigContentView = sbn.getNotification().bigContentView;
if (contentView == null) {
return false;
}

    // create the row view
    LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
            Context.LAYOUT_INFLATER_SERVICE);
    ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
            R.layout.status_bar_notification_row, parent, false);

    .....

    entry.row = row;
    entry.row.setRowHeight(mRowHeight);
    entry.content = content;
    entry.expanded = contentViewLocal;
    entry.setBigContentView(bigContentViewLocal);

    /// M: Support SIM Info Notification.
    updateNotificationSimInfo(entry);

    return true;
}

—>entry.row = row;(ExpandableNotificationRow)

—>往下会调用BaseStatusBar中的addNotificationViews方法:

—>protected void addNotificationViews(NotificationData.Entry entry) {
// Add the expanded view and icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
Log.d(TAG, “addNotificationViews: added at ” + pos);
}
updateExpansionStates();
updateNotificationIcons();
}

—>updateNotificationIcons()抽象方法又在其子类PhoneStatusBar中实现

—>@Override
protected void updateNotificationIcons() {
if (mNotificationIcons == null) return;
Log.i(“zyl break”,”PhoneStatusBar–updateNotificationIcons()———————>done”);
loadNotificationShade();
}
—>loadNotificationShade()方法:
—>private void loadNotificationShade() {

            for (int i=0; i<N; i++) {
                    Entry ent = mNotificationData.get(N-i-1);
                    if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
                    if (!notificationIsForCurrentUser(ent.notification)) continue;
                    toShow.add(ent.row);//expanded view
                }
                ...
                for (int i=0; i<toShow.size(); i++) {
                    View v = toShow.get(i);
                    if (v.getParent() == null) {
                        mPile.addView(v, i);
                    }
                }
            }

—>mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems);即下拉状态栏布局中的消息通知
//04.19:
——>PhoneStatusBar:
updateNotificationShade(
for (int i=0; i< toShow.size(); i++) {
View v = toShow.get(i);
if (v.getParent() == null) {
mStackScroller.addView(v);
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值