Android(安卓)蓝牙耳机 语音输入与播放
16lz
2022-05-17
Android 蓝牙耳机 语音输入与播放
原以为手机连上蓝牙耳机就能录入语音信号,too young to simple.
经过一番搜寻与折腾,找到两种方式:
- AudioManager.startBluetoothSco(true)
- BluetoothHeadset.startVoiceRecognition(BluetoothDevice device)
第一种方式是通过sco,这种方式有个缺点:连接上和释放时会有嘟的一声
第二种方式则没这个缺点
SCO
设置蓝牙权限AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.BROADCAST_STICKY" /><uses-permission android:name="android.permission.BLUETOOTH" />
private AudioManager mAudioManager;@Overrideprotected void onCreate(Bundle savedInstanceState) { mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); //启动蓝牙输入btStart();}//启动蓝牙输入private void btStart() { if (mAudioManager != null) { mAudioManager.setBluetoothScoOn(true); mAudioManager.startBluetoothSco(); }}//停止蓝牙输入--如果不停止,播放语音的时候没声音private void btStop() { if (mAudioManager != null) { mAudioManager.setBluetoothScoOn(false); mAudioManager.stopBluetoothSco(); }}
语音播报用的是百度TTS SDK,如果不调用btStop
停止蓝牙sco,会听不到任何声音。
为了能听到声音,在百度TTS 的回调接口SpeechSynthesizerListener
的合成开始阶段onSynthesizeStart
调用btStop
停止sco
,当语音播放完成onSpeechFinish
之后调用btStart
重新获取语音输入通道。(因为我的app是带语音唤醒功能的,所以要一直让蓝牙耳机采集到输入信号)
package com.twx.poc.voiceprint.baidu.tts;import android.media.AudioManager;import android.util.Log;import com.baidu.tts.client.SpeechError;import com.baidu.tts.client.SpeechSynthesizerListener;import com.twx.poc.voiceprint.util.bluetooth.MyBluetooth;public class SpeechListener implements SpeechSynthesizerListener { private static final String TAG = "SpeechListener"; private AudioManager mAudioManager; public SpeechListener(AudioManager mAudioManager) { this.mAudioManager = mAudioManager; } @Override public void onSynthesizeStart(String s) { Log.i(TAG, "onSynthesizeStart: 开始合成语音..."); btStop(); } @Override public void onSynthesizeDataArrived(String s, byte[] bytes, int i, int i1) { } @Override public void onSynthesizeFinish(String s) { Log.i(TAG, "onSynthesizeStart: 合成语音完成..."); } @Override public void onSpeechStart(String s) { } @Override public void onSpeechProgressChanged(String s, int i) { } @Override public void onSpeechFinish(String s) { Log.i(TAG, "onSpeechFinish: 完成播放"); btStart(); } @Override public void onError(String s, SpeechError speechError) { Log.e(TAG, "onError: 语音播放出错了"+speechError.description ); } private void btStart() { if (mAudioManager != null) { mAudioManager.setBluetoothScoOn(true); mAudioManager.startBluetoothSco(); } } private void btStop() { if (mAudioManager != null) { mAudioManager.setBluetoothScoOn(false); mAudioManager.stopBluetoothSco(); } }}
BluetoothHeadset.startVoiceRecognition
这个方案的好处是连接与释放的时候没有嘟声
参考博文:
- 带蓝牙麦克风的Android语音识别器
- 蓝牙耳机下的语音(输入/识别)及按键监听
权限:在soc方案的基础上加一个
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
创建一个MyBluetooth
类,该类负责获取已连接的蓝牙设备、启动、停止蓝牙语音输入。
package com.twx.poc.voiceprint.util.bluetooth;import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothHeadset;import android.bluetooth.BluetoothManager;import android.bluetooth.BluetoothProfile;import android.content.Context;import java.util.Iterator;import java.util.List;import java.util.Set;public class MyBluetooth { private BluetoothHeadset bluetoothHeadset; private BluetoothDevice btDevice; BluetoothProfile.ServiceListener blueHeadsetListener = new BluetoothProfile.ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if(profile==BluetoothProfile.HEADSET){ bluetoothHeadset=(BluetoothHeadset) proxy; } if (bluetoothHeadset != null) { List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices(); System.out.println("蓝牙已连接...数量"+devices.size()); for (int i = 0; i < devices.size(); i++) { System.out.println("名称: "+devices.get(i).getName()); btDevice = devices.get(i); } //这里启动蓝牙语音输入 start(); } } @Override public void onServiceDisconnected(int profile) { if(profile==BluetoothProfile.HEADSET){ bluetoothHeadset=null; } } }; public void initBlueToothHeadset(Context context,Activity activity){ BluetoothAdapter adapter; //android4.3之前直接用BluetoothAdapter.getDefaultAdapter()就能得到BluetoothAdapter if(android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.JELLY_BEAN_MR2){ adapter=BluetoothAdapter.getDefaultAdapter(); }else { BluetoothManager bm=(BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE); adapter=bm.getAdapter(); } adapter.getProfileProxy(context, blueHeadsetListener, BluetoothProfile.HEADSET); } /** * 蓝牙开始录入语音... */ public void start() { if (btDevice != null) { System.out.println(btDevice.getName()+" 蓝牙开始录入语音..."); bluetoothHeadset.startVoiceRecognition(btDevice); } } /** * 蓝牙停止录入语音... */ public void stop() { if (btDevice != null) { System.out.println(btDevice.getName()+" 蓝牙停止录入语音..."); bluetoothHeadset.stopVoiceRecognition(btDevice); } }}
在activity
中使用MyBluetooth
:
@Overrideprotected void onCreate(Bundle savedInstanceState) { MyBluetooth bluetooth = new MyBluetooth(); //获取已连接的BluetoothDevice并启动蓝牙输入 bluetooth.initBlueToothHeadset(this,this); //百度语音播报回调接口 SpeechListener speechListener = new SpeechListener(bluetooth);}
在SpeechListener
中控制蓝牙耳机的语音输入和释放(为了语音播报能正常进行,必须释放)
public class SpeechListener implements SpeechSynthesizerListener { private static final String TAG = "SpeechListener"; private MyBluetooth bluetooth; public SpeechListener(MyBluetooth bluetooth) { this.bluetooth = bluetooth; } @Override public void onSynthesizeStart(String s) { Log.i(TAG, "onSynthesizeStart: 开始合成语音..."); btStop(); } @Override public void onSynthesizeDataArrived(String s, byte[] bytes, int i, int i1) { } @Override public void onSynthesizeFinish(String s) { Log.i(TAG, "onSynthesizeStart: 合成语音完成..."); } @Override public void onSpeechStart(String s) { } @Override public void onSpeechProgressChanged(String s, int i) { } @Override public void onSpeechFinish(String s) { Log.i(TAG, "onSpeechFinish: 完成播放"); btStart(); } @Override public void onError(String s, SpeechError speechError) { Log.e(TAG, "onError: 语音播放出错了"+speechError.description ); } private void btStart() { if (bluetooth != null) { bluetooth.start(); } } private void btStop() { if (bluetooth != null) { bluetooth.stop(); } }}
更多相关文章
- Android数字签名获取证书指纹(SHA1)
- Android(安卓)8.1隐藏状态栏图标
- Android(安卓)中文API (70) —— BluetoothDevice[蓝牙]
- Android(安卓)输入系统
- Android学习--摘录
- EditText的光标选择(android.text.Selection)&输入指定字符
- 让editView、AutoCompleteTextView开始捕获的焦点
- 阻止一进入页面就弹输入法对话框的方法
- 【Android】Mac系统Android开发环境搭建