华为手环耳机模式适配

前言

最近接到一个需求,须要在播放声音时适配华为蓝牙手环,这个手环不一样于其余手环,将手环主机从腕带上取出时,就变成了蓝牙耳机,能够接听电话。如图所示: java

这里为了便于理解,定义两个概念:

  • 手环模式:未将主机从腕带上取出状态
  • 耳机模式:将主机从腕带上取出状态

定位问题

遇到的问题

手环模式下,手机链接手环蓝牙后,声音由听筒播放。less

为何会从听筒中播放?

从手机设置界面观察到,该手环的音频选项在处于手环模式和耳机模式时有不一样的状态,当处于手环模式时,通话音频处于开启状态,媒体音频处于关闭状态,如图: 异步

手环模式
当处于耳机模式时,通话音频和媒体音频均为开启状态
耳机模式
由此咱们能够获得一个重要的线索,若是系统设置能够判断出音频状态,咱们也能够经过代码判断当前蓝牙设备的通话音频和媒体音频的状态。

接下来咱们看代码,在原有的实现中,当有蓝牙设备链接时,会收到链接的广播,而后咱们经过以下代码设置将声音经过蓝牙耳机播放spa

private void chooseBluetooth() {
        audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        audioManager.startBluetoothSco();      // 打开 SCO 类型蓝牙链路
        audioManager.setBluetoothScoOn(true);  // 打开 SCO 类型蓝牙链路
        audioManager.setSpeakerphoneOn(false); // 关闭扬声器
 }
复制代码

audioManagerAudioManager 对象,这里简单介绍一下 audioManager.startBluetoothSco(); 这行代码的意思是打开 SCO 类型蓝牙链路。在蓝牙通讯中,共有两种通讯链路:code

  1. 同步链路 (Synchronous Connection Oriented)
  2. 异步链路 (Asynchronous Connectionless)

同步链路 (SCO) 链接为对称链接,利用保留时隙传送数据包。链接创建后,主设备和从设备能够不被选中就发送SCO数据包。SCO数据包既能够传送话音,也能够传送数据,但在传送数据时,只用于重发被损坏的那部分的数据。主要用来传输对时间要求很高的数据通讯cdn

异步链路(ACL)就是定向发送数据包,它既支持对称链接,也支持不对称链接(既能够一对一,也能够一对多)。主设备负责控制链路带宽,并决定微微网中的每一个从设备能够占用多少带宽和链接的对称性。从设备只有被选中时才能传送数据。ACL链路也支持接收主设备发给微微网中全部从设备的广播消息。对象

那么为何在手环模式下声音会从听筒中播放?这里作出一个猜测,在手环模式下,Android 系统并无主动打开媒体音频,当咱们的程序执行 audioManager.startBluetoothSco(); 时执行失败,致使没法打开蓝牙链路,以后咱们又设置了 audioManager.setSpeakerphoneOn(false); 关闭扬声器,声音天然就从听筒中播放。blog

解决方案

大体思路就是在调用 chooseBluetooth() 以前判断系统是否打开了媒体音频,若是打开了则进行蓝牙播放,不然依然使用扬声器播放,具体判断代码以下:get

boolean isA2dpOn = audioManager.isBluetoothA2dpOn();
复制代码

参考文献

相关文章
相关标签/搜索