在手表上点击暂停,iPhone 上的音乐随即停止;切换下一首,手表上的歌名也跟着更新。这个看似简单的功能,背后涉及两个不同的问题:控制指令如何到达播放器,播放状态又如何回到手表。
谈到蓝牙音乐控制,很多人首先想到 AVRCP。但对于连接 iPhone 的低功耗配件,Apple 还提供了一条值得了解的路径:Apple Media Service,简称 AMS。
AMS 是 Apple 定义并公开文档化的 BLE/GATT 服务,允许外部配件控制 iOS 媒体播放,并获取相关状态。对于以“播放、暂停、切歌、显示当前曲目”为目标的手表,它提供了直接的协议入口。Apple AMS 官方介绍
理解 AMS,首先要明确代码应该运行在哪里。Apple 将提供服务的 iOS 设备称为 Media Source(MS) ,将访问服务的配件称为 Media Remote(MR) 。对应到 GATT,iPhone 是服务端,手表是客户端。
手表固件:AMS Client
⇅
BLE / GATT
⇅
iPhone 系统:AMS Server
⇅
当前媒体播放器
因此,手表固件需要发现并访问 iPhone 提供的 AMS 服务。如果反过来,在手表上创建同名服务,再等待 iPhone 向它写入播放状态,交互方向就错了。
GATT 客户端也不意味着手表必须主动扫描并连接手机。蓝牙连接角色与 GATT 访问角色属于不同层次。Nordic 的官方示例就叫作 Peripheral AMS client:设备可以承担 Peripheral 连接角色,同时访问对端的 AMS 服务。Nordic 官方实现示例
这条路径也解释了配套 App 的职责边界。AMS 控制指令由配件直接交给 iOS 系统,不要求配套 App 逐条转发。 配套 App 仍可能负责发现、配置、建立连接和其他业务,但这些工作应与媒体控制通道分开设计。
对于音乐 App,公开的 MPRemoteCommandCenter 用于接收来自系统控件和外部配件的控制事件。它与 AMS 处于不同层面,也不等于给配套 App 提供了任意控制其他播放器的权限。Apple MPRemoteCommandCenter 文档
AMS 的协议结构比较紧凑。其服务 UUID 为:
89D3502B-0F36-433A-8EF4-C502AD55F8DC
主要交互通过三个特征完成:
| 特征 | 职责 |
|---|---|
| Remote Command | 发送播放控制命令,接收当前支持的命令列表 |
| Entity Update | 注册关注的属性,接收属性变化通知 |
| Entity Attribute | 读取在通知中被截断的完整属性值 |
可以将其理解为三个入口:发指令、收更新、补读长内容。实际接入时,应发现并检查可用特征,而不是假定所有特征必然存在。Apple AMS 服务规范
控制命令采用单字节 ID。例如,播放是 0x00,暂停是 0x01,播放/暂停切换是 0x02,下一首和上一首分别是 0x03、0x04。协议还定义了音量增减、随机与循环模式切换等操作。
命令是否可用,需要以当前播放器报告的能力为准。 手表界面不应因为协议定义了某个命令,就始终显示对应按钮。
媒体信息则分为三个实体:
| 实体 | 提供的信息 |
|---|---|
| Player | 播放器名称、播放状态、播放速度、已播放时间、音量 |
| Queue | 当前队列位置、曲目数量、随机和循环模式 |
| Track | 歌手、专辑、歌名、总时长 |
这里有一个容易误解的地方:Queue 提供的是队列属性,不是完整的播放列表内容。知道当前播放第几首、队列共有多少首,并不代表能读取每首歌的名称并任意点播。Apple 命令与属性定义
以显示当前曲目为例,配件建立连接并完成所需的安全建立流程后,发现 AMS、订阅通知,再声明需要哪些属性。订阅歌手、专辑、歌名和时长时,向 Entity Update 写入:
02 00 01 02 03
│ │ │ │ └─ 时长
│ │ │ └──── 歌名
│ │ └─────── 专辑
│ └────────── 歌手
└───────────── Track 实体
订阅播放器名称、播放信息和音量,则写入:
00 00 01 02
Nordic 的示例展示了这些字节序列,以及通过开发板按钮触发播放、暂停和切歌的验证流程。它可以作为理解“固件操作如何映射到 AMS 交互”的参考。Nordic 示例:初始化与属性订阅
长歌名还需要额外处理。属性通知包含实体、属性、标志和文本值;当文本被标记为截断时,配件应通过 Entity Attribute 选择目标属性,再读取完整内容。只处理普通通知,可能让较长的歌名或专辑名显示不完整。Apple 属性更新与读取流程
播放进度也不需要每秒向手机查询。AMS 的播放信息包含播放速度和已播放时间,手表可以根据接收后的本地时间推算进度,再用后续状态更新校正。
例如,属性值 1,1.0,42.5 表示正在播放、正常速度、发送时已播放 42.5 秒。若接收后经过约 3 秒,界面可以估算进度为约 45.5 秒。这种方式适合低功耗设备,但能够显示进度,不代表协议提供了拖动到任意时间点的控制命令。Apple 播放信息与进度计算说明
从原型走向产品,真正需要投入精力的是状态一致性。Apple 明确指出:命令写入成功,只代表命令已经转交播放器,不保证播放器执行了动作。 AMS 本身也不保证始终存在,配件应关注 GATT 的 Service Changed,处理服务发布和撤销。Apple 服务生命周期与命令语义
基于这些约束,实现时可以采用以下策略:
- 区分“已发送”和“已生效”。 用户点击后可以显示短暂反馈,最终播放状态仍由回报校正。
- 谨慎重试切换类命令。 播放/暂停切换若被执行两次,可能回到原来的状态;超时不能简单等同于执行失败。
- 重连后重新确认状态。 检查服务、特征、能力与订阅,避免继续显示断线前的旧曲目。
- 串行执行长属性读取。 将“选择属性—读取属性”作为完整操作调度,防止并发请求相互覆盖目标。
测试也应覆盖用户真实会遇到的变化:锁屏、暂停、拖动进度、切换播放器、长中文歌名、手机与手表短暂失联。若日志分别记录用户操作、GATT 写入结果和后续状态回报,就更容易判断问题发生在连接、协议还是播放器响应阶段。
AMS 的适用范围也需要在产品设计时明确。公开接口没有定义封面传输、完整媒体库浏览、按曲目 ID 任意选歌、指定控制某个 App,以及设置任意播放时间或绝对音量的操作。若产品需要这些能力,应单独寻找适用接口并验证,而不能从基础遥控能力推导出来。Apple AMS 接口全集
Apple 的 AMS 文档目前位于 Documentation Archive,页面标注的更新时间为 2014 年 9 月 17 日。接入时应以公开规范为起点,并在明确的 iPhone、iOS 和播放器版本组合上验证。协议存在、固件实现正确与目标产品体验稳定,是需要分别确认的三件事。
对于一块主要承担手机音乐遥控的 BLE 手表,合理的第一步是跑通一条最小链路:发现 AMS、订阅歌名与播放状态、发送播放/暂停命令,再验证断线恢复。 当这条链路可靠后,再逐步增加进度显示、音量控制和播放器能力适配,技术范围和验收标准都会更清晰。