7、车载通信应用开发:CarMessagingService、通知栏消息管理、语音输入与TTS输出、联系人同步
车载通信应用,说白了就是让用户在开车时也能安全地收发消息。这可不是简单地把手机上的微信搬过来。我参与过好几个车载项目,最深的体会是:安全第一,交互第二,功能第三。你想想看,驾驶员在高速上低头看手机两秒钟,车就开出去几十米了。所以Android Automotive在设计通信API时,处处都透着「别让司机分心」这个核心思想。
7.1 CarMessagingService:车载消息服务的核心
CarMessagingService是Android Automotive专门为消息类应用提供的系统服务。它负责管理消息的收发、通知的展示,以及与车载硬件的交互。我个人习惯把它的工作流程分成三步:
- 消息接收:应用通过CarMessagingService接收新消息
- 通知展示:系统自动将消息转换为车载通知栏样式
- 用户交互:支持语音播报、快捷回复、免打扰模式
核心要点:CarMessagingService不是让你自己画UI的。它提供了一套标准化的消息展示模板,你只需要提供消息内容和操作意图,剩下的交给系统。
来看一个基本的实现示例:
public class MyMessagingService extends CarMessagingService {
@Override
public void onMessageReceived(CarMessage message) {
// 收到新消息
String sender = message.getSender();
String text = message.getText();
long timestamp = message.getTimestamp();
// 构建通知
CarNotification notification = new CarNotification.Builder(this)
.setTitle(sender)
.setText(text)
.setTimestamp(timestamp)
.setReadIntent(createReadIntent(message))
.setReplyIntent(createReplyIntent(message))
.build();
// 发送通知
notify(notification);
}
@Override
public void onNotificationDismissed(CarNotification notification) {
// 用户滑掉了通知,标记为已读
markAsRead(notification.getMessageId());
}
}
我在项目中遇到过一个问题:消息重复通知。原因是手机端和车机端同时收到了消息,都弹了通知。后来我们在服务端加了一个设备标识,车机连接时只推送到车机端,手机端静默处理。嗯,这个坑踩得值。
7.2 通知栏消息管理:别让司机分心
车载通知栏和手机通知栏最大的区别是什么?优先级和可操作性。手机上的通知可以堆成山,但车载通知必须精简到极致。我建议你记住这几个原则:
- 最多显示3条:超过3条的通知会被折叠,只显示「还有N条消息」
- 支持快捷操作:每条通知至少提供「播报」和「忽略」两个操作
- 自动消失:车辆启动后,非紧急通知自动清除
- 驾驶模式联动:车辆行驶中,通知只显示摘要,不显示具体内容
小技巧:使用CarNotification.Builder的setGroup()方法对消息分组。比如同一个联系人的多条消息合并成一组,用户点开后再逐条查看。这样既减少了通知数量,又保留了信息完整性。
通知的优先级管理也很关键。我一般这样划分:
| 优先级 | 场景 | 展示方式 |
|---|---|---|
| 紧急 | 安全警报、紧急联系人消息 | 全屏弹窗 + 语音播报 |
| 重要 | 工作消息、导航提示 | 通知栏置顶 + 语音提示 |
| 普通 | 社交消息、新闻推送 | 通知栏折叠 + 静默提醒 |
| 低优先级 | 广告、系统更新 | 不展示,存入通知中心 |
7.3 语音输入与TTS输出:解放双手
车载场景下,语音交互是刚需。你想想看,司机正在开车,突然来了一条消息,总不能让他打字回复吧?所以Android Automotive提供了完整的语音输入和TTS(文本转语音)支持。
语音输入流程:
- 用户点击麦克风按钮或说出唤醒词
- 系统启动语音识别服务(如Google Assistant或第三方引擎)
- 识别结果通过SpeechRecognizer回调返回
- 应用处理识别结果,执行相应操作
// 启动语音输入
private void startVoiceInput() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "请说出您要发送的消息");
startActivityForResult(intent, VOICE_INPUT_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VOICE_INPUT_REQUEST_CODE && resultCode == RESULT_OK) {
ArrayList<String> results =
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
String spokenText = results.get(0);
// 发送消息
sendMessage(spokenText);
}
}
TTS输出:收到消息后,系统自动播报。但要注意,不要全文播报。我曾经见过一个应用,收到一封长邮件就从头念到尾,司机差点崩溃。正确的做法是:
- 先播报发送者和消息摘要(如「张三发来一条消息:关于明天的会议...」)
- 用户确认后,再播报完整内容
- 支持打断:用户说「停」或「忽略」时立即停止播报
注意:TTS播报时,如果车辆正在播放音乐或导航语音,系统会自动降低音乐音量(称为「闪避」或Ducking)。但你的应用不要手动控制音量,交给系统处理就好。否则可能出现音量冲突。
7.4 联系人同步:从手机到车机
联系人同步是车载通信的基础。没有联系人,你连消息发给谁都不知道。Android Automotive通过AccountManager和ContactsContract API实现联系人同步。但这里有个关键点:车机上的联系人数据是手机联系人的一个子集,只同步常用联系人和最近联系人。
同步流程大致如下:
- 车机与手机建立连接(通过蓝牙或WiFi)
- 车机请求联系人同步权限
- 手机端筛选出常用联系人(最近30天有通话或消息记录的)
- 数据加密传输到车机本地存储
- 车机更新联系人索引,支持语音搜索
// 同步联系人
public void syncContacts() {
ContentResolver resolver = getContentResolver();
Uri uri = ContactsContract.Contacts.CONTENT_URI;
// 只查询有手机号码的联系人
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = 1";
Cursor cursor = resolver.query(uri, null, selection, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phoneNumber = getPhoneNumber(cursor);
// 存储到车机本地数据库
saveContactToLocal(name, phoneNumber);
}
cursor.close();
}
}
经验之谈:联系人同步不要全量同步。我见过一个项目,用户手机上有2000多个联系人,每次同步都要好几分钟。后来我们改成增量同步,只同步新增或修改的联系人,速度提升了很多。另外,一定要做去重,同一个联系人可能有多个号码,合并展示会更清晰。
7.5 整体架构与数据流
说了这么多,我们来画一张图,把整个车载通信应用的核心逻辑串起来。这样你脑子里会有一个清晰的框架。
这张图展示了数据从手机端到车机端的完整流向。你注意看,用户交互层是独立出来的,这意味着不管底层数据怎么来,最终给用户的体验都是一致的:语音唤醒、语音输入、消息播报、快捷回复,再加上一个免打扰模式。嗯,这个设计思路我在好几个项目中都用过,效果不错。
总结一下:车载通信应用开发的核心不是功能有多花哨,而是安全、简洁、高效。CarMessagingService帮你管好了消息的收发和通知展示,语音输入和TTS让司机不用动手,联系人同步保证了通信的准确性。把这些模块组合好,就是一个合格的车载通信应用了。