SystemUI

发布于:2025-06-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、SystemUI的介绍

SystemUI是Android操作系统中的一个关键系统级应用,负责管理和提供用户界面的核心元素,

主要包括:StatusBar(状态栏)、NavigationBar(导航栏)与Notification Panel(通知栏),以及Notification Panel(通知面板)等,另外在Android8.0代码中,Keyguard(锁屏)模块已经从外部被合并到SystemUI源码目录下。

关于Android13的架构层级如下:

 1、状态栏:StatusBar是Android SystemUI的核心组件之一,位于屏幕顶部。它显示了通知图标、系统图标(如电池、信号强度、时间等)以及其他与系统状态相关的信息。

2、导航栏:NavigationBar是位于屏幕底部的导航界面,提供了返回、主页和最近任务等导航操作的按钮。它使用户能够浏览应用程序和系统功能,如切换应用、返回主屏幕等。

3、通知栏:Notification Shade是一个可下拉的面板,用户可以从任何屏幕位置向下滑动以展开它。它显示了来自各个应用程序的通知,并提供一些快速设置选项,如Wi-Fi、蓝牙、飞行模式等。

4、快捷控制:Quick Settings是通知面板中的一部分,提供了一组常用的系统设置选项,用户可以通过快速切换按钮打开或关闭这些选项,例如调整屏幕亮度、打开/关闭无线网络等。

以下是Android SystemUI的主要功能的介绍:

二、启动流程

SystemUI 的启动本质是 ​​SystemServer 进程初始化系统服务的一部分​​,其核心流程可分为以下阶段(以 Android 13 为例):

1、SystemServer 启动​:Android 系统启动时,init 进程启动 system_server 进程(SystemServer.java)。

2、加载系统服务配置​:读取 /system/etc/systemui/config.xml 等配置文件,确定需要启动的 SystemUI 模块。

3、初始化核心服务​:启动 StatusBarManagerServiceNavigationBarManagerService 等关键服务。

4、启动 SystemUI 应用​:通过 ActivityThread 启动 SystemUIApplication,加载状态栏、导航栏等界面组件。

5、绑定服务与交互​:SystemUI 与应用层通过 Binder通信(如状态栏颜色修改、通知推送)。

关键代码流程(基于AOSP源码):

1、SystemUI 的启动入口在 SystemServer.javamain() 方法中。系统启动时,init 进程调用 system_server 的 main() 方法,启动系统服务。

AOSP 源码(frameworks/base/services/java/com/android/server/SystemServer.java):

public static void main(String[] args) {
    new SystemServer().run();
}
private void run() {
    // ... 系统初始化(如时间、电源管理)
    startBootstrapServices(); // 启动引导服务(如 ActivityManagerService)
    startCoreServices();      // 启动核心服务(如 PackageManagerService)
    startOtherServices();     // 启动其他服务(包括 SystemUI)
    // ...
}
private void startOtherServices() {
    // ... 其他服务启动
    mSystemServiceManager.startService(StatusBarManagerService.class); // 启动状态栏服务
    mSystemServiceManager.startService(NavigationBarManagerService.class); // 启动导航栏服务
    // ...
    startSystemUi(); // 显式启动 SystemUI 应用
}

关键方法 startSystemUi()(Android 10+):

private void startSystemUi() {
    // 通过 ActivityManagerService 启动 SystemUI 的主 Activity
    Intent intent = new Intent();
    intent.setComponent(new ComponentName(
        "com.android.systemui", 
        "com.android.systemui.SystemUIApplication"
    ));
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    mSystemServiceManager.startService(intent); // 实际调用 AMS 启动应用
}

2、SystemUIApplication 初始化(Android 8.0+)

SystemUIApplication 是 SystemUI 应用的入口类,负责初始化界面组件(状态栏、导航栏等)并绑定服务。

AOSP 源码(frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java):

public class SystemUIApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化系统 UI 核心组件
        initSystemUI();
    }
    private void initSystemUI() {
        // 加载配置(如状态栏图标、导航栏布局)
        Resources res = getResources();
        boolean hasNavigationBar = res.getBoolean(R.bool.config_showNavigationBar);
        // 初始化状态栏
        mStatusBar = new StatusBar(this);
        mStatusBar.init(); // 初始化状态栏视图和逻辑
        // 初始化导航栏(如果设备支持)
        if (hasNavigationBar) {
            mNavigationBar = new NavigationBar(this);
            mNavigationBar.init();
        }
        // 绑定通知管理服务
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.addNotificationListener(mNotificationListener, null, USER_ALL);
    }
}

3、状态栏服务启动(Android 5.0~Android 13)

StatusBarManagerService 是管理系统栏的核心服务,负责处理状态栏的显示/隐藏、图标更新等逻辑。

AOSP 源码(frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java):

public class StatusBarManagerService extends IStatusBarManager.Stub {
    private StatusBarManager mStatusBarManager;
    @Override
    public void setStatusBarColor(int color, int statusBarIconBrightness) {
        // 调用本地方法更新状态栏颜色和图标亮度
        nativeSetStatusBarColor(color, statusBarIconBrightness);
    }
    private native void nativeSetStatusBarColor(int color, int brightness);
}
系统服务注册(Android 7.0+):
// 在 SystemServer 的 startCoreServices() 中注册
mSystemServiceManager.startService(StatusBarManagerService.class);

三、SystemUI核心功能实现

1、状态栏(StatusBar)控制

示例:修改状态栏颜色与图标

public class StatusBarUtils {
    public static void setStatusBarColor(Activity activity, int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(color);
            // 设置状态栏图标颜色(深色背景用白色图标)
            int flags = window.getDecorView().getSystemUiVisibility();
            if (isLightStatusBar(activity)) {
                flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
            window.getDecorView().setSystemUiVisibility(flags);
        }
    }
    private static boolean isLightStatusBar(Activity activity) {
        Drawable background = activity.getWindow().getDecorView().getBackground();
        if (background instanceof ColorDrawable) {
            int color = ((ColorDrawable) background).getColor();
            return Color.red(color) > 128 && Color.green(color) > 128 && Color.blue(color) > 128;
        }
        return false;
    }
}

2、隐藏系统栏(沉浸式模式)

public class FullscreenActivity extends AppCompatActivity {
    private View mDecorView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fullscreen);
        mDecorView = getWindow().getDecorView();
        hideSystemUI();
    }
    private void hideSystemUI() {
        int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        mDecorView.setSystemUiVisibility(flags);
    }
    @Override
    public void onWindowFocusChangeListener(boolean hasFocus) {
        if (hasFocus) hideSystemUI();
    }
}

3、监听系统UI可见性变化

mDecorView.setOnSystemUiVisibilityChangeListener(visibility -> {
    if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
        // 状态栏/导航栏显示
        Log.d("SystemUI", "System bars are visible");
    } else {
        // 系统栏隐藏
        Log.d("SystemUI", "System bars are hidden");
    }
});

四、不同安卓版本之间的差异

1、Android 5.0(Lollipop)~ Android 7.1(Nougat)

状态栏与导航栏​​:引入沉浸式模式(SYSTEMUIFLAG_IMMERSIVE),但边缘滑动触发系统栏显示的逻辑尚未完善。通知栏使用传统布局(NotificationCompat),不支持动态布局。

代码差异​​:

// Android 5.0+ 设置状态栏透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    getWindow().setStatusBarColor(Color.TRANSPARENT);
}

启动方式​​:SystemUI 作为独立应用启动,通过 ActivityThread 加载 SystemUIApplication

​服务管理​​:状态栏和导航栏服务(StatusBarManagerService、NavigationBarManagerService)直接由 SystemServer 启动。

​代码差异​​:

// Android 5.0 启动 SystemUI 的 Intent
Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(new ComponentName(
    "com.android.systemui", 
    "com.android.systemui.SystemUIApplication"
));

2、Android 8.0(Oreo)~ Android 10(Q)

通知渠道​​:强制要求应用创建通知渠道(NotificationChannel)。

分区存储​​:外部存储访问需适配 Scoped Storage(Android 10+)。

​代码差异​​:

// Android 8.0+ 创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    NotificationChannel channel = new NotificationChannel(
        "channel_id", "Channel Name", NotificationManager.IMPORTANCE_DEFAULT);
    channel.setDescription("Channel Description");
    NotificationManager manager = getSystemService(NotificationManager.class);
    manager.createNotificationChannel(channel);
}

模块化增强​​:引入 SystemUIFactory 动态加载模块(如状态栏图标、通知布局)。

服务绑定优化​​:通过 Binder 实现跨进程通信(如应用修改状态栏需调用 StatusBarManager)。

代码差异​​:

// Android 8.0+ 动态加载状态栏模块
public class StatusBarManager {
    public void loadModule(String moduleName) {
        // 从 /system/lib/systemui/ 加载模块 APK
        System.loadLibrary(moduleName);
    }
}

3、Android 11(R)~ Android 13(Tiramisu)

​作用域存储​​:Scoped Storage 强制生效,外部存储访问需使用 Storage Access Framework

沉浸式模式增强​​:支持边缘到边缘(Edge-to-Edge)显示,需配合 WindowInsetsController。引入 WindowInsetsController 替代 View.setSystemUiVisibility()

​代码差异​​:

// Android 11+ 边缘到边缘适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    WindowInsetsController controller = getWindow().getInsetsController();
    controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
    getWindow().setDecorFitsSystemWindows(false);
}else {
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}

4、Android 14(Upside Down Cake)

状态栏图标架构重构​​:引入 ​​Pipeline 架构​​,将状态栏图标分为数据层、域层、UI 层(搜索结果),旧版 NetworkController 被废弃,改用 StatusBarPipelineFlags 控制图标刷新。

​代码差异​​:

// Android 14+ 状态栏图标新架构
StatusBarPipelineFlags flags = new StatusBarPipelineFlags();
if (flags.useMobileIcons()) {
    // 使用新架构加载 Mobile 图标
    MobileIconController mobileIconController = new MobileIconController(context);
    mobileIconController.updateIcon(networkType);
} 

借鉴与有关博客:

systemUI的详细介绍:Android SystemUI(一):图文并茂的介绍 :D-腾讯云开发者社区-腾讯云

systemUI简介以及启动流程:Android 车载应用开发指南 - SystemUI-CSDN博客

修改 systemUI步骤:Android修改 systemui_mob649e81547b8f的技术博客_51CTO博客

systemUI的简介、启动和初始化:Android SystemUI梳理_51CTO博客_android.systemui

systemUI的启动:SystemUI分析 - cascle - 博客园

systemUI的前世今生与主要组件:Android SystemUI篇(一)-CSDN博客