9.0 自定义SystemUI下拉状态栏和通知栏视图(十五)之悬浮通知布局
1.前言
在进行9.0的系统rom产品定制化开发中,在9.0中针对systemui下拉状态栏和通知栏的定制UI的工作开发中,原生系统的下拉状态栏和通知栏的视图UI在产品开发中会不太满足功能,
所以根据产品需要来自定义SystemUI的下拉状态栏和通知栏功能,首选实现的就是下拉通知栏左滑删除通知的部分功能,接下来就来实现第十五部分关于实现systemui关于悬浮
通知的相关布局实现
效果图如图:
2. 自定义SystemUI下拉状态栏和通知栏视图(十五)之悬浮通知布局的核心类
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
3.自定义SystemUI下拉状态栏和通知栏视图(十五)之悬浮通知布局的核心功能分析和实现
在9.0的systemui系统中的悬浮通知也是调用的下拉状态栏的相关的悬浮通知来显示悬浮通知的,所以也需要监听系统关于悬浮通知的相关流程,然后
在这里添加自定义的悬浮通知的接口,首先需要实现对悬浮通知的监听
3.1NotificationInflater.java 弹窗类型分析
public class NotificationInflater {public void inflateNotificationViews() {inflateNotificationViews(FLAG_REINFLATE_ALL);}/*** Reinflate all views for the specified flags on a background thread. This is asynchronous and* will notify the callback once it's finished.** @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}* to reinflate all of views.*/@VisibleForTestingvoid 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;AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mRow,mIsLowPriority,mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,mCallback, mRemoteViewClickHandler);if (mCallback != null && mCallback.doInflateSynchronous()) {task.onPostExecute(task.doInBackground());} else {task.execute();}}@VisibleForTestingInflationProgress inflateNotificationViews(int reInflateFlags,Notification.Builder builder, Context packageContext) {InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,mRedactAmbient, packageContext);apply(result, reInflateFlags, mRow, mRedactAmbient, mRemoteViewClickHandler, null);return result;}
通过NotificationInflater.java中的上述几个常量发现那就是通知的几种类型 而弹窗通知具体是由NotificationAlertingManager来管理NotificationAlertingManager 构造函数中给NotificationEntryManager 加 NotificationEntryListener ,
以便在通知视图首次填充(onEntryInflated) 时 感知并弹出悬浮通知。
而在NotificationAlertingManager.java 负责管理弹出悬浮通知,接下来分析下NotificationAlertingManager.java悬浮通知的方法
3.2 NotificationEntryManager.java 弹窗通知分析
public NotificationEntryManager(Context context) {mContext = context;mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);mBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));mMessagingUtil = new NotificationMessagingUtil(context);mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);mGroupManager.setPendingEntries(mPendingNotifications);mFGSExtender.setCallback(key -> removeNotification(key, mLatestRankingMap));}private void addEntry(NotificationData.Entry shadeEntry) {boolean isHeadsUped = shouldPeek(shadeEntry);if (isHeadsUped) {mHeadsUpManager.showNotification(shadeEntry);
+ Log.e("NotificationPanelViewController", "entry:"+ entry.notification);
+ if(shadeEntry.notification!=null)NotificationHelper.getInstance().addAlertNotification(shadeEntry.notification);// Mark as seen immediatelysetNotificationShown(shadeEntry.notification);}addNotificationViews(shadeEntry);mCallback.onNotificationAdded(shadeEntry);}
通过NotificationEntryManager.java上述代码发现
addEntry(NotificationData.Entry shadeEntry) 就是监听悬浮通知的 所以在addEntry(NotificationData.Entry shadeEntry)
就是负责悬浮通知弹窗的相关方法,所以在这里增加自定义的悬浮通知回调方法
NotificationHelper.getInstance().addAlertNotification(shadeEntry.notification);;然后在NotificationPanelView.java中接收自定义悬浮
通知,然后显示悬浮通知
3.3 NotificationPanelView.java关于显示悬浮通知的相关方法
public class NotificationPanelView extends PanelView implements
+ com.android.systemui.notification.NotificationListener,ExpandableView.OnHeightChangedListener,+ private com.android.systemui.notification.NotificationEntry mNotificationEntry;
+ @Override
+ public void addAlertNotification(StatusBarNotification sbn) {
+ Log.e("NotificationPanelViewController", "addAlertNotification:packageName=" + sbn.getPackageName());
+ try {
+ Notification notification = sbn.getNotification();
+ String packageName = sbn.getPackageName();
+ long when = notification.when;
+ Bundle bundle = notification.extras;
+ String title = bundle.getString("android.title");
+ String content = bundle.getString("android.text");
+ Log.e("NotificationPanelViewController", "addAlertNotification-packageName:" + "-----" + packageName+"--notification:"+notification);
+ Log.e("NotificationPanelViewController", "addAlertNotification-tickerText:" + "------" + notification.tickerText);
+ Log.e("NotificationPanelViewController", "addAlertNotification-title:" + "-----" + notification.extras.get("android.title"));
+ Log.e("NotificationPanelViewController", "addAlertNotification-text:" + "-----" + notification.extras.get("android.text"));
+ if(TextUtils.isEmpty(title)&&TextUtils.isEmpty(content))return;
+ PackageManager pm = getContext().getPackageManager();
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ mNotificationEntry = new com.android.systemui.notification.NotificationEntry();
+ mNotificationEntry.setNotification_content(content);
+ mNotificationEntry.setNotification_title(title);
+ mNotificationEntry.setPackageName(packageName);
+ mNotificationEntry.setStatusBarNotification(sbn);
+ if (applicationInfo != null) {
+ mNotificationEntry.setmAppName(pm.getApplicationLabel(applicationInfo).toString());
+ mNotificationEntry.setmAppDrawable(pm.getApplicationIcon(applicationInfo));
+ } else {
+ if (packageName.equals("android")) mNotificationEntry.setmAppName("Android 系统");
+ }
+ mSwipeMeunListView.setVisibility(mBarState == StatusBarState.KEYGUARD?View.GONE:View.VISIBLE);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
在NotificationPanelView.java的上述方法中,通过增加addAlertNotification(StatusBarNotification sbn)接口来实现接收悬浮通知的相关布局
中,添加到显示悬浮通知的列表中,
@@ -2667,12 +2934,23 @@ public class NotificationPanelView extends PanelView implementspublic void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {mNotificationStackScroller.setInHeadsUpPinnedMode(inPinnedMode);if (inPinnedMode) {
+ ArrayList<com.android.systemui.notification.NotificationEntry> alertNotification = new ArrayList<>();
+ if(mNotificationEntry!=null)alertNotification.add(mNotificationEntry);
+ mNFDataAdapter = new NotificationDataAdapter(alertNotification, getContext());
+ mSwipeMeunListView.setAdapter(mNFDataAdapter);mHeadsUpExistenceChangedRunnable.run();updateNotificationTranslucency();} else {setHeadsUpAnimatingAway(true);mNotificationStackScroller.runAfterAnimationFinished(mHeadsUpExistenceChangedRunnable);
+ mKeyguardBottomArea.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mNFDataAdapter = new NotificationDataAdapter(mAllNotification, getContext());
+ mSwipeMeunListView.setAdapter(mNFDataAdapter);
+ }
+ },2000);}}
在NotificationPanelView.java的上述方法中,通过 onHeadsUpPinnedModeChanged(final boolean inPinnedMode)中,根据inPinnedMode的值来判断
当前悬浮通知是否显示和隐藏,当为true时表示悬浮通知弹窗,这时候就更新显示悬浮通知列表,
当inPinnedMode为false 就是悬浮通知消失的时候,这时候也是延时刷新悬浮通知列表,通过上面布局的修改
就可以实现在NotificationPanelView.java中,通过在悬浮通知弹窗的时候,来刷新自定义通知列表来实现功能