蓝牙开发之 IOS AMS

前言

本篇是针对 IOS 的 AMS(Apple Media Service) 进行记录并总结,如果对 ANCS(Apple Notification Center Service) 有兴趣,可以前往我的另一篇推文 蓝牙开发之 IOS ANCS

文章有误或有理解不到位的地方,望不吝指教,我会及时改正错误。

什么是 AMS

效果展示

播放暂停:

播放暂停

进度获取:

进度条

媒体控制:

控制

切换音乐:

切歌

音量加减:

音量

AMS 介绍

AMS 全称 Apple Media Service(苹果媒体服务),是提供给 BLE 设备的一种简单控制媒体应用程序的方式,并且用于获取已连接的 IOS 设备的媒体状态信息。

AMS 字节序和字节码

除非另有规定,否则通过 AMS 传输的所有数值都应是小端格式。
除非另有规定,否则通过 AMS 传输的所有字符串值都应是 UTF-8 编码的 unicode 字符所组成的。

依赖性

除了标准的通用属性配置文件(GATT)子程序集外,AMS 没有任何依赖性。作为 GATT 客户端的设备在使用 AMS 时,可以自由访问和使用 iOS 设备提供的其他服务。

术语

  1. Apple Media Service 称为 AMS
  2. AMS 服务的发布者(也就是我们的 iOS 设备)应被称为媒体源(MS)。
  3. AMS 服务的客户端(也就是我们的蓝牙设备)应被称为媒体控制器(MR)。

下面统一使用 媒体源媒体控制器 来描述 IOS 设备和蓝牙设备。


AMS Service UUID

AMS 主服务(Service) UUID 为 89D3502B-0F36-433A-8EF4-C502AD55F8DC

AMS 服务下的三个特征(Characteristic) UUID:

远程命令(Remote Command)(writeable, notifiable)

9B3C81D8-57B1-4A8A-B8DF-0E56F7CA51C2

实体更新(Entity Update)(writeable with response, notifiable)

2F7CABCE-808D-411F-9A0C-BB92BA96C102

实体属性(Entity Attribute)(readable, writeable)

C6B2F38C-23AB-46D8-A6AB-A3A870BBD5D7

下图展示了媒体源和媒体控制器间的服务设置:

服务设置

  1. 媒体控制器发现媒体源的 AMS 服务和特征
  2. 媒体控制器订阅媒体源实体更新
  3. 媒体控制器向媒体源写入需要监听的实体(EntityID),例如监听歌曲变化等
  4. 当媒体源监听的实体(EntityID)有变动时,会通知其变动内容

AMS Characteristic

实体

AMS 定义了 3 个不同的实体,每个实体都有一组不同的属性:

  • 播放器(Player):当前活跃的媒体应用。该实体属性包括其名称、播放状态和播放音量等。
  • 队列(Queue):当前加载的播放队列。该实体的属性包括其队列数及其随机和重复模式等。
  • 音轨(Track):当前加载的音轨。该实体的属性包括其艺术家、标题和总的播放时间等。
Name Value
EntityIDPlayer 0
EntityIDQueue 1
EntityIDTrack 2
Reserved 3-255

播放器(Player)属性表

Name Value
PlayerAttributeIDName 0
PlayerAttributeIDPlaybackInfo 1
PlayerAttributeIDVolume 2
Reserved 3-255
  • PlayerAttributeIDName:包含应用的名称的字符串
  • PlayerAttributeIDPlaybackInfo:用三个逗号作为分割,分别有:
    • PlaybackState(播放状态):表示播放状态的整数值字符串:
      • PlaybackStatePaused(0):暂停
      • PlaybackStatePlaying(1):播放
      • PlaybackStateRewinding(2):倒带
      • PlaybackStateFastForwarding(3):快进
    • PlaybackRate(播放速率):播放速率的浮点值字符串
    • ElapsedTime(已用时间):一个字符串,表示当前已用时间的浮点值(以秒为单位)
  • PlayerAttributeIDVolume:一个字符串,表示音量的浮点值,范围从(0-1)

通过播放器属性,我们可以获取 PlayerAttributeIDName 当前音乐播放器的字符串,例如 IOS 手机使用的网易云音乐,那么媒体源推送的字符串转换为 unicode 编码后再转成中文,实际上就是“网易云音乐”,同理其他的音乐 APP,也会显示其相应的名称,非音乐 APP 是不会有推送的。

PlayerAttributeIDPlaybackInfo 可以获取对应的播放状态、播放速率以及歌曲经过的时间,例如接收到推送为 49 44 49 46 48 44 55 49 46 49 52 55 表示 1,1.0,71.147,当前状态为播放、速率 1.0、已过时间 71.147 秒。

PlayerAttributeIDVolume 用于获取当前的音量浮点值,音量最大时为 1,最小时为 0,IOS 按一次音量按键,每次递进 0.0625

注:通过上面的信息,我们可以计算出当前经过的时间,公式如下:

CurrentElapsedTime = ElapsedTime + ((TimeNow–TimePlaybackInfoWasReceived) * PlaybackRate)

上方展示的音乐进度条,也是依靠该方式和歌曲总长度计算的

队列(Queue)属性表

Name Value
QueueAttributeIDIndex 0
QueueAttributeIDCount 1
QueueAttributeIDShuffleMode 2
QueueAttributeIDRepeatMode 3
Reserved 4-255
  • QueueAttributeIDIndex:字符串,包含队列索引的整数值,从零开始
  • QueueAttributeIDCount:字符串,包含队列中项目总数的整数值
  • QueueAttributeIDShuffleMode:字符串,包含随机播放模式的整数值
    • ShuffleModeOff(0):非随机模式
    • ShuffleModeOne(1):单曲随机(没见过这种模式)
    • ShuffleModeAll(2):随机播放
  • QueueAttributeIDRepeatMode:字符串,包含重复模式的整数值
    • RepeatModeOff(0):非重复模式
    • RepeatModeOne(1):单曲循环
    • RepeatModeAll(2):列表循环

这一块好理解,就不过多解释了。切换播放器播放模式时,会通知对应的模式变化。

音轨(Track)属性表

Name Value
TrackAttributeIDArtist 0
TrackAttributeIDAlbum 1
TrackAttributeIDTitle 2
TrackAttributeIDDuration 3
Reserved 4-255
  • QueueAttributeIDIndex:字符串,包含艺术家姓名
  • QueueAttributeIDCount:字符串,包含唱片集名称
  • QueueAttributeIDShuffleMode:字符串,包含曲目标题
  • QueueAttributeIDRepeatMode:字符串,包含轨道总持续时间的浮点值(以秒为单位)

这一块包含了歌曲名、歌手名、专辑名称以及当前音乐总时长。音乐时长假设为 03:02,那么媒体控制器接收到的则是 182.000 秒。

媒体服务的典型操作

若媒体控制器订阅了 Track 属性,那么当媒体源播放音乐时,会将 A 音乐的曲名和歌手名推送给媒体控制器,每次有变动时,都会通知媒体控制器。

远程命令(Remote Command)

远程命令这个特征值是用于 媒体控制器 发送给 媒体源 的播放状态特征,例如播放/暂停、音量加/减、上/下一首、循环播放等。

媒体控制器 发送命令格式如下:

Byte Value
1 RemoteCommandID

远程命令

媒体控制器 发现 媒体源 AMS 服务后,可以通过发送控制命令,播放/暂停、音量加/减等操作媒体源播放器

此特性还用于向 媒体控制器 报告当前 媒体源 支持的命令集,当媒体播放器支持的命令列表发生变化时,媒体源 会使用如下所示的格式,在该特征生产一条通知,通知中包括了支持的命令集:

媒体源 返回支持命令集格式如下:

Byte Value
1 RemoteCommandID1
2 RemoteCommandID2
RemoteCommandIDx

RemoteCommandID 对应的命令集:

Name Value
RemoteCommandIDPlay 0
RemoteCommandIDPause 1
RemoteCommandIDTogglePlayPause 2
RemoteCommandIDNextTrack 3
RemoteCommandIDPreviousTrack 4
RemoteCommandIDVolumeUp 5
RemoteCommandIDVolumeDown 6
RemoteCommandIDAdvanceRepeatMode 7
RemoteCommandIDAdvanceShuffleMode 8
RemoteCommandIDSkipForward 9
RemoteCommandIDSkipBackward 10
RemoteCommandIDLikeTrack 11
RemoteCommandIDDislikeTrack 12
RemoteCommandIDBookmarkTrack 13
Reserved 14-255

通过该命令集,我们的蓝牙设备就可以对 IOS 设备的媒体播放器进行控制,该方式的音乐控制,相比较 HID,我觉得更优,因为 HID 控制只能在媒体播放器界面进行控制,模拟按键的方式去控制播放,并且 HID 的方式不能获取歌曲名、歌曲进度等,所以相较下,如果用于控制 IOS 媒体播放器,那么使用 AMS 是最优的方式。

实体更新(Entity Update)

实体更新特性是 媒体控制器 通知 媒体源 其所需实体/属性对的特征,并在发生更改时告知 媒体控制器,例如 媒体源 媒体播放器变动、当前歌曲变更等。

默认情况下,媒体控制器 不会接收有关实体属性的任何信息。所以,为了接收此数据,媒体控制器 首先需要订阅有关实体更新特征的 GATT 通知。然后,媒体控制器 将命令写入实体更新特征,以通知 媒体源 它想知道哪个实体/属性对值。

媒体控制器 发送的实体更新命令的格式如下所示:

  • EntityID:后续属性所对应的实体
  • AttributeID:媒体控制器 所需的属性列表
Byte Value
1 EntityID
2 AttributeID1
3 AttributeID2
AttributeIDx

写入成功后, 媒体控制器 将立即开始获取其监听的实体/属性对的值。

媒体源通知格式如下:

  • EntityID:后续属性所对应的实体。
  • AttributeID:在通知中发送其值的属性。
  • EntityUpdateFlags:一个位掩码,其设置位为 媒体控制器 提供有关通知的特定信息。
  • Value:一个字符串,对应于与给定属性关联的值。
Byte Value
1 EntityID
2 AttributeID
3 EntityUpdateFlags
4… Value

实体属性(Entity Attribute)

实体属性特征是 媒体控制器 检索属性拓展值的特征。理想情况下,仅当实体/属性对的值在相应的实体更新通知中标记为已截断,并且 媒体控制器 希望显示更多关联值时,才应使用此特征。

要检索特定实体/属性对的完整值,媒体控制器 必须先通过写入实体属性特征来发送命令。

实体属性命令的格式如下所示:

Byte Value
1 EntityID
2 AttributeID

检索截断值的完整值

媒体源需要通知的字符过长,则会截断发送给媒体控制器,若媒体控制器需要被截断的部分,则需要通过写入实体属性命令,将被截断的部分发送给媒体控制器。


其他

错误代码(Error Codes)

写入任何特征或读取实体属性时,媒体控制器 可能会收到以下特定于 AMS 的错误代码:

  • 无效状态 (0xA0): 媒体控制器 未正确设置,例如,写入实体更新或实体属性时,未先订阅实体更新特征通知。
  • 无效的命令 (0xA1): 该命令的格式不正确。
  • 缺省属性 (0xA2): 相应属性为空。

结语

关于蓝牙的 IOS AMS 的总结就分享到这里了,如果在文中发现有误,欢迎指出,我会及时修改的,提前感谢🙏!

参阅