7、车载通信应用开发:CarMessagingService、通知栏消息管理、语音输入与TTS输出、联系人同步

车载通信应用,说白了就是让用户在开车时也能安全地收发消息。这可不是简单地把手机上的微信搬过来。我参与过好几个车载项目,最深的体会是:安全第一,交互第二,功能第三。你想想看,驾驶员在高速上低头看手机两秒钟,车就开出去几十米了。所以Android Automotive在设计通信API时,处处都透着「别让司机分心」这个核心思想。

7.1 CarMessagingService:车载消息服务的核心

CarMessagingService是Android Automotive专门为消息类应用提供的系统服务。它负责管理消息的收发、通知的展示,以及与车载硬件的交互。我个人习惯把它的工作流程分成三步:

  1. 消息接收:应用通过CarMessagingService接收新消息
  2. 通知展示:系统自动将消息转换为车载通知栏样式
  3. 用户交互:支持语音播报、快捷回复、免打扰模式

核心要点: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(文本转语音)支持。

语音输入流程

  1. 用户点击麦克风按钮或说出唤醒词
  2. 系统启动语音识别服务(如Google Assistant或第三方引擎)
  3. 识别结果通过SpeechRecognizer回调返回
  4. 应用处理识别结果,执行相应操作
// 启动语音输入
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实现联系人同步。但这里有个关键点:车机上的联系人数据是手机联系人的一个子集,只同步常用联系人和最近联系人。

同步流程大致如下:

  1. 车机与手机建立连接(通过蓝牙或WiFi)
  2. 车机请求联系人同步权限
  3. 手机端筛选出常用联系人(最近30天有通话或消息记录的)
  4. 数据加密传输到车机本地存储
  5. 车机更新联系人索引,支持语音搜索
// 同步联系人
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 整体架构与数据流

说了这么多,我们来画一张图,把整个车载通信应用的核心逻辑串起来。这样你脑子里会有一个清晰的框架。

车载通信应用核心架构 手机端 联系人数据库 消息接收服务 语音识别引擎 连接层 蓝牙 / WiFi / 云同步 数据加密传输 车机端 CarMessagingService 本地联系人缓存 TTS播报引擎 用户交互层 语音唤醒 → 语音输入 → 消息播报 → 快捷回复 → 免打扰模式 数据流向:手机端 → 连接层 → 车机端 → 用户交互 关键点:数据加密、增量同步、语音打断、通知优先级管理

这张图展示了数据从手机端到车机端的完整流向。你注意看,用户交互层是独立出来的,这意味着不管底层数据怎么来,最终给用户的体验都是一致的:语音唤醒、语音输入、消息播报、快捷回复,再加上一个免打扰模式。嗯,这个设计思路我在好几个项目中都用过,效果不错。

总结一下:车载通信应用开发的核心不是功能有多花哨,而是安全、简洁、高效。CarMessagingService帮你管好了消息的收发和通知展示,语音输入和TTS让司机不用动手,联系人同步保证了通信的准确性。把这些模块组合好,就是一个合格的车载通信应用了。

公众号:蓝海资料掘金营,微信deep3321