ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Open Headunit 的 NearbySocket 与 NearbyManager:用 Google Nearby 实现 Android Auto 无线发现的完整指南

2026/9/18 14:03:46 拓冰建站 浏览量
Open Headunit 的 NearbySocket 与 NearbyManager:用 Google Nearby 实现 Android Auto 无线发现的完整指南 Open Headunit 的 NearbySocket 与 NearbyManager用 Google Nearby 实现 Android Auto 无线发现的完整指南【免费下载链接】open-headunitHeadunit App for displaying Android Auto项目地址: https://gitcode.com/GitHub_Trending/he/open-headunitOpen Headunit 是一款把 Android 平板变成 Android Auto 车机接收端的开源应用。本文带你读懂其中负责找到手机并建立无线链路的一对核心类NearbySocket与NearbyManager——它们基于 Google Nearby Connections 完成设备发现、点对点连接与双向数据隧道是无线 Helper 模式下默认的自动发现方案。 为什么需要 Nearby 发现传统的无线连接方式同网段扫描、Wi-Fi Direct、热点都要求两台设备恰好在网络层面可见而 Google Nearby Connections 用蓝牙/Wi-Fi 混合广播直接宣告设备存在——无需预配置网络开机即发现。在 HelperStrategy.kt 中可以看到Helper 模式共有 5 种策略其中NEARBY_DEVICES(2) // Google Nearby —— 且是 DEFAULT 默认策略也就是说当你什么都不改时Open Headunit 启动后默认走的就是 Nearby 发现。️ 架构速览平板只做发现者NearbyManager.kt 的类注释写得很直白The Tablet acts as a DISCOVERER only平板只做发现者。整个体系分工如下组件职责源码位置NearbyManager发现手机、发起连接、组装流隧道、诊断故障NearbyManager.ktNearbySocket用两条 Nearby 数据流拼出一个标准Socket假象NearbySocket.ktWifiLauncherHelperHelper 模式入口策略路由与隧道就绪回调WifiLauncherHelper.kt发现到的设备通过StateFlowListDiscoveredEndpoint暴露给 UI主界面列表实时刷新用户点击设备或触发自动重连时都走同一个connectToEndpoint()入口。 连接四步走从广播到隧道NearbyManager 内部用回调串联起整个生命周期每一步都会上报连接阶段见 ConnectionStage.ktSEARCHING—start()校验定位 蓝牙广播/扫描/连接权限后以SERVICE_ID com.andrerinas.openhu、策略P2P_POINT_TO_POINT开始发现PHONE_ANSWERED—onEndpointFound发现手机写入设备列表若开启自动重连且设备名匹配上次记录立即发起连接PHONE_JOINING—onConnectionInitiated自动接受连接同时把设备名存为lastNearbyDeviceName备用并立即停止发现找到目标就不再扫描建隧道— 连接结果 OK 且带宽升级到 HIGH 后maybeBuildTunnel()创建NearbySocket通过ParcelFileDescriptor.createPipe()建管道以Payload.fromStream把管道一端发给手机随即回调onSocketReady(socket)交给CommManager启动 Android Auto 握手 关键设计maybeBuildTunnel()同时被连接成功和带宽变化两个回调触发。因为 Nearby 的回调到达顺序不保证拆出这个统一判断点可以杜绝先收到 HIGH 但端点还没记录导致隧道永远建不起来的时序坑。 NearbySocket 内部一个由两条流拼成的假 SocketNearby 传输的是**数据流Stream Payload**而不是 TCP 套接字。为了让上层 AAP 协议栈无感知地读写NearbySocket.kt 继承java.net.Socket并伪装isConnected()恒返回truegetInetAddress()返回回环地址——对上层屏蔽了这不是真网络套接字的事实getInputStream()/getOutputStream()返回内部包装流读写最终落到 Nearby 的两条流上写入后强制 flush因为 GMS Nearby 流会大量缓冲不刷就会卡在握手最巧妙的地方是有界等待手机那条入站流可能晚于我方出站流到达读取前必须等它注册。源码用CountDownLatch实现等待超时定值为STREAM_WAIT_MS 8_000LNearbySocket.kt#L41。这个 8 秒是精心夹在两个已知时间之间的实测握手 1.2~1.3 s 8 s 10 s上层握手总预算 16 sNearby 自身的 payload 超时这样一旦手机端助手没有注册自己的流日志会在 8 秒时明确指出手机端从未送达流的一半而不是像旧实现那样让握手线程无限挂起、数分钟后才冒出无头无尾的报错。⏱️ 带宽升级与 10 秒超时Wi-Fi 就绪信号Nearby 连接初始可能跑在低功耗链路上必须等onBandwidthChanged报告HIGH质量即已切到 Wi-Fi 直连才建隧道。lastQuality按端点缓存看到过的最高质量不依赖回调顺序质量级别含义是否建隧道LOW / MEDIUM仍在低功耗链路❌ 继续等HIGH已升级到 Wi-Fi✅ 立即建隧道10 秒内未见 HIGH升级超时❌ 断开并提示检查 Wi-Fi/蓝牙设置超时断开是有意为之——宁可放弃也不让链路回落到蓝牙否则 Android Auto 投屏带宽完全不够用。 自动重连与故障自诊断两个很实用的细节都出自 NearbyManager.kt记住你的手机每次onConnectionInitiated都会保存设备名下次发现阶段一旦匹配到同名设备且开启自动连接无需人工点选直接连上隧道失败二分诊断连接时记录当前网络句柄networkAtConnect隧道失败时再比对一次——若网络没变说明手机根本没应答若网络已变说明平板 Wi-Fi 在升级协商期间被拆掉重建射频无法同时维持热点与 P2P 组网此时日志会直接给出建议改用同频 Wi-Fi 或Common WiFi / Headunit Server策略因为它们复用现有网络、不重配射频️ 排错清单Nearby 连接失败的常见原因现象可能原因处理建议设备列表始终为空定位/蓝牙/NEARBY_WIFI_DEVICESAndroid 13权限缺失start()直接跳过在系统设置补齐权限后重启服务卡住 10 秒后断开带宽未升级到 HIGH射频无法同时维持两个 Wi-Fi 角色两设备同频 Wi-Fi或换 Native/Headunit Server 模式日志报 no inbound payload from phone手机端助手 App 未注册流确认手机端 Wireless Helper 已启动且版本匹配重复点击提示忽略已连接到该端点属正常去重无需处理 核心源码文件导航文件说明NearbyManager.ktNearby 发现与连接全生命周期管理NearbySocket.kt流隧道包装成 Socket含 8 秒有界等待WifiLauncherHelper.ktHelper 模式策略入口隧道就绪后接入 CommManagerHelperStrategy.kt5 种 Helper 连接策略枚举NEARBY 为默认ConnectionStage.kt连接阶段定义SEARCHING→PHONE_ANSWERED→PHONE_JOINING一句话总结NearbyManager 负责找得到、连得上、诊断得出NearbySocket 负责把流伪装成 Socket、把等待限制住。两者配合让 Open Headunit 在开机后几乎零配置就能自动发现并连上你的手机 【免费下载链接】open-headunitHeadunit App for displaying Android Auto项目地址: https://gitcode.com/GitHub_Trending/he/open-headunit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考