最近接到一个需求,须要在播放声音时适配华为蓝牙手环,这个手环不一样于其余手环,将手环主机从腕带上取出时,就变成了蓝牙耳机,能够接听电话。如图所示: java
手环模式下,手机链接手环蓝牙后,声音由听筒播放。less
从手机设置界面观察到,该手环的音频选项在处于手环模式和耳机模式时有不一样的状态,当处于手环模式时,通话音频处于开启状态,媒体音频处于关闭状态,如图: 异步
接下来咱们看代码,在原有的实现中,当有蓝牙设备链接时,会收到链接的广播,而后咱们经过以下代码设置将声音经过蓝牙耳机播放spa
private void chooseBluetooth() {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.startBluetoothSco(); // 打开 SCO 类型蓝牙链路
audioManager.setBluetoothScoOn(true); // 打开 SCO 类型蓝牙链路
audioManager.setSpeakerphoneOn(false); // 关闭扬声器
}
复制代码
audioManager
即 AudioManager
对象,这里简单介绍一下 audioManager.startBluetoothSco(); 这行代码的意思是打开 SCO 类型蓝牙链路。在蓝牙通讯中,共有两种通讯链路:code
同步链路 (SCO) 链接为对称链接,利用保留时隙传送数据包。链接创建后,主设备和从设备能够不被选中就发送SCO数据包。SCO数据包既能够传送话音,也能够传送数据,但在传送数据时,只用于重发被损坏的那部分的数据。主要用来传输对时间要求很高的数据通讯cdn
异步链路(ACL)就是定向发送数据包,它既支持对称链接,也支持不对称链接(既能够一对一,也能够一对多)。主设备负责控制链路带宽,并决定微微网中的每一个从设备能够占用多少带宽和链接的对称性。从设备只有被选中时才能传送数据。ACL链路也支持接收主设备发给微微网中全部从设备的广播消息。对象
那么为何在手环模式下声音会从听筒中播放?这里作出一个猜测,在手环模式下,Android 系统并无主动打开媒体音频,当咱们的程序执行 audioManager.startBluetoothSco();
时执行失败,致使没法打开蓝牙链路,以后咱们又设置了 audioManager.setSpeakerphoneOn(false);
关闭扬声器,声音天然就从听筒中播放。blog
大体思路就是在调用 chooseBluetooth()
以前判断系统是否打开了媒体音频,若是打开了则进行蓝牙播放,不然依然使用扬声器播放,具体判断代码以下:get
boolean isA2dpOn = audioManager.isBluetoothA2dpOn();
复制代码