乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android8.1 SystemUI源碼分析之 Notification流程

       印度阿三17 2019-05-31

      代碼流程

      1、先看UI顯示,StatuBar加載 CollapsedStatusBarFragment 替換 status_bar_container(狀態(tài)欄通知顯示區(qū)域)

      SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java

      FragmentHostManager.get(mStatusBarWindow)
                  .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                      CollapsedStatusBarFragment statusBarFragment =
                              (CollapsedStatusBarFragment) fragment;
                      statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
                      mStatusBarView = (PhoneStatusBarView) fragment.getView();
                      mStatusBarView.setBar(this);
                      mStatusBarView.setPanel(mNotificationPanel);
                      mStatusBarView.setScrimController(mScrimController);
                      mStatusBarView.setBouncerShowing(mBouncerShowing);
                      setAreThereNotifications();
                      checkBarModes();
                      /// M: add for plmn display feature @{
                      attachPlmnPlugin();
                      ///@}
                  }).getFragmentManager()
                  .beginTransaction()
                  .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                          CollapsedStatusBarFragment.TAG)
                  .commit();

      statusBarFragment.initNotificationIconArea(mNotificationIconAreaController) 初始化通知欄區(qū)域,這是我們關(guān)心的

      mStatusBarView.setBar(this) 傳遞statusBar處理下拉事件

      mStatusBarView.setPanel(mNotificationPanel) 傳遞 NotificationPanelView 顯示下拉UI控制

      2、跟進 CollapsedStatusBarFragment 中,先看布局文件 status_bar.xml

      1、notification_lights_out---ImageView默認gone
      
      2、status_bar_contents--LinearLayout
      
          notification_icon_area--FrameLayout
      
          system_icon_area--LinearLayout
      
                  system_icons.xml(藍牙、wifi、VPN、網(wǎng)卡、SIM卡信號、飛行模式等) 電池
      
                  clock--Clock.java 
      
      3、emergency_cryptkeeper_text--ViewStub(延遲加載 緊急電話文字)

      這就是我們看到的statusBar的布局,本篇只關(guān)心 notification_icon_area,其它的以后再進行分析。繼續(xù)看到之前的 initNotificationIconArea()

      SystemUI\src\com\android\systemui\statusbar\phone\CollapsedStatusBarFragment.java

      public void initNotificationIconArea(NotificationIconAreaController
              notificationIconAreaController) {
          ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
          mNotificationIconAreaInner =
                  notificationIconAreaController.getNotificationInnerAreaView();
          if (mNotificationIconAreaInner.getParent() != null) {
              ((ViewGroup) mNotificationIconAreaInner.getParent())
                      .removeView(mNotificationIconAreaInner);
          }
          notificationIconArea.addView(mNotificationIconAreaInner);
          // Default to showing until we know otherwise.
          showNotificationIconArea(false);
      }

      獲取到 notification_icon_area,F(xiàn)rameLayout轉(zhuǎn)為ViewGroup,調(diào)用 notificationIconAreaController 獲取通知要顯示的view(LinearLayout),

      如果已經(jīng)有顯示的view,通過 view 父布局將其自身remove,然后再重新addView。最后將 mNotificationIconAreaInner 顯示出來(設(shè)置透明度為1,visibility為VISIBLE)

      可以看到 CollapsedStatusBarFragment 中定義了幾個如下的方法。

       public void hideSystemIconArea(boolean animate) {
          animateHide(mSystemIconArea, animate);
      }
      
      public void showSystemIconArea(boolean animate) {
          animateShow(mSystemIconArea, animate);
      }
      
      public void hideNotificationIconArea(boolean animate) {
          animateHide(mNotificationIconAreaInner, animate);
      }
      
      public void showNotificationIconArea(boolean animate) {
          animateShow(mNotificationIconAreaInner, animate);
      }

      當狀態(tài)欄下拉時,狀態(tài)欄中的圖標icon會慢慢的變成透明和不可見,就是通過hideSystemIconArea(true), hideNotificationIconArea(true)

      3、接下來,我們需要跟進 getNotificationInnerAreaView()方法中看看通知欄icon對應(yīng)的容器

      SystemUI\src\com\android\systemui\statusbar\phone\NotificationIconAreaController.java

      public View getNotificationInnerAreaView() {
          return mNotificationIconArea;
      }
      
      protected void initializeNotificationAreaViews(Context context) {
          reloadDimens(context);
      
          LayoutInflater layoutInflater = LayoutInflater.from(context);
          mNotificationIconArea = inflateIconArea(layoutInflater);
          mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(
                  R.id.notificationIcons);
      
          mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
      }
      
      protected View inflateIconArea(LayoutInflater inflater) {
          return inflater.inflate(R.layout.notification_icon_area, null);
      }
      
      //notification_icon_area.xml
      <com.android.keyguard.AlphaOptimizedLinearLayout
      xmlns:android="http://schemas./apk/res/android"
      android:id="@ id/notification_icon_area_inner"
      android:layout_width="match_parent"
      android:layout_height="match_parent" >
      <com.android.systemui.statusbar.phone.NotificationIconContainer
          android:id="@ id/notificationIcons"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_alignParentStart="true"
          android:gravity="center_vertical"
          android:orientation="horizontal"/>
      </com.android.keyguard.AlphaOptimizedLinearLayout>

      好了,觀察上面的代碼,現(xiàn)在基本上已經(jīng)理清 notification_icon_area 的布局結(jié)構(gòu)了

      notification_icon_area(FrameLayout) 中添加 notification_icon_area_inner(LinearLayout),

      每一個通知對應(yīng)的bean為 NotificationData,創(chuàng)建 Notification 添加到 NotificationIconContainer(FrameLayout)中

      4、緊接著我們就來看下 Notification 的監(jiān)聽加載流程,回到 statusBar 的start()中注冊 NotificationListenerWithPlugins 作為系統(tǒng)service監(jiān)聽通知消息

      try {
              mNotificationListener.registerAsSystemService(mContext,
                      new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
                      UserHandle.USER_ALL);
          } catch (RemoteException e) {
              Log.e(TAG, "Unable to register notification listener", e);
      
          }
      
          private final NotificationListenerWithPlugins mNotificationListener =
              new NotificationListenerWithPlugins() {
          @Override
          public void onListenerConnected() {
              ......  services成功啟動,獲取當前處于活動狀態(tài)的通知(沒被移除的通知),添加到通知欄,此處應(yīng)該是重啟后重新加載
          }
      
          @Override
          public void onNotificationPosted(final StatusBarNotification sbn,
                  final RankingMap rankingMap) {
              ...... 收到通知消息,添加或者修改
              if (isUpdate) {
                  updateNotification(sbn, rankingMap);
              } else {
                  addNotification(sbn, rankingMap);
              }
          }
      
          @Override
          public void onNotificationRemoved(StatusBarNotification sbn,
                  final RankingMap rankingMap) {
              ...... 移除通知消息
              if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
                  final String key = sbn.getKey();
                  mHandler.post(() -> removeNotification(key, rankingMap));
              }
          }
      
          @Override
          public void onNotificationRankingUpdate(final RankingMap rankingMap) {
              ..... 通知的排序優(yōu)先級改變,修改通知位置
              if (rankingMap != null) {
                  RankingMap r = onPluginRankingUpdate(rankingMap);
                  mHandler.post(() -> updateNotificationRanking(r));
              }
          }
      
      };

      繼續(xù)來看下 addNotification()方法

      public void addNotification(StatusBarNotification notification, RankingMap ranking)
              throws InflationException {
          String key = notification.getKey();
          if (true/**DEBUG*/) Log.d(TAG, "addNotification key="   key);
          mNotificationData.updateRanking(ranking);
          Entry shadeEntry = createNotificationViews(notification);
          ......
      }

      可以看到是通過 createNotificationViews()來創(chuàng)建通知 View對象,內(nèi)部繼續(xù)調(diào)用 inflateViews()

      protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)
              throws InflationException {
          if (DEBUG) {
              Log.d(TAG, "createNotificationViews(notification="   sbn);
          }
          NotificationData.Entry entry = new NotificationData.Entry(sbn);
          Dependency.get(LeakDetector.class).trackInstance(entry);
          entry.createIcons(mContext, sbn);
          // Construct the expanded view.
          inflateViews(entry, mStackScroller);
          return entry;
      }
      
      protected void inflateViews(Entry entry, ViewGroup parent) {
          PackageManager pmUser = getPackageManagerForUser(mContext,
                  entry.notification.getUser().getIdentifier());
      
          final StatusBarNotification sbn = entry.notification;
          if (entry.row != null) {
              entry.reset();
              updateNotification(entry, pmUser, sbn, entry.row);
          } else {
              new RowInflaterTask().inflate(mContext, parent, entry,
                      row -> {
                          bindRow(entry, pmUser, sbn, row);
                          updateNotification(entry, pmUser, sbn, row);
                      });
          }
      
      }

      看到上面的方法中,entry在 createNotificationViews 中創(chuàng)建,只賦值了icons, entry.row 為null,進入 RowInflaterTask 中

      SystemUI\src\com\android\systemui\statusbar\notification\RowInflaterTask.java

      public void inflate(Context context, ViewGroup parent, NotificationData.Entry entry,
              RowInflationFinishedListener listener) {
          mListener = listener;
          AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);
          mEntry = entry;
          entry.setInflationTask(this);
          inflater.inflate(R.layout.status_bar_notification_row, parent, this);
      }

      這里我們得到了 Notification 對應(yīng)的layout為 status_bar_notification_row.xml

      回調(diào)方法中將 row 和 entry 綁定,繼續(xù)再調(diào)用 updateNotification(),注意這個方法是四個參數(shù)的,該類中還有重載方法是兩個參數(shù)的。

      private void updateNotification(Entry entry, PackageManager pmUser,
              StatusBarNotification sbn, ExpandableNotificationRow row) {
          .....
      
          entry.row = row;
          entry.row.setOnActivatedListener(this);
      
          boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
                  mNotificationData.getImportance(sbn.getKey()));
          boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight && mPanelExpanded;
          row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
          row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
          row.updateNotification(entry);
      }

      緊接著調(diào)用了 ExpandableNotificationRow的 updateNotification(),內(nèi)部繼續(xù)調(diào)用 NotificationInflater.inflateNotificationViews()

      SystemUI\src\com\android\systemui\statusbar\notification\NotificationInflater.java

      @VisibleForTesting
      void inflateNotificationViews(int reInflateFlags) {
          if (mRow.isRemoved()) {
              // We don't want to reinflate anything for removed notifications. Otherwise views might
              // be readded to the stack, leading to leaks. This may happen with low-priority groups
              // where the removal of already removed children can lead to a reinflation.
              return;
          }
          StatusBarNotification sbn = mRow.getEntry().notification;
          new AsyncInflationTask(sbn, reInflateFlags, mRow, mIsLowPriority,
                  mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
                  mCallback, mRemoteViewClickHandler).execute();
      }

      new AsyncInflationTask().execute();

      @Override
      protected InflationProgress doInBackground(Void... params) {
          try {
              final Notification.Builder recoveredBuilder
                      = Notification.Builder.recoverBuilder(mContext,
                      mSbn.getNotification());
              Context packageContext = mSbn.getPackageContext(mContext);
              Notification notification = mSbn.getNotification();
              if (mIsLowPriority) {
                  int backgroundColor = mContext.getColor(
                          R.color.notification_material_background_low_priority_color);
                  recoveredBuilder.setBackgroundColorHint(backgroundColor);
              }
              if (notification.isMediaNotification()) {
                  MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,
                          packageContext);
                  processor.setIsLowPriority(mIsLowPriority);
                  processor.processNotification(notification, recoveredBuilder);
              }
              return createRemoteViews(mReInflateFlags,
                      recoveredBuilder, mIsLowPriority, mIsChildInGroup,
                      mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
                      packageContext);
          } catch (Exception e) {
              mError = e;
              return null;
          }
      }
      
      @Override
      protected void onPostExecute(InflationProgress result) {
          if (mError == null) {
              mCancellationSignal = apply(result, mReInflateFlags, mRow, mRedactAmbient,
                      mRemoteViewClickHandler, this);
          } else {
              handleError(mError);
          }
      }

      從msbn中獲取 notifaction,判斷是否是媒體類型的通知,進行對應(yīng)的主題背景色修改,通過傳遞的優(yōu)先級設(shè)置通知背景色,繼續(xù)看核心方法 createRemoteViews()

      private static InflationProgress createRemoteViews(int reInflateFlags,
              Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,
              boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
              Context packageContext) {
          InflationProgress result = new InflationProgress();
          isLowPriority = isLowPriority && !isChildInGroup;
          if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
              result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
          }
      
          if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
              result.newExpandedView = createExpandedView(builder, isLowPriority);
          }
      
          if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
              result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
          }
      
          if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
              result.newPublicView = builder.makePublicContentView();
          }
      
          if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
              result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()
                      : builder.makeAmbientNotification();
          }
          result.packageContext = packageContext;
          return result;
      }

      這里就是創(chuàng)建各種布局 CONTENT_VIEW、EXPANDED_VIEW、HEADS_UP_VIEW、PUBLIC_VIEW、AMBIENT_VIEW,

      然后回到 AsyncInflationTask 的 onPostExecute()中執(zhí)行 apply(),代碼太多就不貼了, SystemUI部分的通知流程分析技術(shù),歡迎留言討論。

      statusBar左邊區(qū)域(notification_icon_area)看完了,接下來看下右邊的系統(tǒng)圖標區(qū)域(system_icon_area)

      Android8.1 SystemUI源碼分析之 電池時鐘刷新

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多