【android bluetooth 案例分析 04】【Carplay 详解 2】【Carplay 连接之手机主动连车机】

news2025/6/3 20:44:59

1. 背景

在【android bluetooth 案例分析 04】【Carplay 详解 1】【CarPlay 在车机侧的蓝牙通信原理与角色划分详解】中我们从整理上介绍了车机中 carplay 相关基础概念。 本节 将详细分析 iphone手机主动 连接 车机carplay 这一过程。

先回顾一下 上一节, carplay 整个流程:

  1. EIR 广播识别

    • iPhone 开启 EIR 广播,包含 UUID_DEVICE_CARPLAY_EIR 2d8d2466-e14d-451c-88bc-7301abea291a
    • 车机通过蓝牙扫描识别支持 CarPlay 的 iPhone
  2. 蓝牙连接

    • 没有配对,需要先配对
    • iPhone 主动连接车机的 SPP Server UUID (UUID_IAP_ACCESSORY 00000000-deca-fade-deca-deafdecacaff
      • 车机需要先 listenUsingRfcommWithServiceRecord
    • 车机作为 Client 主动连接 iPhone 暴露的 Server UUID
      • (需 iPhone 开启EIR 广播)
  3. IAP2 协议交互

    • 交换设备信息、认证令牌、能力参数(支持哪种 Wi-Fi 架构)
  4. Wi-Fi 建链

    • 手机连接车机热点,或车机连接手机热点,完成 IP 建立
  5. TCP & mDNS 发现 CarPlay 服务

    • 建立 TCP 通信,寻找 _carplay._tcp.local 服务,启动 CarPlay Session
  6. 启动投屏/音频/导航服务

上面总过分为 6 步: 但是涉及到蓝牙的只有 1 、 2、 3 步。 那我们就来分别来介绍一下 在当前 手机主动连车机的清晰。这三步是如何具体实操的。

2. 手机主动连车机

1. EIR 广播

EIR 广播识别:

  1. 车机开启 EIR 广播, 包含 00000000-deca-fade-deca-deafdecacaffec884348-cd41-40a2-9727-575d50bf1fd3
    • 手机就可以扫描到 车机支持 carplay
  2. iPhone 开启 EIR 广播,包含 00000000-deca-fade-deca-deafdecacafe2d8d2466-e14d-451c-88bc-7301abea291a
    • 车机通过蓝牙扫描识别支持 CarPlay 的 iPhone

1. 手机 开启 EIR 广播

当 iphone 手机进入 设置 -> 通用 -> Carplay 车载 界面时, 此时,车机如果开启 扫描。此时就能从 扫描到的 EIR 中看到如下的广播信息。


300	2025-01-01 19:40:57.096358	controller	host	HCI_EVT	258	Rcvd Extended Inquiry Result

Bluetooth HCI Event - Extended Inquiry Result
    Event Code: Extended Inquiry Result (0x2f)
    Parameter Total Length: 255
    Number of responses: 1
    BD_ADDR: Apple_7c:81:36 (84:ad:8d:7c:81:36)
    Page Scan Repetition Mode: R1 (0x01)
    Reserved: 0x00
    Class of Device: 0x7a020c (Phone:Smartphone - services: Networking Capturing ObjectTransfer Audio Telephony)
    .110 1101 0010 1011 = Clock Offset: 0x6d2b
    RSSI: -38 dBm
    Extended Inquiry Response Data
        Device Name: Jxl
            Length: 4
            Type: Device Name (0x09)
            Device Name: Jxl
        16-bit Service Class UUIDs
            Length: 15
            Type: 16-bit Service Class UUIDs (0x03)
            UUID 16: PnP Information (0x1200)
            UUID 16: Handsfree Audio Gateway (0x111f)
            UUID 16: Phonebook Access Server (0x112f)
            UUID 16: Audio Source (0x110a)
            UUID 16: A/V Remote Control Target (0x110c)
            UUID 16: Message Access Server (0x1132)
            UUID 16: Generic Attribute Profile (0x1801)
        32-bit Service Class UUIDs
            Length: 1
            Type: 32-bit Service Class UUIDs (0x05)
        128-bit Service Class UUIDs
            Length: 49
            Type: 128-bit Service Class UUIDs (0x07)
            Custom UUID: 00000000-deca-fade-deca-deafdecacafe (Unknown)
            Custom UUID: 02030302-1d19-415f-86f2-22a2106a0a77 (Unknown)
            Custom UUID: 2d8d2466-e14d-451c-88bc-7301abea291a (Unknown)  // 此时手机 回复的 uuid 中就包含, 识别手机支持 carplay 的 uuid
        Manufacturer Specific
            Length: 39
            Type: Manufacturer Specific (0xff)
            Company ID: Unknown (0x4c00)
            Data: 022402000000000000000000000000000000000000000000000000000000000000000000
                [Expert Info (Note/Undecoded): Undecoded]
                    [Undecoded]
                    [Severity level: Note]
                    [Group: Undecoded]
        Unused


2d8d2466-e14d-451c-88bc-7301abea291a 这个 uuid 就是帮助车机筛选 那些手机支持 carplay 功能的。

在协议栈中 我们会将 该 uuid 上报 到 应用侧。如果不明白 如果上报,可以看一下这篇文章
【android bluetooth 协议分析 03】【蓝牙扫描详解 1】【扫描关键函数 btif_dm_search_devices_evt 分析】

此时在车机 carplay 连接 界面就可以看到 当前 iphone 手机。

2. 车机开启EIR 广播

分析到这里, 有人疑惑,车机是 可以看到 手机支持 carplay. 但是此时 手机 应该看不到 车机支持carplay 功能吧。确实是这样子?

我们可以参照手机的操作。 将 carplay 的 uuid 写入 车机的 EIR 中。 这样手机在扫描时 , 就可以扫描 到车机的 EIR. 这块手机就可以发现 车机支持 carplay.

如下是 app 侧的操作 流程:

    /*我们代码添加IAP的uuid,车机的BT模块里自动添加CP的uuid*/
    //IAP2 uuid 使用此uuid,手机才能发起IAP连接
    private static final UUID SERVER_SPP_UUID = UUID.fromString("00000000-deca-fade-deca-deafdecacaff");
    //CP uuid 使用此uuid,手机CarPlay车载画面能够扫描出来,但是在手机CarPlay车载画面点击车机时,无法连接上
    private static final UUID SERVER_SPP_UUID_CP = UUID.fromString("EC884348-CD41-40A2-9727-575D50BF1FD3");


	BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

	BluetoothServerSocket mServerSocket = adapter.listenUsingRfcommWithServiceRecord("com.running.android.carplay", SERVER_SPP_UUID);

	BluetoothSocket mClientSocket = mServerSocket.accept();
  1. 先调用 listenUsingRfcommWithServiceRecord 方法,在 该 listenUsingRfcommWithServiceRecord 中,就会将 00000000-deca-fade-deca-deafdecacaff 和 EC884348-CD41-40A2-9727-575D50BF1FD3 两个 uuid. 写入到我们的 eir 中。 并创建 一个 spp server.
  2. mServerSocket.accept(); 等待 手机来连接。 手机连接后,将会返回一个新的 socket.
  3. 拿到这个 socket. 手机和车机就可以 交互 carplay 连接需要的信息。例如 wifi 热点名字,密码等。

105	2025-01-01 19:40:31.420798	host	controller	HCI_CMD	245	Sent Write Extended Inquiry Response


Frame 105: 245 bytes on wire (1960 bits), 245 bytes captured (1960 bits)
Bluetooth
Bluetooth HCI H4
Bluetooth HCI Command - Write Extended Inquiry Response
    Command Opcode: Write Extended Inquiry Response (0x0c52)
    Parameter Total Length: 241
    FEC Required: true (1)
    Extended Inquiry Response Data
        Device Name: xxxxxx
        16-bit Service Class UUIDs
            Length: 13
            Type: 16-bit Service Class UUIDs (0x03)
            UUID 16: Audio Sink (0x110b)
            UUID 16: A/V Remote Control Target (0x110c)
            UUID 16: A/V Remote Control (0x110e)
            UUID 16: Handsfree (0x111e)
            UUID 16: Phonebook Access Client (0x112e)
            UUID 16: PnP Information (0x1200)
        32-bit Service Class UUIDs
            Length: 1
            Type: 32-bit Service Class UUIDs (0x05)
        128-bit Service Class UUIDs
            Length: 129
            Type: 128-bit Service Class UUIDs (0x07)
            Custom UUID: 00000000-deca-fade-deca-deafdecacaff (Unknown) // 这个是 app 侧下发的 uuid
            Custom UUID: ec884348-cd41-40a2-9727-575d50bf1fd3 (Unknown) // 这个我们根据 app 下发的uuid 在协议栈中我们任务加的
            Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)
            Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)
            Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)
            Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)
            Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)
            Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)
        Tx Power Level
            Length: 2
            Type: Tx Power Level (0x0a)
            Power Level (dBm): 8
        Unused
    [Response in frame: 106]
    [Command-Response Delta: 28.115ms]

  • 此时 我们的手机就可以正确的扫描到 我们的车机也支持 carplay。

2. 蓝牙连接 iap 并通信

没有配对,需要先配对 : 这个是常规操作, 这里不分享了。

这里主要分析一下。 手机 主动连接 车机 iap 的过程:

在这里插入图片描述

在这里插入图片描述

  • 手机向 车机发起了 sdp , 这里手机向我们查询的 uuid. 正是我们前面注册的 00000000-deca-fade-deca-deafdecacaff
  • 车机回复了 对应的 rfcomm 通道为 3

手机继续 主动查询 车机之前注册的 UUID ec884348-cd41-40a2-9727-575d50bf1fd3

在这里插入图片描述

在这里插入图片描述

这里车机回复了该uuid 对应的 rfcomm 通道为 4

在这里插入图片描述

手机 主动 请求连接车机的 rfcomm channel 3

在这里插入图片描述

接下来 车机和手机 通过 channel 3 开始将 后面 carplay 连接需要的 wifi 相关的 热点名字,密码发送给手机。

3. 总结

手机 如果要主动连接车机carplay

车机需要 完成如下步骤:

  1. 车机 app 侧需要 通过如下代码:
    • 开启 车机 EIR 广播:广播 00000000-deca-fade-deca-deafdecacaffec884348-cd41-40a2-9727-575d50bf1fd3 这样 在手机carplay 界面才可以看到车机。
    • 向 sdp 数据库中注册 上述 两个uuid. 这样 手机主动发起 上述两个服务的uuid 时, 车机才知道如何回复。
	BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

	// 开启 EIR 和 注册 SDP 数据库,都是通过该调用实现的
	BluetoothServerSocket mServerSocket = adapter.listenUsingRfcommWithServiceRecord("com.running.android.carplay", SERVER_SPP_UUID);
  1. 车机carplay app. 等待 手机连接
BluetoothSocket mClientSocket = mServerSocket.accept(); // 当手机主动连接时, 这里将返回,一个新的 socket. 用于 iap 内容交互
  1. 此时 手机 carplay 界面就可以扫描到 车机, 点击界面发起 对车机的主动连接:

    • 此时会看到 手机主动向 车机发起 00000000-deca-fade-deca-deafdecacaffec884348-cd41-40a2-9727-575d50bf1fd3 两个服务的 SDP 查询。
    • 车机返回对应的 rfcomm 通道号。 例如 00000000-deca-fade-deca-deafdecacaff iap协议, rfcomm channel= 3
  2. 手机主动发起 rfcomm channel 3 , iap 协议的连接。

  3. 车机和手机,此时就可以通过 iap 协议交互,后续 carplay 连接所需要的 wifi 热点信息。

  4. 交互完成后,断开rfcomm channel3

  5. 发起 真正的 carplay 连接, 此时就可以看到 手机将画面 投屏到车机上。

这里的重点是 调用 listenUsingRfcommWithServiceRecord 函数。
该函数的讲解,将在另外的 文章中单独讲解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2395146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【仿muduo库实现并发服务器】实现时间轮定时器

实现时间轮定时器 1.时间轮定时器原理2.项目中实现目的3.实现功能3.1构造定时任务类3.2构造时间轮定时器每秒钟往后移动添加定时任务刷新定时任务取消定时任务 4.完整代码 1.时间轮定时器原理 时间轮定时器的原理类似于时钟,比如现在12点,定一个3点的闹…

day15 leetcode-hot100-28(链表7)

2. 两数相加 - 力扣(LeetCode) 1.模拟 思路 最核心的一点就是将两个链表模拟为等长,不足的假设为0; (1)设置一个新链表newl来代表相加结果。 (2)链表1与链表2相加,具…

​​知识图谱:重构认知的智能革命​

在数字经济的浪潮中,知识图谱正悄然掀起一场认知革命。它不仅是技术的迭代,更是人类从“数据依赖”迈向“知识驱动”的里程碑。当谷歌用知识图谱优化搜索引擎、银行用它穿透复杂的金融欺诈网络、医院用它辅助癌症诊疗时,这项技术已悄然渗透到…

【计算机网络】4网络层①

这篇笔记讲IPv4和IPv6。 为了解决“IP地址耗尽”问题,有三种措施: ①CIDR(延长IPv4使用寿命) ②NAT(延长IPv4使用寿命) ③IPv6(从根本上解决IP地址耗尽问题) IPv6 在考研中考查频率较低,但需掌握基础概念以防冷门考点,重点结合数据报格式和与 IPv4 的对比记忆。…

MATLAB中的table数据类型:高效数据管理的利器

MATLAB中的table数据类型:高效数据管理的利器 什么是table数据类型? MATLAB中的table是一种用于存储列向数据的数据类型,它将不同类型的数据组织在一个表格结构中,类似于电子表格或数据库表。自R2013b版本引入以来,t…

Dropout 在大语言模型中的应用:以 GPT 和 BERT 为例

引言 大型语言模型(LLMs)如 GPT(生成式预训练 Transformer)和 BERT(双向编码器表示 Transformer)通过其强大的语言理解和生成能力,彻底改变了自然语言处理(NLP)领域。然…

gitLab 切换中文模式

点击【头像】--选择settings 选择【language】,选择中文,点击【保存】即可。

133.在 Vue3 中使用 OpenLayers 实现画多边形、任意编辑、遮罩与剪切处理功能

🎬 效果演示截图(先睹为快) ✨ 功能概览: ✅ 鼠标画任意形状多边形; ✏️ 点击“修改边界”可拖动顶点; 🟥 点击“遮罩”后地图除多边形区域外变红; ✂️ 点击“剪切”后仅显示选…

4.8.4 利用Spark SQL实现分组排行榜

在本次实战中,我们的目标是利用Spark SQL实现分组排行榜,特别是计算每个学生分数最高的前3个成绩。任务的原始数据由一组学生成绩组成,每个学生可能有多个成绩记录。我们首先将这些数据读入Spark DataFrame,然后按学生姓名分组&am…

【五子棋在线对战】一.前置知识的了解

前置知识的了解 前言1.Websocketpp1.1 使用Websocketpp的原因1.2 Websocket常用接口1.3 Websocket搭建服务器流程 2.JsonCpp2.1 Json 数据对象类的表示2.2序列化和反序列化的接口2.3 演示代码 3.Mysql![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/93305f423b544fc1…

历年中国科学技术大学计算机保研上机真题

2025中国科学技术大学计算机保研上机真题 2024中国科学技术大学计算机保研上机真题 2023中国科学技术大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school?classification1 拆分数字 题目描述 给定一个数字,拆分成若干个数字之和&#xff…

HackMyVM-Art

信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-31 03:00 EDT Nmap scan report for 192.168.43.1 Host is up (0.0047s latency). MAC Address: C6:45:66:05:91:88 (Unknown) Nmap scan rep…

网页前端开发(基础进阶1)

颜色表示方法3种: 1.关键字: color:green; gray red yellow 2.rgb表示法:红,绿,蓝三原色。rgb(r,g,b),r表示红色,g表示绿…

如何找到一条适合自己企业的发展之路?

一个创业型的企业,开始就需要面向市场,通过自己的服务或产品,帮助用户解决问题,为客户创造价值,通过为客户创造的价值,出创造一定的的现金流,让企业存活下来! 企业的运营过程中&…

Vue-数据监听

数据监听 基础信息 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>数据监听</title><!-- 引入Vue --><script type"text/javascript" src"../js/vue.js&qu…

当前用户的Git全局配置情况:git config --global --list

通过config命令可以查询当前用户的全局配置情况。这些配置项定义了 Git 在全局范围内的行为&#xff0c;包括如何处理大文件、SSL 证书验证以及提交时的用户信息。 git config --global --list http.sslVerifyfalse 这个配置项禁用了 SSL 证书验证。这在与自签名证书的 Git 服…

AI生态警报:MCP协议风险与应对指南(中)——MCP Server运行时安全​​

作为连接AI模型与外部工具的“USB-C接口”&#xff0c;MCP协议成为AI生态的核心枢纽&#xff0c;其安全风险已从理论威胁转化为实际攻击目标。 AI生态警报&#xff1a;MCP协议风险与应对指南&#xff08;上&#xff09;——架构与供应链风险https://blog.csdn.net/WangsuSecur…

day15 leetcode-hot100-29(链表8)

19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 1.暴力法 思路 &#xff08;1&#xff09;先获取链表的长度L &#xff08;2&#xff09;然后再次遍历链表到L-n的位置&#xff0c;直接让该指针的节点指向下下一个即可。 2.哈希表 思路 &#xff0…

MonitorSDK_性能监控(从Web Vital性能指标、PerformanceObserver API和具体代码实现)

性能监控 性能指标 在实现性能监控前&#xff0c;先了解Web Vitals涉及的常见的性能指标 Web Vitals 是由 Google 推出的网页用户体验衡量指标体系&#xff0c;旨在帮助开发者量化和优化网页在实际用户终端上的性能体验。Web Vitals 强调“以用户为中心”的度量&#xff0c;而不…

LeeCode 98. 验证二叉搜索树

给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 提示&#xff1a; 树中节…