Android O 8.0 Notification 源码分析(二)

本编文章针对AndroidO 8.0代码讲述。此版本的SystemUI和Notification较之前版本有一些改动。

本编文章讲述展示过程: System Notification --> SystemUI --> Display Notifications。

第一编文章《Android O 8.0 Notification 源码分析(一)》讲述生成过程:

App create Notification ----> System's  NotificationManagerService

此便文章的目的为方便自己回忆和给需要的同学参考下。

还是先把整体流程图贴出来:

咱们直接从StatusBar的start()方法开始,到底SystemUI怎么重启的流程,咱们下回分解。

步骤1,2,3,4,5,5,6,7,8,10,11,13:为SystemUI的Statusbar,Navigationbar,Notificationpanel自定义控件的初始化。

步骤15:初始化NotificationListenerWithPlugins,并且注册:

 
  1. public class NotificationListenerWithPlugins extends NotificationListenerService implements

  2. PluginListener<NotificationListenerController> {

  3. //下面只列出了类中方法名,具体实现自己翻代码。

  4. registerAsSystemService();

  5. unregisterAsSystemService();

  6. getActiveNotifications();

  7. getCurrentRanking();

  8. ...

  9. }

下面在start()方法注册service:

 
  1. // Set up the initial notification state.

  2. try {

  3. mNotificationListener.registerAsSystemService(mContext,

  4. new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),

  5. UserHandle.USER_ALL);

  6. } catch (RemoteException e) {

  7. Log.e(TAG, "Unable to register notification listener", e);

  8. }

下面代码为在destroy()方法中注销service:

 
  1. public void destroy() {

  2. // Begin old BaseStatusBar.destroy().

  3. mContext.unregisterReceiver(mBaseBroadcastReceiver);

  4. try {

  5. mNotificationListener.unregisterAsSystemService();

  6. } catch (RemoteException e) {

  7. // Ignore.

  8. }

  9. }

步骤9,12,14,16,18:为listener的回调方法会调用 

步骤17,19 StatusBar的addNotification(),updateNotification()方法;

 
  1. public void addNotification(StatusBarNotification notification, RankingMap ranking)

  2. throws InflationException {

  3. String key = notification.getKey();

  4. if (DEBUG) Log.d(TAG, "addNotification key=" + key);

  5.  
  6. mNotificationData.updateRanking(ranking);

  7. Entry shadeEntry = createNotificationViews(notification);

  8. ...

  9. //提示方式

  10. }

步骤20,21:

 
  1. protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)

  2. throws InflationException {

  3. NotificationData.Entry entry = new NotificationData.Entry(sbn);

  4. Dependency.get(LeakDetector.class).trackInstance(entry);

  5. entry.createIcons(mContext, sbn);

  6. // Construct the expanded view.

  7. inflateViews(entry, mStackScroller);

  8. return entry;

  9. }

 
  1. protected void inflateViews(Entry entry, ViewGroup parent) {

  2. PackageManager pmUser = getPackageManagerForUser(mContext,

  3. entry.notification.getUser().getIdentifier());

  4.  
  5. final StatusBarNotification sbn = entry.notification;

  6. if (entry.row != null) {

  7. entry.reset();

  8. updateNotification(entry, pmUser, sbn, entry.row);

  9. } else {

  10. new RowInflaterTask().inflate(mContext, parent, entry,

  11. row -> {

  12. bindRow(entry, pmUser, sbn, row);

  13. updateNotification(entry, pmUser, sbn, row);

  14. });

  15. }

  16.  
  17. }

步骤22:使用RowInflaterTask的inflate方法:

 
  1. public void inflate(Context context, ViewGroup parent, NotificationData.Entry entry,

  2. RowInflationFinishedListener listener) {

  3. mListener = listener;

  4. AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);

  5. mEntry = entry;

  6. entry.setInflationTask(this);

  7. inflater.inflate(R.layout.status_bar_notification_row, parent, this);

  8. }

步骤26,27: view加载完后的回调;

 
  1. private void updateNotification(Entry entry, PackageManager pmUser,

  2. StatusBarNotification sbn, ExpandableNotificationRow row) {

  3. ...

  4. row.updateNotification(entry);

  5. }

步骤28:调用ExpandableNotificationRow的方法;

 
  1. public void updateNotification(NotificationData.Entry entry) {

  2. mEntry = entry;

  3. mStatusBarNotification = entry.notification;

  4. mNotificationInflater.inflateNotificationViews();

  5. }

步骤29:调用NotificationInflater的方法;

 
  1. @VisibleForTesting

  2. void inflateNotificationViews(int reInflateFlags) {

  3. if (mRow.isRemoved()) {

  4. // We don't want to reinflate anything for removed notifications. Otherwise views might

  5. // be readded to the stack, leading to leaks. This may happen with low-priority groups

  6. // where the removal of already removed children can lead to a reinflation.

  7. return;

  8. }

  9. StatusBarNotification sbn = mRow.getEntry().notification;

  10. new AsyncInflationTask(sbn, reInflateFlags, mRow, mIsLowPriority,

  11. mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,

  12. mCallback, mRemoteViewClickHandler).execute();

  13. }

步骤30,调用NotificationInflater.AsyncInflationTask的方法;

 
  1. @Override

  2. protected InflationProgress doInBackground(Void... params) {

  3. try {

  4. final Notification.Builder recoveredBuilder

  5. = Notification.Builder.recoverBuilder(mContext,

  6. mSbn.getNotification());

  7. Context packageContext = mSbn.getPackageContext(mContext);

  8. Notification notification = mSbn.getNotification();

  9. if (mIsLowPriority) {

  10. int backgroundColor = mContext.getColor(

  11. R.color.notification_material_background_low_priority_color);

  12. recoveredBuilder.setBackgroundColorHint(backgroundColor);

  13. }

  14. if (notification.isMediaNotification()) {

  15. MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,

  16. packageContext);

  17. processor.setIsLowPriority(mIsLowPriority);

  18. processor.processNotification(notification, recoveredBuilder);

  19. }

  20. return createRemoteViews(mReInflateFlags,

  21. recoveredBuilder, mIsLowPriority, mIsChildInGroup,

  22. mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,

  23. packageContext);

  24. } catch (Exception e) {

  25. mError = e;

  26. return null;

  27. }

  28. }

  29.  
  30. @Override

  31. protected void onPostExecute(InflationProgress result) {

  32. if (mError == null) {

  33. mCancellationSignal = apply(result, mReInflateFlags, mRow, mRedactAmbient,

  34. mRemoteViewClickHandler, this);

  35. } else {

  36. handleError(mError);

  37. }

  38. }

步骤32-38:生成RemoteView;

 
  1. private static InflationProgress createRemoteViews(int reInflateFlags,

  2. Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,

  3. boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,

  4. Context packageContext) {

  5. InflationProgress result = new InflationProgress();

  6. isLowPriority = isLowPriority && !isChildInGroup;

  7. if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {

  8. result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);

  9. }

  10.  
  11. if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {

  12. result.newExpandedView = createExpandedView(builder, isLowPriority);

  13. }

  14.  
  15. if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {

  16. result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);

  17. }

  18.  
  19. if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {

  20. result.newPublicView = builder.makePublicContentView();

  21. }

  22.  
  23. if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {

  24. result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()

  25. : builder.makeAmbientNotification();

  26. }

  27. result.packageContext = packageContext;

  28. return result;

  29. }

还有apply的方法:

 
  1. public static CancellationSignal apply(InflationProgress result, int reInflateFlags,

  2. ExpandableNotificationRow row, boolean redactAmbient,

  3. RemoteViews.OnClickHandler remoteViewClickHandler,

  4. @Nullable InflationCallback callback) {

  5. NotificationData.Entry entry = row.getEntry();

  6. NotificationContentView privateLayout = row.getPrivateLayout();

  7. NotificationContentView publicLayout = row.getPublicLayout();

  8. final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>();

  9.  
  10. int flag = FLAG_REINFLATE_CONTENT_VIEW;

  11. if ((reInflateFlags & flag) != 0) {

  12. boolean isNewView = !canReapplyRemoteView(result.newContentView, entry.cachedContentView);

  13. ApplyCallback applyCallback = new ApplyCallback() {

  14. @Override

  15. public void setResultView(View v) {

  16. result.inflatedContentView = v;

  17. }

  18.  
  19. @Override

  20. public RemoteViews getRemoteView() {

  21. return result.newContentView;

  22. }

  23. };

  24. applyRemoteView(result, reInflateFlags, flag, row, redactAmbient,

  25. isNewView, remoteViewClickHandler, callback, entry, privateLayout,

  26. privateLayout.getContractedChild(), privateLayout.getVisibleWrapper(

  27. NotificationContentView.VISIBLE_TYPE_CONTRACTED),

  28. runningInflations, applyCallback);

  29. }

  30.  
  31. flag = FLAG_REINFLATE_EXPANDED_VIEW;

  32. if ((reInflateFlags & flag) != 0) {

  33. if (result.newExpandedView != null) {

  34. boolean isNewView = !canReapplyRemoteView(result.newExpandedView,

  35. entry.cachedBigContentView);

  36. ApplyCallback applyCallback = new ApplyCallback() {

  37. @Override

  38. public void setResultView(View v) {

  39. result.inflatedExpandedView = v;

  40. }

  41.  
  42. @Override

  43. public RemoteViews getRemoteView() {

  44. return result.newExpandedView;

  45. }

  46. };

  47. applyRemoteView(result, reInflateFlags, flag, row,

  48. redactAmbient, isNewView, remoteViewClickHandler, callback, entry,

  49. privateLayout, privateLayout.getExpandedChild(),

  50. privateLayout.getVisibleWrapper(

  51. NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,

  52. applyCallback);

  53. }

  54. }

  55.  
  56. flag = FLAG_REINFLATE_HEADS_UP_VIEW;

  57. if ((reInflateFlags & flag) != 0) {

  58. if (result.newHeadsUpView != null) {

  59. boolean isNewView = !canReapplyRemoteView(result.newHeadsUpView,

  60. entry.cachedHeadsUpContentView);

  61. ApplyCallback applyCallback = new ApplyCallback() {

  62. @Override

  63. public void setResultView(View v) {

  64. result.inflatedHeadsUpView = v;

  65. }

  66.  
  67. @Override

  68. public RemoteViews getRemoteView() {

  69. return result.newHeadsUpView;

  70. }

  71. };

  72. applyRemoteView(result, reInflateFlags, flag, row,

  73. redactAmbient, isNewView, remoteViewClickHandler, callback, entry,

  74. privateLayout, privateLayout.getHeadsUpChild(),

  75. privateLayout.getVisibleWrapper(

  76. NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations,

  77. applyCallback);

  78. }

  79. }

  80.  
  81. flag = FLAG_REINFLATE_PUBLIC_VIEW;

  82. if ((reInflateFlags & flag) != 0) {

  83. boolean isNewView = !canReapplyRemoteView(result.newPublicView,

  84. entry.cachedPublicContentView);

  85. ApplyCallback applyCallback = new ApplyCallback() {

  86. @Override

  87. public void setResultView(View v) {

  88. result.inflatedPublicView = v;

  89. }

  90.  
  91. @Override

  92. public RemoteViews getRemoteView() {

  93. return result.newPublicView;

  94. }

  95. };

  96. applyRemoteView(result, reInflateFlags, flag, row,

  97. redactAmbient, isNewView, remoteViewClickHandler, callback, entry,

  98. publicLayout, publicLayout.getContractedChild(),

  99. publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),

  100. runningInflations, applyCallback);

  101. }

  102.  
  103. flag = FLAG_REINFLATE_AMBIENT_VIEW;

  104. if ((reInflateFlags & flag) != 0) {

  105. NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout;

  106. boolean isNewView = !canReapplyAmbient(row, redactAmbient) ||

  107. !canReapplyRemoteView(result.newAmbientView, entry.cachedAmbientContentView);

  108. ApplyCallback applyCallback = new ApplyCallback() {

  109. @Override

  110. public void setResultView(View v) {

  111. result.inflatedAmbientView = v;

  112. }

  113.  
  114. @Override

  115. public RemoteViews getRemoteView() {

  116. return result.newAmbientView;

  117. }

  118. };

  119. applyRemoteView(result, reInflateFlags, flag, row,

  120. redactAmbient, isNewView, remoteViewClickHandler, callback, entry,

  121. newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper(

  122. NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations,

  123. applyCallback);

  124. }

  125.  
  126. // Let's try to finish, maybe nobody is even inflating anything

  127. finishIfDone(result, reInflateFlags, runningInflations, callback, row,

  128. redactAmbient);

  129. CancellationSignal cancellationSignal = new CancellationSignal();

  130. cancellationSignal.setOnCancelListener(

  131. () -> runningInflations.values().forEach(CancellationSignal::cancel));

  132. return cancellationSignal;

  133. }

好了,以上为大部分流程。有不对的地方欢迎指正。

上编文章讲述了Notificaion从Apps端发送到系统中的流程。
《Android O 8.0 Notification 源码分析(一)》

原文地址:https://blog.csdn.net/yangzs516/article/details/81490670

猜你喜欢

转载自blog.csdn.net/f2006116/article/details/82145862