30、综合项目实战:需求分析、架构设计、功能实现、测试与发布、项目总结

终于到了最后一章。说实话,走到这一步不容易。

前面29章,我们拆解了Android Automotive OS的方方面面。从系统架构到HAL层,从车载应用到OTA升级。但光有知识点还不够,你得把它们串起来。

这一章,我们就拿一个真实项目练手。我管它叫「车载智能助手」——一个集语音控制、车辆状态监测、导航联动于一体的车载应用。嗯,这活儿我一个人干过,踩了不少坑,今天全抖出来给你看。

1. 需求分析:别急着写代码

我见过太多人,拿到需求就开干。结果呢?做到一半发现方向错了。

需求分析,说白了就是搞清楚「做什么」和「为什么做」。对于车载项目,这一点尤其重要。因为车机环境比手机复杂得多——安全、稳定、低延迟,缺一不可。

核心需求清单(MVP版本)

  • 语音唤醒与指令识别:支持「你好,小智」唤醒,识别导航、音乐、空调控制指令
  • 车辆状态显示:实时展示车速、电量、续航里程、胎压
  • 导航联动:接收语音目的地,调用系统导航,并在主界面显示导航信息
  • 多屏适配:支持中控屏(1920x720)和仪表盘(1280x480)
  • 驾驶安全约束:车辆行驶时,限制视频播放和复杂操作

你可能会问:「需求就这么点?」

对,MVP就这么多。我个人的习惯是:先做核心闭环,再慢慢加功能。车载项目尤其如此——功能越多,测试越复杂,出问题的概率越大。

避坑指南

我曾经在一个项目里,一口气加了10个功能。结果呢?光联调就花了三周。后来我学乖了:MVP只做3-5个核心功能,跑通流程再迭代。

2. 架构设计:分层解耦,各司其职

需求明确了,接下来就是架构设计。车载应用架构,我推荐分层设计。为什么?因为好维护、好测试、好扩展。

下面这张图,是我自己画的项目架构图。你看一眼就明白了。

车载智能助手 - 分层架构图 UI层(Jetpack Compose + Car UI Library) 主界面 | 仪表盘界面 | 语音交互界面 | 多屏适配 ViewModel层(状态管理 + 业务逻辑编排) MainViewModel | VehicleViewModel | VoiceViewModel Service层(后台服务 + 系统API封装) VoiceService | VehicleService | NavigationService HAL / 系统层(Vehicle HAL + CarService + 硬件抽象) CAN总线 | 麦克风阵列 | GPS模块 | 车载传感器

你看,从上到下,职责非常清晰:

  • UI层:只负责展示和用户交互。我用的是Jetpack Compose + Car UI Library,适配多屏很方便。
  • ViewModel层:管理UI状态,编排业务逻辑。说白了,就是UI和Service之间的「翻译官」。
  • Service层:封装系统API,处理后台任务。比如语音识别、车辆数据采集。
  • HAL/系统层:这是Android Automotive OS的底层,直接和硬件打交道。我们一般不动它,只调用标准接口。

注意:分层架构最大的好处是「可替换」。比如你想把语音识别从百度换成讯飞,只需要改Service层,UI层完全不用动。我在项目中吃过耦合的亏,后来强制分层,维护成本降了一半。

3. 功能实现:核心代码走一遍

架构搭好了,咱们开始写代码。我挑三个核心功能讲讲。

3.1 车辆状态实时获取

车辆状态数据,通过Vehicle HAL提供。我们只需要订阅对应的Property ID。

// 订阅车速和电量
val speedProperty = VehiclePropertyIds.PERF_VEHICLE_SPEED
val batteryProperty = VehiclePropertyIds.EV_BATTERY_LEVEL

// 在VehicleService中订阅
car.connectCarService()
car.getVehicleManager()?.let { manager ->
    manager.addCallback(speedProperty, 0) { value ->
        // 更新车速到ViewModel
        _speedLiveData.postValue(value.floatValue)
    }
    manager.addCallback(batteryProperty, 0) { value ->
        _batteryLiveData.postValue(value.floatValue)
    }
}

这里有个坑:Vehicle HAL的回调频率很高。如果你直接更新UI,性能会崩。我建议在ViewModel里做节流处理,比如每200ms更新一次。

3.2 语音唤醒与指令解析

语音唤醒,我用的是离线唤醒词方案。这样不依赖网络,响应更快。

// 初始化语音唤醒
val wakeupEngine = WakeupEngine.create(context)
wakeupEngine.setWakeupWord("你好小智")
wakeupEngine.setWakeupCallback {
    // 唤醒成功,启动语音识别
    startVoiceRecognition()
}

// 语音识别结果解析
fun parseVoiceCommand(text: String): VoiceCommand {
    return when {
        text.contains("导航到") -> {
            val destination = text.substringAfter("导航到")
            VoiceCommand.Navigate(destination)
        }
        text.contains("空调") && text.contains("开") -> VoiceCommand.ACOn
        text.contains("空调") && text.contains("关") -> VoiceCommand.ACOff
        text.contains("播放音乐") -> VoiceCommand.PlayMusic
        else -> VoiceCommand.Unknown
    }
}

你想想看,如果用户说「导航到天安门」,你的解析器能正确提取目的地吗?我建议用正则或者简单的关键词匹配,别一上来就上NLP,车载场景指令有限,够用就行。

3.3 驾驶安全约束

这个功能,说白了就是「车动了,有些操作就不让做了」。Android Automotive OS提供了CarOccupantZoneManager来判断驾驶位。

// 判断当前是否在驾驶位
val occupantZoneManager = car.getCarManager(CarOccupantZoneManager::class.java)
val isDriver = occupantZoneManager?.let {
    it.getOccupantZone(OccupantZoneInfo.ROLE_DRIVER)?.isOccupant
} ?: false

// 获取车辆运动状态
val vehicleSpeed = _speedLiveData.value ?: 0f
if (vehicleSpeed > 0.5f && isDriver) {
    // 限制视频播放、复杂操作
    showBlockingUI()
}

个人经验:车速阈值别设太低。我一开始设了0.1m/s,结果等红灯时稍微溜车就触发限制了,用户疯狂投诉。后来改成0.5m/s(约1.8km/h),体验好多了。

4. 测试与发布:别让bug上路

车载应用的测试,比手机应用严格得多。因为bug可能导致安全事故。

我一般分三步走:

  1. 单元测试:用JUnit + Mockito,测试ViewModel和Service层的逻辑。比如语音指令解析、车速阈值判断。
  2. 集成测试:用Android Automotive模拟器,模拟车辆状态变化。测试多屏交互、语音唤醒等场景。
  3. 实车测试:这是最关键的。找一台开发板或者实车,跑一遍所有功能。我建议至少跑100公里,覆盖城市、高速、隧道等场景。

测试清单(部分)

测试项 测试场景 预期结果
语音唤醒 车速80km/h,开窗,播放音乐 唤醒成功率 > 90%
导航联动 语音输入「导航到北京西站」 正确解析并启动导航
安全约束 车速 > 5km/h,点击视频播放 弹出提示,禁止播放
多屏适配 中控屏和仪表盘同时显示 布局正确,无重叠

发布时,我建议走Google Play for Automotive。它会自动做兼容性检查。不过要注意,车载应用更新频率别太高,用户不会像手机那样频繁升级。

5. 项目总结:复盘一下

项目做完了,咱们复盘一下。说实话,这个「车载智能助手」项目,麻雀虽小五脏俱全。

你学到了什么?

  • 需求分析:别贪多,MVP先跑通。
  • 架构设计:分层解耦,好维护好扩展。
  • 功能实现:Vehicle HAL、语音唤醒、安全约束,都是车载核心能力。
  • 测试发布:实车测试不能省,安全第一。

我记得第一次做车载项目时,光Vehicle HAL的权限问题就折腾了两天。后来发现是manifest里少声明了一个权限。嗯,这种坑踩一次就够了。

最后送你一句话:车载开发,慢就是快。多花时间在设计和测试上,上线后你会感谢自己的。

如果你对某个模块有疑问,或者想深入聊聊,欢迎来找我。公众号:蓝海资料掘金营,微信deep3321