我是靠谱客的博主 虚幻月饼,这篇文章主要介绍Android 5.1 SystemUI-状态栏,现在分享给大家,希望可以做个参考。

平台

复制代码
1
2
RK3288 + Android 5.1

SystemUI 启动:

|-- frameworks/base/services/java/com/android/server/SystemServer.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void startOtherServices() { ... mActivityManagerService.systemReady(new Runnable() { @Override public void run() { Slog.i(TAG, "Making services ready"); .... try { startSystemUi(context); } catch (Throwable e) { reportWtf("starting System UI", e); } ... } } static final void startSystemUi(Context context) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.OWNER); }

启动的时间, 是在系统服务ready时候, 这时个WindowManagerService, ActivityManagerService, PackageManagerService等关键的服务已经就绪.

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class SystemUIService extends Service { @Override public void onCreate() { super.onCreate(); //关键代码: ((SystemUIApplication) getApplication()).startServicesIfNeeded(); } @Override public IBinder onBind(Intent intent) { return null; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { SystemUI[] services = ((SystemUIApplication) getApplication()).getServices(); if (args == null || args.length == 0) { for (SystemUI ui: services) { pw.println("dumping service: " + ui.getClass().getName()); ui.dump(fd, pw, args); } } else { String svc = args[0]; for (SystemUI ui: services) { String name = ui.getClass().getName(); if (name.endsWith(svc)) { ui.dump(fd, pw, args); } } } } }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/** * The classes of the stuff to start. */ private final Class<?>[] SERVICES = new Class[] { com.android.systemui.keyguard.KeyguardViewMediator.class, com.android.systemui.recent.Recents.class, com.android.systemui.volume.VolumeUI.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 }; public void startServicesIfNeeded() { if (mServicesStarted) { return; } if (!mBootCompleted) { // check to see if maybe it was already completed long before we began // see ActivityManagerService.finishBooting() if ("1".equals(SystemProperties.get("sys.boot_completed"))) { mBootCompleted = true; if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent"); } } /**----启动 SERVICES 所有的组件:----**/ Log.v(TAG, "Starting SystemUI services."); final int N = SERVICES.length; for (int i=0; i<N; i++) { Class<?> cl = SERVICES[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); try { mServices[i] = (SystemUI)cl.newInstance(); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); mServices[i].start(); if (mBootCompleted) { mServices[i].onBootCompleted(); } } mServicesStarted = true; }

重点关注 com.android.systemui.statusbar.SystemBars.class, 聚焦后面我们研究状态栏.

状态栏 + 导航栏的核心 PhoneStatusBar

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java

复制代码
1
2
3
4
5
6
7
8
9
10
@Override public void start() { if (DEBUG) Log.d(TAG, "start"); mServiceMonitor = new ServiceMonitor(TAG, DEBUG, mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); mServiceMonitor.start(); // will call onNoService if no remote service is found }

因为在公版代码中, 并未设置 BAR_SERVICE_COMPONENT 所以, ServiceMonitor执行start后, 会回调

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Override public void onNoService() { if (DEBUG) Log.d(TAG, "onNoService"); createStatusBarFromConfig(); // fallback to using an in-process implementation } private void createStatusBarFromConfig() { if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); String clsName = mContext.getString(R.string.config_statusBarComponent); /** frameworks/base/packages/SystemUI/res/values/config.xml: <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string> **/ if ("box".equals(SystemProperties.get("ro.target.product", "tablet"))&&!mContext.getResources().getConfiguration().enableMultiWindow()){ clsName = "com.android.systemui.statusbar.tv.TvStatusBar"; } if (clsName == null || clsName.length() == 0) { throw andLog("No status bar component configured", null); } Class<?> cls = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { mStatusBar = (BaseStatusBar) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; mStatusBar.start(); if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName()); }

到此, 终于进入主角: PhoneStatusBar

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void start() {//父类BaseStatusBar的函数 ... mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); mRecents = getComponent(RecentsComponent.class); mRecents.setCallback(this); final Configuration currentConfig = mContext.getResources().getConfiguration(); mLocale = currentConfig.locale; mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale); mFontScale = currentConfig.fontScale; mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext, android.R.interpolator.linear_out_slow_in); mFastOutLinearIn = AnimationUtils.loadInterpolator(mContext, android.R.interpolator.fast_out_linear_in); // Connect in to the status bar manager service StatusBarIconList iconList = new StatusBarIconList(); mCommandQueue = new CommandQueue(this, iconList); ... /** ----添加状态栏----**/ createAndAddWindows(); ... }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); updateDisplaySize(); mScrimSrcModeEnabled = mContext.getResources().getBoolean( R.bool.config_status_bar_scrim_behind_use_src); super.start(); // calls createAndAddWindows() ... // TODO: use MediaSessionManager.SessionListener to hook us up to future updates // in session state /** ----添加导航栏(BACK, HOME, RECENT)----**/ addNavigationBar(); ... } // For small-screen devices (read: phones) that lack hardware navigation buttons private void addNavigationBar() { if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView); if (mNavigationBarView == null) return; prepareNavigationBarView(); mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams()); }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
@Override public void createAndAddWindows() { wm = (WindowManager) mContext.getSystemService( Context.WINDOW_SERVICE); mWallpaperManager = (WallpaperManager) mContext.getSystemService(Context.WALLPAPER_SERVICE); addMultiModeWindow(); addStatusBarWindow(); addHalfScreenWindowController(); if(IS_USE_WHCONTROLS){ addFourScreenWindowController(); } addCenterBtnWindow(); if(ONE_LEVEL_MENU){ addCircleMenuWindow(); } if(IS_USE_BACK_WINDOW){ if(mFourScreenBackWindow == null){ mFourScreenBackWindow = new FourScreenBackWindow(mContext, wm); } } if(mMinWindow == null){ mMinWindow = new MinWindow(mContext, wm); } } private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = new StatusBarWindowManager(mContext); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); } // ================================================================================ // Constructing the view // ================================================================================ protected PhoneStatusBarView makeStatusBarView() { final Context context = mContext; IntentFilter intentfilter=new IntentFilter(); intentfilter.addAction("rk.android.screenshot.SHOW"); intentfilter.addAction("rk.android.screenshot.ACTION"); context.registerReceiver(receiver, intentfilter); IntentFilter winintentfilter=new IntentFilter(); winintentfilter.addAction("rk.android.wintask.SHOW"); winintentfilter.addAction("rk.android.wintask.FINISH"); context.registerReceiver(winreceiver, winintentfilter); IntentFilter packagefilter=new IntentFilter(); packagefilter.addAction(Intent.ACTION_PACKAGE_ADDED); packagefilter.addAction(Intent.ACTION_PACKAGE_REMOVED); packagefilter.addDataScheme("package"); context.registerReceiver(packagereceiver, packagefilter); mContext.registerReceiver(wallpaperReceiver, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED)); Resources res = context.getResources(); updateDisplaySize(); // populates mDisplayMetrics updateResources(); mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size); if(mContext.getResources().getConfiguration().enableMultiWindow()){ mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar_win, null); }else{ mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null); } mStatusBarWindow.mService = this; mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { checkUserAutohide(v, event); if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mExpandedVisible) { animateCollapsePanels(); } } return mStatusBarWindow.onTouchEvent(event); }}); mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); mStatusBarView.setBar(this); PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder); mStatusBarView.setPanelHolder(holder); mAppBarPanel = (AppBarPanelView)mStatusBarWindow.findViewById(R.id.appbar_panel); mAppBarPanel.setStatusBar(this); mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel); mNotificationPanel.setStatusBar(this); if (!ActivityManager.isHighEndGfx()) { mStatusBarWindow.setBackground(null); mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor( R.color.notification_panel_solid_background))); mAppBarPanel.setBackground(new FastColorDrawable(context.getResources().getColor( R.color.notification_panel_solid_background))); } if (ENABLE_HEADS_UP) { if(mContext.getResources().getConfiguration().enableMultiWindow()){ mHeadsUpNotificationView = (HeadsUpNotificationView) View.inflate(context, R.layout.heads_up_win, null); } else { mHeadsUpNotificationView = (HeadsUpNotificationView) View.inflate(context, R.layout.heads_up, null); } mHeadsUpNotificationView.setVisibility(View.GONE); mHeadsUpNotificationView.setBar(this); } if (MULTIUSER_DEBUG) { mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById( R.id.header_debug_info); mNotificationPanelDebugText.setVisibility(View.VISIBLE); } updateShowSearchHoldoff(); try { boolean showNav = mWindowManagerService.hasNavigationBar(); if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav); if (showNav) { //haungjc:win bar if(mContext.getResources().getConfiguration().enableMultiWindow()){ mNavigationBarView = (NavigationBarView) View.inflate(mContext, R.layout.navigation_bar_win, null); }else{ mNavigationBarView = (NavigationBarView) View.inflate(mContext, R.layout.navigation_bar, null); } mNavigationBarView.setDisabledFlags(mDisabled); mNavigationBarView.setBar(this); mNavigationBarView.setOnVerticalChangedListener( new NavigationBarView.OnVerticalChangedListener() { @Override public void onVerticalChanged(boolean isVertical) { if (mSearchPanelView != null) { mSearchPanelView.setHorizontal(isVertical); } mNotificationPanel.setQsScrimEnabled(!isVertical); } }); mNavigationBarView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { checkUserAutohide(v, event); return false; }}); if(mContext.getResources().getConfiguration().enableMultiWindow()){ mNotificationLite = null;//new NotificationCenterLite(mContext); mCalendarDialog = new CalendarDialog(mContext); } } } catch (RemoteException ex) { // no window manager? good luck with that } // figure out which pixel-format to use for the status bar. mPixelFormat = PixelFormat.OPAQUE; mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area); mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons); mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons); mNotificationIconArea = mStatusBarView.findViewById(R.id.notification_icon_area_inner); mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons); mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon); mNotificationIcons.setOverflowIndicator(mMoreIcon); mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents); mSimSwitchNotification = (LinearLayout) mStatusBarView.findViewById( R.id.simSwitchNotification); mSimSwitchNotificationText = (TextView) mStatusBarView.findViewById( R.id.simSwitchNotificationText); mSimSwitchContainer = (LinearLayout) mStatusBarWindow.findViewById( R.id.sim_switch_container); mSim1Container = (LinearLayout)mStatusBarWindow.findViewById(R.id.sim1_container); mSim2Container = (LinearLayout)mStatusBarWindow.findViewById(R.id.sim2_container); mAskContainer = (LinearLayout)mStatusBarWindow.findViewById(R.id.ask_container); mSwitchSim1Button = (ImageView)mStatusBarWindow.findViewById(R.id.sim1_switch_button); mSwitchSim2Button = (ImageView)mStatusBarWindow.findViewById(R.id.sim2_switch_button); mSwitchAskButton = (ImageView)mStatusBarWindow.findViewById(R.id.ask_switch_button); mSwitchSim1Button.setOnClickListener(mSimSwitchListener); mSwitchSim2Button.setOnClickListener(mSimSwitchListener); mSwitchAskButton.setOnClickListener(mSimSwitchListener); mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( R.id.notification_stack_scroller); mStackScroller.setLongPressListener(getNotificationLongClicker()); mStackScroller.setPhoneStatusBar(this); mKeyguardIconOverflowContainer = (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate( R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false); mKeyguardIconOverflowContainer.setOnActivatedListener(this); mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener); mStackScroller.addView(mKeyguardIconOverflowContainer); SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate( R.layout.status_bar_notification_speed_bump, mStackScroller, false); mStackScroller.setSpeedBumpView(speedBump); mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate( R.layout.status_bar_no_notifications, mStackScroller, false); mStackScroller.setEmptyShadeView(mEmptyShadeView); mDismissView = (DismissView) LayoutInflater.from(mContext).inflate( R.layout.status_bar_notification_dismiss_all, mStackScroller, false); mDismissView.setOnButtonClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clearAllNotifications(); } }); mStackScroller.setDismissView(mDismissView); mExpandedContents = mStackScroller; mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop); mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front); mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back); ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind); ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front); mScrimController = new ScrimController(scrimBehind, scrimInFront, mScrimSrcModeEnabled); mScrimController.setBackDropView(mBackdrop); mStatusBarView.setScrimController(mScrimController); mDozeScrimController = new DozeScrimController(mScrimController, context); mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header); mHeader.setActivityStarter(this); mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header); mStatusIconsKeyguard = (LinearLayout) mKeyguardStatusBar.findViewById(R.id.statusIcons); mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view); mKeyguardBottomArea = (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area); mKeyguardBottomArea.setActivityStarter(this); mKeyguardIndicationController = new KeyguardIndicationController(mContext, (KeyguardIndicationTextView) mStatusBarWindow.findViewById( R.id.keyguard_indication_text)); mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController); mTickerEnabled = res.getBoolean(R.bool.enable_ticker); if (mTickerEnabled) { final ViewStub tickerStub = (ViewStub) mStatusBarView.findViewById(R.id.ticker_stub); if (tickerStub != null) { mTickerView = tickerStub.inflate(); mTicker = new MyTicker(context, mStatusBarView); TickerView tickerView = (TickerView) mStatusBarView.findViewById(R.id.tickerText); tickerView.mTicker = mTicker; } } mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore); // set the inital view visibility setAreThereNotifications(); // Background thread for any controllers that need it. mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); // Other icons mLocationController = new LocationControllerImpl(mContext); // will post a notification mBatteryController = new BatteryController(mContext); mBatteryController.setPercentageView((TextView) mStatusBarWindow.findViewById(R.id.battery_percentage)); mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { @Override public void onPowerSaveChanged() { mHandler.post(mCheckBarModes); if (mDozeServiceHost != null) { mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave()); } } @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { // noop } }); mNetworkController = new NetworkControllerImpl(mContext); mHotspotController = new HotspotControllerImpl(mContext); mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper()); mSecurityController = new SecurityControllerImpl(mContext); if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) { mRotationLockController = new RotationLockControllerImpl(mContext); } mUserInfoController = new UserInfoController(mContext); mVolumeComponent = getComponent(VolumeComponent.class); if (mVolumeComponent != null) { mZenModeController = mVolumeComponent.getZenController(); } mCastController = new CastControllerImpl(mContext); final SignalClusterView signalCluster = (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster); final SignalClusterView signalClusterKeyguard = (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster); final SignalClusterView signalClusterQs = (SignalClusterView) mHeader.findViewById(R.id.signal_cluster); mNetworkController.addSignalCluster(signalCluster); mNetworkController.addSignalCluster(signalClusterKeyguard); mNetworkController.addSignalCluster(signalClusterQs); signalCluster.setSecurityController(mSecurityController); signalCluster.setNetworkController(mNetworkController); signalClusterKeyguard.setSecurityController(mSecurityController); signalClusterKeyguard.setNetworkController(mNetworkController); signalClusterQs.setSecurityController(mSecurityController); signalClusterQs.setNetworkController(mNetworkController); if(mContext.getResources().getConfiguration().enableMultiWindow()){ if(signalCluster_win==null&&mNavigationBarView!=null){ mStatusIcons_win = mNavigationBarView.getStatusIcons_win(); signalCluster_win = (SignalClusterView) mNavigationBarView.findViewById(R.id.signal_cluster); mNetworkController.addSignalCluster(signalCluster_win); signalCluster_win.setSecurityController(mSecurityController); signalCluster_win.setNetworkController(mNetworkController); } } final boolean isAPhone = mNetworkController.hasVoiceCallingFeature(); if (isAPhone) { mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() { @Override public void setEmergencyCallsOnly(boolean emergencyOnly) { mHeader.setShowEmergencyCallsOnly(emergencyOnly); } }); } mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label); mShowCarrierInPanel = (mCarrierLabel != null); if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel); if (mShowCarrierInPanel) { mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE); mNetworkController.addCarrierLabel(new NetworkControllerImpl.CarrierLabelListener() { @Override public void setCarrierLabel(String label) { mCarrierLabel.setText(label); if (mNetworkController.hasMobileDataFeature()) { if (TextUtils.isEmpty(label)) { mCarrierLabel.setVisibility(View.GONE); } else { mCarrierLabel.setVisibility(View.VISIBLE); } } } }); } mFlashlightController = new FlashlightController(mContext); mKeyguardBottomArea.setFlashlightController(mFlashlightController); mKeyguardBottomArea.setPhoneStatusBar(this); mAccessibilityController = new AccessibilityController(mContext); mKeyguardBottomArea.setAccessibilityController(mAccessibilityController); mNextAlarmController = new NextAlarmController(mContext); mKeyguardMonitor = new KeyguardMonitor(); if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) { mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor); } mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController); // Set up the quick settings tile panel mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel); if (mQSPanel != null) { final QSTileHost qsh = new QSTileHost(mContext, this, mBluetoothController, mLocationController, mRotationLockController, mNetworkController, mZenModeController, mHotspotController, mCastController, mFlashlightController, mUserSwitcherController, mKeyguardMonitor, mSecurityController); mQSPanel.setHost(qsh); mQSPanel.setTiles(qsh.getTiles()); mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow); mQSPanel.setBrightnessMirror(mBrightnessMirrorController); mHeader.setQSPanel(mQSPanel); qsh.setCallback(new QSTileHost.Callback() { @Override public void onTilesChanged() { mQSPanel.setTiles(qsh.getTiles()); } }); } // User info. Trigger first load. mHeader.setUserInfoController(mUserInfoController); mKeyguardStatusBar.setUserInfoController(mUserInfoController); mUserInfoController.reloadUserInfo(); mHeader.setBatteryController(mBatteryController); ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController( mBatteryController); //AnsonCode hide battery if(!mContext.getResources().getBoolean(R.bool.config_has_battery)){ mStatusBarView.findViewById(R.id.battery).setVisibility(View.GONE); } mKeyguardStatusBar.setBatteryController(mBatteryController); mHeader.setNextAlarmController(mNextAlarmController); PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mBroadcastReceiver.onReceive(mContext, new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF)); // receive broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); if (DEBUG_MEDIA_FAKE_ARTWORK) { filter.addAction("fake_artwork"); } filter.addAction(ACTION_DEMO); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); // listen for USER_SETUP_COMPLETE setting (per-user) resetUserSetupObserver(); startGlyphRasterizeHack(); return mStatusBarView; }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/** * Adds the status bar view to the window manager. * * @param statusBarView The view to add. * @param barHeight The height of the status bar in collapsed state. */ public void add(View statusBarView, int barHeight) { // Now that the status bar window encompasses the sliding panel and its // translucent backdrop, the entire thing is made TRANSLUCENT and is // hardware-accelerated. mLp = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, barHeight, WindowManager.LayoutParams.TYPE_STATUS_BAR, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, PixelFormat.TRANSLUCENT); mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; mLp.gravity = Gravity.TOP; mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; mLp.setTitle("StatusBar"); mLp.packageName = mContext.getPackageName(); mStatusBarView = statusBarView; mBarHeight = barHeight; /**----注释即可不显示 ----**/ mWindowManager.addView(mStatusBarView, mLp); mLpChanged = new WindowManager.LayoutParams(); mLpChanged.copyFrom(mLp); }

状态栏 和导航栏, 通过WindowManager.addView添加并显示.

[扩展]

去除状态栏的方式有
1. 把状态栏高度设置为0;
2. 删除 mWindowManager.addView(mStatusBarView, mLp);

去除HEADS-UP通知显示

在5.0后, android 增加了新的通知提示方式(HEADS-UP), 让用户能在任何界面(即使全屏)不会错过重要通知.

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Notification.Builder builder = new Notification.Builder(this); builder.setContentTitle("通知"); builder.setContentText("横幅提醒"); builder.setDefaults(Notification.DEFAULT_ALL); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)); Intent intent = new Intent(this, EntranceActivity.class); PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0); builder.setContentIntent(pIntent); /**----重点----***/ builder.setFullScreenIntent(pIntent, true); builder.setAutoCancel(true);

setFullScreenIntent 干了什么:

|-- frameworks/base/core/java/android/app/Notification.java

复制代码
1
2
3
4
5
6
7
8
public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { /**---- mFullScreenIntent赋了非空 ----**/ mFullScreenIntent = intent; setFlag(FLAG_HIGH_PRIORITY, highPriority); return this; }

发送通知:

|-- frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
@Override public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id, Notification notification, int[] idOut, int userId) throws RemoteException { enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(), Binder.getCallingPid(), tag, id, notification, idOut, userId); } void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid, final int callingPid, final String tag, final int id, final Notification notification, int[] idOut, int incomingUserId) { if (DBG) { Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); } checkCallerIsSystemOrSameApp(pkg); final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg)); final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg); final int userId = ActivityManager.handleIncomingUser(callingPid, callingUid, incomingUserId, true, false, "enqueueNotification", pkg); final UserHandle user = new UserHandle(userId); // Limit the number of notifications that any given package except the android // package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks. if (!isSystemNotification && !isNotificationFromListener) { synchronized (mNotificationList) { int count = 0; final int N = mNotificationList.size(); for (int i=0; i<N; i++) { final NotificationRecord r = mNotificationList.get(i); if (r.sbn.getPackageName().equals(pkg) && r.sbn.getUserId() == userId) { count++; if (count >= MAX_PACKAGE_NOTIFICATIONS) { Slog.e(TAG, "Package has already posted " + count + " notifications. Not showing more. package=" + pkg); return; } } } } } if (pkg == null || notification == null) { throw new IllegalArgumentException("null not allowed: pkg=" + pkg + " id=" + id + " notification=" + notification); } if (notification.icon != 0) { if (!notification.isValid()) { throw new IllegalArgumentException("Invalid notification (): pkg=" + pkg + " id=" + id + " notification=" + notification); } } mHandler.post(new Runnable() { @Override public void run() { synchronized (mNotificationList) { // === Scoring === // 0. Sanitize inputs notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX); // Migrate notification flags to scores if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) { if (notification.priority < Notification.PRIORITY_MAX) { notification.priority = Notification.PRIORITY_MAX; } } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) { if (notification.priority < Notification.PRIORITY_HIGH) { notification.priority = Notification.PRIORITY_HIGH; } } // 1. initial score: buckets of 10, around the app [-20..20] final int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER; // 2. extract ranking signals from the notification data final StatusBarNotification n = new StatusBarNotification( pkg, opPkg, id, tag, callingUid, callingPid, score, notification, user); NotificationRecord r = new NotificationRecord(n, score); NotificationRecord old = mNotificationsByKey.get(n.getKey()); if (old != null) { // Retain ranking information from previous record r.copyRankingInformation(old); } // Handle grouped notifications and bail out early if we // can to avoid extracting signals. handleGroupedNotificationLocked(r, old, callingUid, callingPid); boolean ignoreNotification = removeUnusedGroupedNotificationLocked(r, old, callingUid, callingPid); // This conditional is a dirty hack to limit the logging done on // behalf of the download manager without affecting other apps. if (!pkg.equals("com.android.providers.downloads") || Log.isLoggable("DownloadManager", Log.VERBOSE)) { int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW; if (ignoreNotification) { enqueueStatus = EVENTLOG_ENQUEUE_STATUS_IGNORED; } else if (old != null) { enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE; } EventLogTags.writeNotificationEnqueue(callingUid, callingPid, pkg, id, tag, userId, notification.toString(), enqueueStatus); } if (ignoreNotification) { return; } mRankingHelper.extractSignals(r); // 3. Apply local rules // blocked apps if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) { if (!isSystemNotification) { r.score = JUNK_SCORE; Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); } } if (r.score < SCORE_DISPLAY_THRESHOLD) { // Notification will be blocked because the score is too low. return; } int index = indexOfNotificationLocked(n.getKey()); if (index < 0) { mNotificationList.add(r); mUsageStats.registerPostedByApp(r); } else { old = mNotificationList.get(index); mNotificationList.set(index, r); mUsageStats.registerUpdatedByApp(r, old); // Make sure we don't lose the foreground service state. notification.flags |= old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE; r.isUpdate = true; } mNotificationsByKey.put(n.getKey(), r); // Ensure if this is a foreground service that the proper additional // flags are set. if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) { notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; } applyZenModeLocked(r); mRankingHelper.sort(mNotificationList); if (notification.icon != 0) { StatusBarNotification oldSbn = (old != null) ? old.sbn : null; mListeners.notifyPostedLocked(n, oldSbn); } else { Slog.e(TAG, "Not posting notification with icon==0: " + notification); if (old != null && !old.isCanceled) { mListeners.notifyRemovedLocked(n); } // ATTENTION: in a future release we will bail out here // so that we do not play sounds, show lights, etc. for invalid // notifications Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName()); } buzzBeepBlinkLocked(r); } } }); idOut[0] = id; } /** * asynchronously notify all listeners about a new notification * * <p> * Also takes care of removing a notification that has been visible to a listener before, * but isn't anymore. */ public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) { // Lazily initialized snapshots of the notification. StatusBarNotification sbnClone = null; StatusBarNotification sbnCloneLight = null; for (final ManagedServiceInfo info : mServices) { boolean sbnVisible = isVisibleToListener(sbn, info); boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false; // This notification hasn't been and still isn't visible -> ignore. if (!oldSbnVisible && !sbnVisible) { continue; } final NotificationRankingUpdate update = makeRankingUpdateLocked(info); // This notification became invisible -> remove the old one. if (oldSbnVisible && !sbnVisible) { final StatusBarNotification oldSbnLightClone = oldSbn.cloneLight(); mHandler.post(new Runnable() { @Override public void run() { notifyRemoved(info, oldSbnLightClone, update); } }); continue; } final int trim = mListeners.getOnNotificationPostedTrim(info); if (trim == TRIM_LIGHT && sbnCloneLight == null) { sbnCloneLight = sbn.cloneLight(); } else if (trim == TRIM_FULL && sbnClone == null) { sbnClone = sbn.clone(); } final StatusBarNotification sbnToPost = (trim == TRIM_FULL) ? sbnClone : sbnCloneLight; mHandler.post(new Runnable() { @Override public void run() { notifyPosted(info, sbnToPost, update); } }); } } private void notifyPosted(final ManagedServiceInfo info, final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) { final INotificationListener listener = (INotificationListener)info.service; StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn); try { listener.onNotificationPosted(sbnHolder, rankingUpdate); } catch (RemoteException ex) { Log.e(TAG, "unable to notify listener (posted): " + listener, ex); } }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**---- 注册监听通知服务 ----**/ public void start() { // Set up the initial notification state. 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); } } |-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java ```java /**---- 注册监听通知服务 ----**/ public void start() { // Set up the initial notification state. 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 NotificationListenerService mNotificationListener = new NotificationListenerService() { @Override public void onListenerConnected() { if (DEBUG) Log.d(TAG, "onListenerConnected"); final StatusBarNotification[] notifications = getActiveNotifications(); final RankingMap currentRanking = getCurrentRanking(); mHandler.post(new Runnable() { @Override public void run() { for (StatusBarNotification sbn : notifications) { addNotification(sbn, currentRanking); } } }); } /**---- 由 NotificationManagerService 调用 ----**/ @Override public void onNotificationPosted(final StatusBarNotification sbn, final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn); mHandler.post(new Runnable() { @Override public void run() { Notification n = sbn.getNotification(); boolean isUpdate = mNotificationData.get(sbn.getKey()) != null || isHeadsUp(sbn.getKey()); // Ignore children of notifications that have a summary, since we're not // going to show them anyway. This is true also when the summary is canceled, // because children are automatically canceled by NoMan in that case. if (n.isGroupChild() && mNotificationData.isGroupWithSummary(sbn.getGroupKey())) { if (DEBUG) { Log.d(TAG, "Ignoring group child due to existing summary: " + sbn); } // Remove existing notification to avoid stale data. if (isUpdate) { removeNotification(sbn.getKey(), rankingMap); } else { mNotificationData.updateRanking(rankingMap); } return; } if (isUpdate) { updateNotification(sbn, rankingMap); } else { addNotification(sbn, rankingMap); } } }); } @Override public void onNotificationRemoved(final StatusBarNotification sbn, final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn); mHandler.post(new Runnable() { @Override public void run() { removeNotification(sbn.getKey(), rankingMap); } }); } @Override public void onNotificationRankingUpdate(final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onRankingUpdate"); mHandler.post(new Runnable() { @Override public void run() { updateNotificationRanking(rankingMap); } }); } };

|-- frameworks/base/core/java/android/service/notification/NotificationListenerService.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/** * Directly register this service with the Notification Manager. * * <p>Only system services may use this call. It will fail for non-system callers. * Apps should ask the user to add their listener in Settings. * * @param context Context required for accessing resources. Since this service isn't * launched as a real Service when using this method, a context has to be passed in. * @param componentName the component that will consume the notification information * @param currentUser the user to use as the stream filter * @hide */ @SystemApi public void registerAsSystemService(Context context, ComponentName componentName, int currentUser) throws RemoteException { mSystemContext = context; if (mWrapper == null) { mWrapper = new INotificationListenerWrapper(); } INotificationManager noMan = getNotificationInterface(); noMan.registerListener(mWrapper, componentName, currentUser); mCurrentUser = currentUser; }

|-- frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** * Register a listener binder directly with the notification manager. * * Only works with system callers. Apps should extend * {@link android.service.notification.NotificationListenerService}. */ @Override public void registerListener(final INotificationListener listener, final ComponentName component, final int userid) { enforceSystemOrSystemUI("INotificationManager.registerListener"); mListeners.registerService(listener, component, userid); }

收到通知后的处理:

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Override public void addNotification(StatusBarNotification notification, RankingMap ranking) { if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey()); if (mUseHeadsUp && shouldInterrupt(notification)) { if (DEBUG) Log.d(TAG, "launching notification in heads up mode"); Entry interruptionCandidate = new Entry(notification, null); ViewGroup holder = mHeadsUpNotificationView.getHolder(); if (inflateViewsForHeadsUp(interruptionCandidate, holder)) { /**---- 只需注释掉, 即可阻止显示HEADS-UP 通知 ---- **/ // 1. Populate mHeadsUpNotificationView mHeadsUpNotificationView.showNotification(interruptionCandidate); // do not show the notification in the shade, yet. return; } } Entry shadeEntry = createNotificationViews(notification); if (shadeEntry == null) { return; } if (notification.getNotification().fullScreenIntent != null) { // Stop screensaver if the notification has a full-screen intent. // (like an incoming phone call) awakenDreams(); // not immersive & a full-screen alert should be shown if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); try { EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, notification.getKey()); notification.getNotification().fullScreenIntent.send(); } catch (PendingIntent.CanceledException e) { } } else { // usual case: status bar visible & not immersive // show the ticker if there isn't already a heads up if (mHeadsUpNotificationView.getEntry() == null) { tick(notification, true); } } addNotificationViews(shadeEntry, ranking); // Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); updateExpandedViewPos(EXPANDED_LEAVE_ALONE); }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
protected boolean shouldInterrupt(StatusBarNotification sbn) { if (mNotificationData.shouldFilterOut(sbn)) { if (DEBUG) { Log.d(TAG, "Skipping HUN check for " + sbn.getKey() + " since it's filtered out."); } return false; } if ((null!=mHeadsUpNotificationView)&&mHeadsUpNotificationView.isSnoozed(sbn.getPackageName())) { return false; } Notification notification = sbn.getNotification(); // some predicates to make the boolean logic legible boolean isNoisy = (notification.defaults & Notification.DEFAULT_SOUND) != 0 || (notification.defaults & Notification.DEFAULT_VIBRATE) != 0 || notification.sound != null || notification.vibrate != null; boolean isHighPriority = sbn.getScore() >= INTERRUPTION_THRESHOLD; /**---- 前面已设置非空 ----**/ boolean isFullscreen = notification.fullScreenIntent != null; boolean hasTicker = mHeadsUpTicker && !TextUtils.isEmpty(notification.tickerText); boolean isAllowed = notification.extras.getInt(Notification.EXTRA_AS_HEADS_UP, Notification.HEADS_UP_ALLOWED) != Notification.HEADS_UP_NEVER; boolean accessibilityForcesLaunch = isFullscreen && mAccessibilityManager.isTouchExplorationEnabled(); if(mContext.getResources().getConfiguration().enableMultiWindow()&&!isFullscreen) isFullscreen = true&&!sbn.isOngoing(); boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker))) && isAllowed && !accessibilityForcesLaunch && mPowerManager.isScreenOn() && (!mStatusBarKeyguardViewManager.isShowing() || mStatusBarKeyguardViewManager.isOccluded()) && !mStatusBarKeyguardViewManager.isInputRestricted(); try { interrupt = interrupt && !mDreamManager.isDreaming(); } catch (RemoteException e) { Log.d(TAG, "failed to query dream manager", e); } if (DEBUG) Log.d(TAG, "interrupt: " + interrupt); return interrupt; }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public boolean showNotification(NotificationData.Entry headsUp) { if (mHeadsUp != null && headsUp != null && !mHeadsUp.key.equals(headsUp.key)) { // bump any previous heads up back to the shade release(); } mHeadsUp = headsUp; if (mContentHolder != null) { mContentHolder.removeAllViews(); } if (mHeadsUp != null) { mMostRecentPackageName = mHeadsUp.notification.getPackageName(); mHeadsUp.row.setSystemExpanded(true); mHeadsUp.row.setSensitive(false); mHeadsUp.row.setHeadsUp(true); mHeadsUp.row.setHideSensitive( false, false /* animated */, 0 /* delay */, 0 /* duration */); if (mContentHolder == null) { // too soon! return false; } mContentHolder.setX(0); mContentHolder.setVisibility(View.VISIBLE); mContentHolder.setAlpha(mMaxAlpha); mContentHolder.addView(mHeadsUp.row); sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); mSwipeHelper.snapChild(mContentHolder, 1f); mStartTouchTime = SystemClock.elapsedRealtime() + mTouchSensitivityDelay; mHeadsUp.setInterruption(); // 2. Animate mHeadsUpNotificationView in mBar.scheduleHeadsUpOpen(); // 3. Set alarm to age the notification off mBar.resetHeadsUpDecayTimer(); } return true; }

通知长按处理

通知VIEW结构:

复制代码
1
2
3
4
5
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java |-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java |-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java ... * N

ExpandableNotificationRow 的父类关系:
ExpandableNotificationRow -> ActivatableNotificationView -> ExpandableOutlineView -> ExpandableView -> FrameLayout

长按事件实际是由NotificationStackScrollLayout处理的:
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java

复制代码
1
2
3
4
5
6
public void setLongPressListener(SwipeHelper.LongPressListener listener) { mSwipeHelper.setLongPressListener(listener); mLongPressListener = listener; }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SwipeHelper.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public void setLongPressListener(LongPressListener listener) { mLongPressListener = listener; } public boolean onInterceptTouchEvent(final MotionEvent ev) { final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: mTouchAboveFalsingThreshold = false; mDragging = false; mLongPressSent = false; mCurrView = mCallback.getChildAtPosition(ev); mVelocityTracker.clear(); if (mCurrView != null) { mCurrAnimView = mCallback.getChildContentView(mCurrView); mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); mVelocityTracker.addMovement(ev); mInitialTouchPos = getPos(ev); if (mLongPressListener != null) { if (mWatchLongPress == null) { mWatchLongPress = new Runnable() { @Override public void run() { if (mCurrView != null && !mLongPressSent) { mLongPressSent = true; mCurrView.sendAccessibilityEvent( AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); mCurrView.getLocationOnScreen(mTmpPos); final int x = (int) ev.getRawX() - mTmpPos[0]; final int y = (int) ev.getRawY() - mTmpPos[1]; mLongPressListener.onLongPress(mCurrView, x, y); } } }; } mHandler.postDelayed(mWatchLongPress, mLongPressTimeout); } } break; ... }

长按的监听由PhoneStatusBar传入:
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected PhoneStatusBarView makeStatusBarView() { final Context context = mContext; IntentFilter intentfilter=new IntentFilter(); intentfilter.addAction("rk.android.screenshot.SHOW"); intentfilter.addAction("rk.android.screenshot.ACTION"); context.registerReceiver(receiver, intentfilter); ... mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( R.id.notification_stack_scroller); mStackScroller.setLongPressListener(getNotificationLongClicker()); mStackScroller.setPhoneStatusBar(this); }

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
protected SwipeHelper.LongPressListener getNotificationLongClicker() { return new SwipeHelper.LongPressListener() { @Override public boolean onLongPress(View v, int x, int y) { /**---- 若不希望处理长按, 则可直接返回结果, 或不注册长按监听即可 ----**/ dismissPopups(); if (!(v instanceof ExpandableNotificationRow)) { return false; } if (v.getWindowToken() == null) { Log.e(TAG, "Trying to show notification guts, but not attached to window"); return false; } inflateGuts((ExpandableNotificationRow) v); // Assume we are a status_bar_notification_row final NotificationGuts guts = (NotificationGuts) v.findViewById( R.id.notification_guts); if (guts == null) { // This view has no guts. Examples are the more card or the dismiss all view return false; } // Already showing? if (guts.getVisibility() == View.VISIBLE) { Log.e(TAG, "Trying to show notification guts, but already visible"); return false; } guts.setVisibility(View.VISIBLE); final double horz = Math.max(guts.getWidth() - x, x); final double vert = Math.max(guts.getActualHeight() - y, y); final float r = (float) Math.hypot(horz, vert); final Animator a = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r); a.setDuration(400); a.setInterpolator(mLinearOutSlowIn); a.start(); mNotificationGutsExposed = guts; return true; } }; }

最后

以上就是虚幻月饼最近收集整理的关于Android 5.1 SystemUI-状态栏的全部内容,更多相关Android内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部