android多用户切换时notification的更新
来源:互联网 发布:自主车企实力排名 知乎 编辑:程序博客网 时间:2024/06/06 01:29
描述
General description:
Music displyed in notification bar after switch New user mode to owner user.
Reproducibility:
10/10
Precondition:
Insert SD card with some song.
Add a New user.
Step:
1.Main Menu->switch to new user->music->play a song->drag down notification bar->click owner switch owner user->drag down notification bar
2.Check the phone display.
Actual result:
Music displyed in notification bar after switch New user mode to owner user.
Expect result:
Music should not displyed in notification bar after switch New user mode to owner user.
发现源头
我们需要考虑到Notification属于SystemUI那一部分,实际是SystemUIApplication.java已经有下列定义。
private final Class<?>[] SERVICES = new Class[] { com.android.systemui.tuner.TunerService.class, com.android.systemui.keyguard.KeyguardViewMediator.class, com.android.systemui.recents.Recents.class, com.android.systemui.volume.VolumeUI.class, Divider.class, **com.android.systemui.statusbar.SystemBars.class,** com.android.systemui.usb.StorageNotification.class, com.android.systemui.power.PowerUI.class, com.android.systemui.media.RingtonePlayer.class, com.android.systemui.keyboard.KeyboardUI.class, com.android.systemui.tv.pip.PipUI.class, com.android.systemui.shortcut.ShortcutKeyDispatcher.class };
目前关注于SystemBars这个类,会调用
mStatusBar.start();
PhoneStatusBar.java是BaseStatusBar.java的子类,我们看看它的start方法
@Override public void start() { .... super.start(); .... }很遗憾,又回到了父类BaseStatusBar
public void start() {....mNotificationData = new NotificationData(this);....createAndAddWindows();....} protected abstract void createAndAddWindows();
嗯,这是个抽象的方法,又回到了子类PhoneStatusBar.java,这是一种代码风格吧!
@Override public void createAndAddWindows() { addStatusBarWindow(); } private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = new StatusBarWindowManager(mContext); mRemoteInputController = new RemoteInputController(mStatusBarWindowManager, mHeadsUpManager); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); }
好吧,我编不下去了。我在PhoneStatusbar.java中发现了一段代码
/** * Updates System UI resources that can be skinned */ @Override public void updateSkinnedResources() { if (mNavigationBarView != null) { mNavigationBarView.updateNavigationBarResources(); } mStatusBarView.updateStatusBarResources(); updateSkinnedResourcesForLockscreen(); refreshBrightnessMirror(); }
这是一段ProgressBar更新的UI模块,想必于我前面找到的SERVICES 数组一定是都有这个方法的,
看看 updateSkinnedResourcesForLockscreen();的实现
/** * Updates System UI resources that can be skinned for lockscreen */ private void updateSkinnedResourcesForLockscreen() { final Resources res = mContext.getResources(); // Apply skin resources to bouncer if keyguard is showing. if (mStatusBarKeyguardViewManager != null) { mStatusBarKeyguardViewManager.resetBouncerView(); } // Inform lockscreen it needs to update. SomcLockscreenRuntimeThemeUpdater.newThemeConfiguration(this, (ViewGroup) mStatusBarWindow, res); updateNotificationSkinnedResources(); mIconController.updateSkinnedResources(); mIconController.setIconsDarkKeyguard(mState == StatusBarState.KEYGUARD); ((KeyguardStatusView)mKeyguardStatusView).loadClockPluginView(true); }
根据字面意思的理解,看看updateNotificationSkinnedResources();方法
// all notifications protected NotificationData mNotificationData; private void updateNotificationSkinnedResources() { ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); if (activeNotifications != null) { final int n = activeNotifications.size(); for (int i = 0; i < n; i++) { NotificationData.Entry entry = activeNotifications.get(i); entry.row.updateSkinnedResources(); } } mKeyguardIconOverflowContainer.updateSkinnedResources(); mStackScroller.updateSkinnedResources(); }
在这里ArrayList类型 activeNotifications表明了用户切换后应该显示的Notification,我们看看这个集合是在哪里获取值的,打开NotificationData.java文件
private final ArrayList<Entry> mSortedAndFiltered = new ArrayList<>();public ArrayList<Entry> getActiveNotifications() { return mSortedAndFiltered; }// anything changed, and this class should call back the UI so it updates itself. public void filterAndSort(final boolean filterOutOldNotifications) { mSortedAndFiltered.clear(); resetHideNotificationState(); synchronized (mEntries) { final int N = mEntries.size(); for (int i = 0; i < N; i++) { Entry entry = mEntries.valueAt(i); StatusBarNotification sbn = entry.notification; if (shouldFilterOut(sbn, filterOutOldNotifications)) { continue; } mSortedAndFiltered.add(entry); } } Collections.sort(mSortedAndFiltered, mRankingComparator); }
正如注释所描述的那样,这个类会进行UI回调,说明我们前面的流程是正确的,大家可能会好奇,为什么你一下就走对了,其实我也是打了日志,一步步抓log,编译测试,判断下来的。这里面有个if语句,会对我们的Notification进行一个过滤,看看它的具体实现,可能音乐播放的Notification没有被过滤掉。
boolean shouldFilterOut(StatusBarNotification sbn, final boolean filterOutOldNotifications) { **if (isMediaNotification(sbn)) { // Exit immediately if this is a media notification, we need to keep it! return false; }** if (!(mEnvironment.isDeviceProvisioned() || showNotificationEvenIfUnprovisioned(sbn))) { return true; } if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) { return true; } if (mEnvironment.onSecureLockScreen() && (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET || mEnvironment.shouldHideNotifications(sbn.getUserId()) || mEnvironment.shouldHideNotifications(sbn.getKey()))) { return true; } if (!BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && mGroupManager.isChildInGroupWithSummary(sbn)) { return true; } if (filterOutOldNotifications && (mTimeNotificationsWereLastViewed > sbn.getPostTime())) { mNotificationsHidden = true; return true; } return false; } /** * Return whether there are any clearable notifications (that aren't errors). */ public boolean hasActiveClearableNotifications() { for (Entry e : mSortedAndFiltered) { if (e.getContentView() != null) { // the view successfully inflated if (e.notification.isClearable()) { return true; } } } return false; }
果然,当Notification是媒体类型时直接返回了FALSE,也就是说不过滤掉。不知道是谁改了,只要把这一段代码注释掉就可以了。
/*if (isMediaNotification(sbn)) { // Exit immediately if this is a media notification, we need to keep it! return false; }*/
这是最终的方法,意思就是说,媒体类型不做特殊处理,我根据自己的理解,改成这样,也能通过
if (isMediaNotification(sbn)) { Log.d("elliot_log","ActivityManager.getCurrentUser():"+ActivityManager.getCurrentUser()); Log.d("elliot_log","sbn.getUserId():"+sbn.getUserId()); if(ActivityManager.getCurrentUser()!=sbn.getUserId()){ return true; } return false; }
如果当前用户id不等于Notification所属于的id,则过滤掉。
心得
这个bug让我知道,把原理弄清楚,还是很简单的,没有想象的那么难。
- android多用户切换时notification的更新
- Android N下多用户数据切换的注意事项
- android Notification动态更新
- Mobile Service更新和 Notification Hub 对Android的支持
- android Notification自定义view(view不更新的问题)
- Android多用户模式的特性
- android notification通知栏方式更新APP
- Android 实战-版本更新(okhttp3、service、notification)
- android多用户
- android多用户
- android笔记,点击notification时的跳到栈顶
- Android-Notification的使用
- Android Notification的使用
- android Notification 的使用
- android Notification 的使用
- Android Notification 的使用
- Android-Notification的使用
- android Notification 的使用
- 六种微服务架构的设计模式
- 自动化测试
- 基础知识
- cp: omitting directory ‘sp/’
- Android端 WebP图片压缩与传输的一点探索
- android多用户切换时notification的更新
- PHP判断用户使用手机端登录还是pc端登录(企业版)
- SQLServer找出执行慢的SQL语句
- 图片转Base64并压缩,解压
- CUDA从入门到精通
- cmake 学习
- 【8】Hibernate的事务管理
- 【bzoj3052】糖果公园 树上莫队
- iOS pop至指定页面