赞
踩
1、初步认识SystemUI
Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,锁屏界面 Keyguard ,电源界面 PowerUI,近期任务界面 Recent Task 等等。对于用户而言,SystemUI 的改动是最能直观感受到的。因此,每个 Android 版本在 SystemUI 上都有比较大的改动。而对开发者而言,理解 Android SystemUI 对优化Android系统界面,改善用户体验十分重要。
2、SystemUI 在哪
在 Andorid 系统源码中,package/apps下放的是系统内置的一些 app,例如 settings,camera,Phone,Message 等等。而在 framework/base/package 下,它们也是系统的 app,SystemUI 就在此目录下。它控制着整个Android系统的界面,但其实他也是一个 app,不同于一般的 app,它不可卸载也不可以被第三方应用替换。因为SystemUI 是系统应用,所以它也是一个 APK,有入口 Application,只不过它是由 SystemServer 进程进行启动的。
3、SystemUI 整体结构
这是 SystemUI 相关类的继承关系图,可以看到 SystemUI 为基类,每个子类实现了不同的系统界面。
Status Bar 系统上方的状态栏
Navigator Bar 系统下方的导航栏
Keyguard 锁屏界面
PowerUI 电源界面
Recents Screen 近期任务界面
VolumeUI 音量调节对话框
Stack Divider 分屏功能调节器
PipUI 画中画界面
Screenshot 截屏界面
RingtonePlayer 铃声播放器界面
Settings Activity 系统设置中用到的一些界面,例如:NetworkOverLimitActivity,UsbDebuggingActivity等。
1、SystemServer进程里面有个main()方法,main 方法如下:
framework/base/service/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
2、main 方法里启动了 run() 方法,而在 run 方法中调用了startOtherServices() 方法:
private void run() { ... // Start services. try { traceBeginAndSlog("StartServices"); startBootstrapServices();//启动引导服务 startCoreServices();//启动核心服务 startOtherServices();//启动其他服务 SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } finally { traceEnd(); } ... }
3、在 startOtherServices() 里 mActivityManagerService.systemReady 创建线程去执行startSystemUi(context),这里将启动SystemUI。具体方法如下:
private void startOtherServices() { mActivityManagerService.systemReady(() -> { ... try { startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } ... } } //启动SystemUI static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui","com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); }
1、然后我们进入设置启动 systemui 程序的 SystemUIService 文件里,该类的onCreate() 方法如下:
framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java.
public class SystemUIService extends Service {
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
}
2、((SystemUIApplication) getApplication()).startServicesIfNeeded()这句很关键,该方法如下:
framework/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
public void startServicesIfNeeded() {
String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
startServicesIfNeeded(names);
}
3、SystemUI要启动的所有组件都是在数组 config_systemUIServiceComponents中定义的,可以看下这个数组的定义:
frameworks/base/packages/SystemUI/res/values/config.xml
<!-- SystemUI Services: The classes of the stuff to start. --> <string-array name="config_systemUIServiceComponents" translatable="false"> <item>com.android.systemui.Dependency</item> <item>com.android.systemui.util.NotificationChannels</item> <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item> <item>com.android.systemui.keyguard.KeyguardViewMediator</item> <item>com.android.systemui.recents.Recents</item> <item>com.android.systemui.volume.VolumeUI</item> <item>com.android.systemui.stackdivider.Divider</item> <item>com.android.systemui.SystemBars</item> <item>com.android.systemui.usb.StorageNotification</item> <item>com.android.systemui.power.PowerUI</item> <item>com.android.systemui.media.RingtonePlayer</item> <item>com.android.systemui.keyboard.KeyboardUI</item> <item>com.android.systemui.pip.PipUI</item> <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item> <item>@string/config_systemUIVendorServiceComponent</item> <item>com.android.systemui.util.leak.GarbageMonitor$Service</item> <item>com.android.systemui.LatencyTester</item> <item>com.android.systemui.globalactions.GlobalActionsComponent</item> <item>com.android.systemui.ScreenDecorations</item> <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item> <item>com.android.systemui.SliceBroadcastRelayHandler</item> </string-array>
4、继续看SystemUIApplication的startServicesIfNeeded(String[] services)方法,其中有一个 for 循环,循环里第一句就是将 service[i] 赋值给 clsName, 而service[i]的赋值就是各个SystemUI组件的具体类对象路径,这里通过反射的方法,创建出来对应的SystemUI组件实例对象:
private void startServicesIfNeeded(String[] services) { ... mServices = new SystemUI[services.length]; ... final int N = services.length; for (int i = 0; i < N; i++) { String clsName = services[i];//具体系统组件类的完整路径 if (DEBUG) Log.d(TAG, "loading: " + clsName); log.traceBegin("StartServices" + clsName); long ti = System.currentTimeMillis(); Class cls; try { cls = Class.forName(clsName); mServices[i] = (SystemUI) cls.newInstance();//通过反射创建实例对象 } catch(ClassNotFoundException ex){ throw new RuntimeException(ex); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = mComponents; ... mServices[i].start(); ... ti = System.currentTimeMillis() - ti; ... if (mBootCompleted) { mServices[i].onBootCompleted(); } } ... mServicesStarted = true; }
看到这里我们应该就明白了,这里是拿到每个和 SystemUI 组件相关的类的完整路径,存到了service[] 里,然后赋值给cls,紧接着通过反射将其转化为具体的类对象,存到了mService[i]数组里,最后对象调start() 方法启动相关类的服务,启动完成后,再调用该类的onBootCompleted( ) 方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。