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();        }    }}

更多相关文章

  1. Android数字签名获取证书指纹(SHA1)
  2. Android(安卓)8.1隐藏状态栏图标
  3. Android(安卓)中文API (70) —— BluetoothDevice[蓝牙]
  4. Android(安卓)输入系统
  5. Android学习--摘录
  6. EditText的光标选择(android.text.Selection)&输入指定字符
  7. 让editView、AutoCompleteTextView开始捕获的焦点
  8. 阻止一进入页面就弹输入法对话框的方法
  9. 【Android】Mac系统Android开发环境搭建

随机推荐

  1. mall整合Swagger-UI实现在线API文档
  2. mall整合Redis实现缓存功能
  3. mall整合RabbitMQ实现延迟消息
  4. mall整合SpringSecurity和JWT实现认证和
  5. mall整合OSS实现文件上传
  6. mall在Windows环境下的部署
  7. Navicat实用功能:数据备份与结构同步
  8. mall整合SpringSecurity和JWT实现认证和
  9. 让Monad来得更猛烈些吧_Haskell笔记11
  10. mall整合SpringTask实现定时任务