• 自定义Systemui(顶部,左侧和底部)


    Systemui

    顶部、底部和左侧显示固定的区域
    蓝色线以外区域即为systemui部分

    SystemUI,顾名思义是系统为用户提供的系统级别的信息显示与交互的一套UI组件,所以其功能包罗万象。比如锁屏、状态栏、底部导航栏、最近使用App列表等,大部分功能相互独立,按需启动。在系统源码中,其位置为:frameworks/base/package/SystemUI。尽管从表现形式上看,SystemUI和普通的Android APP有较大的差别,但其本质和普通APP并没有什么差别,也是以apk的形式存在,会被预置再系统指定的目录

    1.systemui启动时机

    首先先说下android系统启动流程

    1. 开启电源,执行BootLoader引导程序
    2. BootLoader拉起并且执行Android操作系统
    3. 启动Linux内核,加载系统文件init.rc
    4. 操作系统启动init进程
    5. init启动zygote进程(创建JVM、注册JNI)
    6. zygote进程启动虚拟机,启动SystemService进程
    7. SystemService启动AMS和WMS等各种服务
    8. 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();
    }
    
    • 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

    2.AndroidMainifest配置

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    
    android:persistent="true"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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();
        }
    
    }
    
    • 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
  • 相关阅读:
    互联网Java工程师面试题·Java 总结篇·第十弹
    云南白药正在度过“中年危机”
    Linux安装Keepalived
    Docker Daemon
    2.0、C语言数据结构——时间复杂度和空间复杂度 (1)
    Android 14 Beta 1
    Nginx
    “综合”web项目编写------手把手0基础教学(二)
    20220629随笔
    python爬虫之protobuf协议介绍
  • 原文地址:https://blog.csdn.net/qq_44203816/article/details/126488355