3、车载应用框架核心:CarAppLibrary 架构、CarService 启动流程、车载应用生命周期
好,我们直接进入正题。这一章讲的是车载应用框架的三大支柱:CarAppLibrary、CarService 和车载应用生命周期。这三块东西,说白了就是你在 Android Automotive OS 上写应用必须搞清楚的底层逻辑。我当年刚接触这个领域时,也踩过不少坑,今天一并讲清楚。
3.1 CarAppLibrary 架构:别重复造轮子
先聊聊 CarAppLibrary。这是 Google 官方提供的一个 Jetpack 库,专门为车载场景设计的。你想想看,普通手机应用和车载应用最大的区别是什么?是交互方式。手机靠触摸,车载靠旋钮、语音、方向盘按键。CarAppLibrary 就是帮你把这些交互统一起来的。
它的核心架构其实不复杂,我画了张图帮你理解:
你看这个分层,CarAppLibrary 处于中间位置。它不直接跟硬件打交道,而是通过 CarService 间接访问车辆数据。这样做的好处是:应用开发者只需要关心 UI 和业务逻辑,不用管底层通信细节。
核心组件速览:
- CarAppService:应用的入口,类似 Activity 但生命周期不同
- Screen:一个屏幕单元,对应一个 UI 页面
- GridTemplate / PaneTemplate:预定义的布局模板,帮你快速搭建界面
- CarNavigation:管理应用内导航,支持返回栈
我个人习惯把 CarAppLibrary 理解成「车载界的 Jetpack Compose」。它帮你处理了大部分跟车载硬件相关的脏活累活。比如旋钮焦点管理,你如果自己写,得监听一堆 KeyEvent,还要处理焦点环的绘制。用 CarAppLibrary,一个 CarNavigation 就搞定了。
3.2 CarService 启动流程:系统的心脏怎么跳动的
接下来聊 CarService。这是 Android Automotive OS 里最核心的系统服务,没有之一。它负责管理所有车辆相关的功能——车速、空调、车门、灯光等等。
它的启动流程,我拆成几个关键阶段:
- SystemServer 启动:Android 系统启动时,SystemServer 进程会加载各种系统服务。CarService 就是其中之一。
- CarServiceHelperService 登场:这是一个辅助服务,负责实例化 CarService。它会在 SystemServer 中运行,但 CarService 本身是一个独立的 APK。
- 绑定 CarService APK:CarServiceHelperService 通过 Intent 绑定到 CarService 的 APK 进程。这里用的是
bindService机制。 - 初始化 Vehicle HAL:CarService 启动后,会连接底层的 Vehicle HAL(硬件抽象层)。这一步如果失败,整个车载功能都会瘫痪。
- 注册系统服务:CarService 将自己注册到 ServiceManager 中,供其他应用调用。
- 发送启动广播:通知所有监听
CarService启动的应用,可以开始干活了。
嗯,这里要注意一个坑:CarService 的启动是异步的。应用不能假设一开机就能拿到 CarService 的引用。我曾经在项目里遇到过一个问题:应用在 onCreate 里直接调用 Car.createCar(),结果返回 null,导致后续所有操作都崩了。后来加了个回调监听才解决。
避坑指南:
我曾经在某个量产项目中,因为 CarService 启动超时导致中控屏黑屏了 10 秒。排查下来发现是 Vehicle HAL 初始化时,某个传感器驱动卡住了。解决方案是给 HAL 初始化加了个超时机制,超时后降级运行。
启动流程的时序图,我画了一个简化版:
3.3 车载应用生命周期:别拿手机那套来套
最后聊生命周期。这是最容易出问题的地方。很多从手机转过来的开发者,上来就用 Activity 的生命周期思维写车载应用,结果各种崩溃。
车载应用的生命周期,跟手机最大的区别在于:车载应用是「服务优先」的。什么意思?你想想看,手机 App 可以随便杀后台,但车载应用不行。导航应用必须一直运行,音乐应用不能因为切到后台就停播。
CarAppLibrary 定义了一套自己的生命周期,核心是 CarAppService:
| 阶段 | 触发条件 | 开发者该做什么 |
|---|---|---|
onCreate |
应用首次启动 | 初始化数据、绑定 CarService |
onStart |
应用可见 | 开始更新 UI、注册监听器 |
onResume |
应用获得焦点 | 处理用户交互 |
onPause |
应用失去焦点 | 暂停非必要的更新 |
onStop |
应用不可见 | 释放资源,但保持核心服务运行 |
onDestroy |
应用被销毁 | 彻底清理 |
你看,跟 Activity 很像对吧?但有一个关键区别:车载应用在后台时,系统不会轻易杀掉它。系统会尽量保持应用进程存活,除非内存实在不够了。
我的经验:
在 onStop 里不要释放跟车辆通信相关的资源。比如车速监听、空调状态监听。这些资源一旦释放,重新获取的成本很高。我见过一个音乐应用,每次切到后台再切回来,都要重新绑定 CarService,导致音乐中断 2-3 秒。用户体验极差。
另外,车载应用还有一个特殊的生命周期状态:「停车模式」。当车辆熄火但系统还没完全关机时,应用会进入这个状态。这时候应用应该保存关键数据,准备随时被杀死。
嗯,这里要特别强调一下:不要依赖 onDestroy 来保存数据。车载系统关机速度很快,有时候根本来不及走完整的生命周期。我建议你在 onPause 或 onStop 时就做持久化保存。
最后总结一下这一章的核心:
- CarAppLibrary 是车载应用的骨架,帮你处理交互和导航
- CarService 是车载系统的发动机,启动流程必须理解清楚
- 生命周期 是车载应用的命脉,别拿手机那套来套
这三块搞明白了,你写车载应用就有了底气。下一块内容,我们聊聊更具体的——怎么用 CarAppLibrary 搭建一个真正的车载界面。