Systemui
顶部、底部和左侧显示固定的区域
SystemUI,顾名思义是系统为用户提供的系统级别的信息显示与交互的一套UI组件,所以其功能包罗万象。比如锁屏、状态栏、底部导航栏、最近使用App列表等,大部分功能相互独立,按需启动。在系统源码中,其位置为:frameworks/base/package/SystemUI。尽管从表现形式上看,SystemUI和普通的Android APP有较大的差别,但其本质和普通APP并没有什么差别,也是以apk的形式存在,会被预置再系统指定的目录
1.systemui启动时机
首先先说下android系统启动流程
- 开启电源,执行BootLoader引导程序
- BootLoader拉起并且执行Android操作系统
- 启动Linux内核,加载系统文件init.rc
- 操作系统启动init进程
- init启动zygote进程(创建JVM、注册JNI)
- zygote进程启动虚拟机,启动SystemService进程
- SystemService启动AMS和WMS等各种服务
- AMS里面启动Launcher
Systemui作为系统主要进程,则是在SystemService中启动的
SystemServer.java中关键代码如下
private void run() {
......
// Start services.开启各种Service
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
throw ex;
} finally {
traceEnd();
}
private void startOtherServices() {
......
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, "Making services ready");
traceBeginAndSlog("StartActivityManagerReadyPhase");
......
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
......
}
}
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
//所以我们在做定制Systemui时,只需将包名和类名设置为如下即可
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
2.AndroidMainifest配置
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<!--将App配置为核心App 即最小Framework系统 作用加密机制
当开机检测到系统加密,会把核心App全部启动,并显示UI提示用户输入密码,密码输入正常后,才会启动完整系统-->
coreApp="true"
package="com.android.systemui"
android:sharedUserId="android.uid.system">
<!--常驻App,不会被kill-->
android:persistent="true"
3. SystemUIService中添加window窗口
public class SystemUIService extends BaseService {
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
@Override
public void onCreate() {
super.onCreate();
Log.d("youdianxiaoshuai", "onCreate())");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//这里只是示例加了个顶部状态栏 不同的位置有不同的windowType可以根据自己需求添加
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mLayoutParams = new WindowManager.LayoutParams();
//顶部状态栏 顶部状态栏的windowType
mLayoutParams.type = WindowManager.LayoutParams.TYPE_STATUS_BAR; // 设置window type
// 使窗口支持透明度
mLayoutParams.format = PixelFormat.TRANSPARENT;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mLayoutParams.x = 0;// 以屏幕右上角为原点,设置x、y初始值
mLayoutParams.y = 0;
mLayoutParams.width = 1320;// 设置悬浮窗口长宽数据
mLayoutParams.height = 56;
mLayoutParams.gravity = Gravity.TOP | Gravity.RIGHT;
mLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mLayoutParams.setTitle("StatusBar");
mLayoutParams.packageName = mContext.getPackageName();
//这里的view添加布局文件
mWindowManager.addView(view, mLayoutParams);
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}