源码网站:http://androidxref.com/9.0.0_r3
可以参照: Android O 8.0 Notification 源码分析(一)
Android O 8.0 Notification 源码分析(二)
1.来电话时发现全屏通知被拦截
拦截原因
1): No Fullscreen intent: suppressed by DND(do not disturb) 被勿扰模式拦截
2).No Fullscreen intent: not important enough 通知优先级不够
2.Fullscreen intent app处理
incallUI发送通知的代码如下
@/packages/apps/Dialer/java/com/android/incallui/StatusBarNotifier.java
private void buildAndSendNotification(
LogUtil.i("StatusBarNotifier.buildAndSendNotification", "notificationType=" + notificationType); //2 log会打印2,表示incallUI发送通知开始
switch (notificationType) {
case NOTIFICATION_INCOMING_CALL: //2
if (BuildCompat.isAtLeastO()) {
builder.setChannelId(NotificationChannelId.INCOMING_CALL); //channel id : INCOMING_CALL
}
// Set the intent as a full screen intent as well if a call is incoming
configureFullScreenIntent(builder, createLaunchPendingIntent(true /* isFullScreen */)); //发送全屏通知
// Set the notification category and bump the priority for incoming calls
builder.setCategory(Notification.CATEGORY_CALL);
// This will be ignored on O+ and handled by the channel
builder.setPriority(Notification.PRIORITY_MAX); //优先级 PRIORITY_MAX
if (currentNotification != NOTIFICATION_INCOMING_CALL) {
LogUtil.i(
"StatusBarNotifier.buildAndSendNotification",
"Canceling old notification so this one can be noisy");
// Moving from a non-interuptive notification (or none) to a noisy one. Cancel the old
// notification (if there is one) so the fullScreenIntent or HUN will show
TelecomAdapter.getInstance().stopForegroundNotification();
}
break;
LogUtil.i(
"StatusBarNotifier.buildAndSendNotification",
"displaying notification for " + notificationType);
// If a notification exists, this will only update it.
TelecomAdapter.getInstance().startForegroundNotification(NOTIFICATION_ID, notification); //notify通知
}
需要设置setFullScreenIntent为true
http://androidxref.com/9.0.0_r3
packages/apps/Dialer/java/com/android/incallui/StatusBarNotifier.java
983 private void configureFullScreenIntent(Notification.Builder builder, PendingIntent intent) {
984 // Ok, we actually want to launch the incoming call
985 // UI at this point (in addition to simply posting a notification
986 // to the status bar). Setting fullScreenIntent will cause
987 // the InCallScreen to be launched immediately *unless* the
988 // current foreground activity is marked as "immersive".
989 LogUtil.d("StatusBarNotifier.configureFullScreenIntent", "setting fullScreenIntent: " + intent);
990 builder.setFullScreenIntent(intent, true);
991 }
3.Framework层收到通知拦截fullScreen Intent
在addNotificationInternal回去拦截,看了几个Android 版本位置都有点差异,不过代码逻辑都是一样的
@/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
743 protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)
744 throws InflationException {
745 if (DEBUG) {
746 Log.d(TAG, "createNotificationViews(notification=" + sbn);
747 }
748 NotificationData.Entry entry = new NotificationData.Entry(sbn);
749 Dependency.get(LeakDetector.class).trackInstance(entry);
750 entry.createIcons(mContext, sbn);
751 // Construct the expanded view.
752 inflateViews(entry, mListContainer.getViewParentForNotification(entry));
753 return entry;
754 }
755
756 private void addNotificationInternal(StatusBarNotification notification,
757 NotificationListenerService.RankingMap ranking) throws InflationException {
758 String key = notification.getKey();
759 if (DEBUG) Log.d(TAG, "addNotification key=" + key);
760
761 mNotificationData.updateRanking(ranking);
762 NotificationData.Entry shadeEntry = createNotificationViews(notification);
763 boolean isHeadsUped = shouldPeek(shadeEntry);
764 if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
765 if (shouldSuppressFullScreenIntent(shadeEntry)) {
766 if (DEBUG) {
767 Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
768 }
769 } else if (mNotificationData.getImportance(key)
770 < NotificationManager.IMPORTANCE_HIGH) {
771 if (DEBUG) {
772 Log.d(TAG, "No Fullscreen intent: not important enough: "
773 + key);
774 }
775 } else {
776 // Stop screensaver if the notification has a fullscreen intent.
777 // (like an incoming phone call)
778 SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
779
780 // not immersive & a fullscreen alert should be shown
781 if (DEBUG)
782 Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
783 try {
784 EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
785 key);
786 notification.getNotification().fullScreenIntent.send();
787 shadeEntry.notifyFullScreenIntentLaunched();
788 mMetricsLogger.count("note_fullscreen", 1);
789 } catch (PendingIntent.CanceledException e) {
790 }
791 }
792 }
793 abortExistingInflation(key);
794
795 mForegroundServiceController.addNotification(notification,
796 mNotificationData.getImportance(key));
797
798 mPendingNotifications.put(key, shadeEntry);
799 mGroupManager.onPendingEntryAdded(shadeEntry);
800 }