android上使用蓝牙设备进行语音输入

2023-05-20,,

主要实现步骤如下:
1.确保已经和蓝牙耳机配对连接上。
2.开启蓝牙信道
AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setBluetoothScoOn(true);
mAudioManager.startBluetoothSco();
3.开启语音识别
4.退出时关闭蓝牙信道
mAudioManager.setBluetoothScoOn(false);
mAudioManager.stopBluetoothSco();
5.额外需要添加的权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY" />  注:部分手机如无此权限会报错
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

以上方法到android5.0以上可能无用

提供另外一种方法

    package com.example.dkdh.testrecord;
    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothHeadset;
    import android.bluetooth.BluetoothProfile;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.media.AudioManager;
    import android.media.MediaPlayer;
    import android.media.MediaRecorder;
    import android.os.Bundle;
    import android.os.Environment;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.example.dkdh.testrecord.util.FucUtil;
    import com.example.dkdh.testrecord.util.JsonParser;
    import com.iflytek.cloud.InitListener;
    import com.iflytek.cloud.RecognizerListener;
    import com.iflytek.cloud.RecognizerResult;
    import com.iflytek.cloud.SpeechConstant;
    import com.iflytek.cloud.SpeechError;
    import com.iflytek.cloud.SpeechRecognizer;
    import com.iflytek.cloud.SpeechUtility;
    import com.iflytek.cloud.ErrorCode;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.List;
    public class MainActivity extends Activity implements View.OnClickListener{
    private final String TAG = MainActivity.class.getSimpleName();
    private final String XF_APP_ID = "xxxxxx";
    BluetoothHeadset headset;
    private Button start,stop;
    private TextView result;
    private AudioManager mAudioManager = null;
    private BluetoothHeadset mBluetoothHeadset;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothDevice mBluetoothDevice;
    private SpeechRecognizer mIat;
    //    // 语音听写UI
    //    private RecognizerDialog mIatDialog;
    //    // 用HashMap存储听写结果
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    SpeechUtility.createUtility(this, SpeechConstant.APPID + "=" + XF_APP_ID);
    result = (TextView)findViewById(R.id.result);
    start = (Button)findViewById(R.id.startRec);
    stop = (Button)findViewById(R.id.stopRec);
    start.setOnClickListener(this);
    stop.setOnClickListener(this);
    mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    mBluetoothAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.HEADSET);
    //        // 初始化识别无UI识别对象
    //        // 使用SpeechRecognizer对象,可根据回调消息自定义界面;第二个参数:本地识别时传mInitListener
    mIat = SpeechRecognizer.createRecognizer(this, mInitListener);
    }
    private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener(){
    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
    if (profile == BluetoothProfile.HEADSET){
    mBluetoothHeadset = (BluetoothHeadset) proxy;
    List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
    if (devices.size()>0){
    mBluetoothDevice = devices.get(0);
    int state = mBluetoothHeadset.getConnectionState(mBluetoothDevice);
    Log.e("==============","headset state:"+state);
    if (state==BluetoothHeadset.STATE_CONNECTED){
    Log.e("=================","bluetooth headset connected");
    }
    }
    }
    }
    @Override
    public void onServiceDisconnected(int profile) {
    if (profile == BluetoothProfile.HEADSET){
    mBluetoothHeadset = null;
    }
    }
    };
    @Override
    public void onClick(View v) {
    switch (v.getId()){
    case R.id.startRec:
    startRecordWav();
    break;
    case R.id.stopRec:
    stopRecordWav();
    break;
    default:
    break;
    }
    }
    /**
    * 识别实时语音
    */
    private void recog(){
    mIatResults.clear();
    // 设置参数
    setParam();
    int ret = 0;
    // 不显示听写对话框
    ret = mIat.startListening(mRecognizerListener);
    if (ret != ErrorCode.SUCCESS) {
    showTip("听写失败,错误码:" + ret);
    } else {
    //                showTip("");
    }
    }
    /**
    * 初始化监听器。
    */
    private InitListener mInitListener = new InitListener() {
    @Override
    public void onInit(int code) {
    Log.i(TAG, "SpeechRecognizer init() code = " + code);
    if (code != ErrorCode.SUCCESS) {
    showTip("初始化失败,错误码:" + code);
    }
    }
    };
    /**
    * 听写监听器。
    */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
    @Override
    public void onBeginOfSpeech() {
    // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
    showTip("开始说话");
    }
    @Override
    public void onError(SpeechError error) {
    // Tips:
    // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
    showTip(error.getPlainDescription(true));
    //            showTip("错误码:10118(您没有说话),可能是录音机权限被禁,请打开应用的录音权限。");
    }
    @Override
    public void onEndOfSpeech() {
    // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
    showTip("结束说话");
    }
    @Override
    public void onResult(RecognizerResult results, boolean isLast) {
    String text = JsonParser.parseIatResult(results.getResultString());
    Log.i(TAG, text);
    showTip(text);
    if(isLast) {
    //TODO 最后的结果
    result.append(text);
    }
    }
    @Override
    public void onVolumeChanged(int volume, byte[] data) {
    //            showTip("当前正在说话,音量大小:" + volume);
    Log.i(TAG,"当前正在说话,音量大小:" + volume);
    Log.i(TAG, "返回音频数据:" + data.length);
    }
    @Override
    public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
    // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
    // 若使用本地能力,会话id为null
    //        if (SpeechEvent.EVENT_SESSION_ID == eventType) {
    //                String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
    //                Log.d(TAG, "session id =" + sid);
    //        }
    }
    };
    /**
    * Toast显示提示
    */
    private void showTip(String str){
    Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
    }
    /**
    * 参数设置
    * @return
    */
    public void setParam(){
    // 清空参数
    mIat.setParameter(SpeechConstant.PARAMS, null);
    // 设置引擎
    mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
    // 设置返回结果格式
    mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
    // 设置语言
    mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
    // 设置语言区域
    mIat.setParameter(SpeechConstant.ACCENT,"mandarin");
    // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
    mIat.setParameter(SpeechConstant.VAD_BOS, "8000");
    // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
    mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
    // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
    mIat.setParameter(SpeechConstant.ASR_PTT, "0");
    // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
    // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
    mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
    mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");
    //       设置录音时长,单位ms
    mIat.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT,"60000");
    //设置音频源,MIC、VOICE_RECOGNITION、VOICE_COMMUNICATION可用,但与不同android系统有关
    mIat.setParameter(SpeechConstant.AUDIO_SOURCE, MediaRecorder.AudioSource.VOICE_COMMUNICATION+"");
    }
    /**
    * 停止录音
    */
    private void stopRecordWav(){
    Log.e(TAG, "停止录音");
    mBluetoothHeadset.stopVoiceRecognition(mBluetoothDevice);
    }
    /**
    * 录音,自主控制录音格式、速率等
    */
    private void startRecordWav(final int source){
    if (!mAudioManager.isBluetoothScoAvailableOffCall()) {
    Log.d(TAG, "系统不支持蓝牙录音");
    return;
    }
    if (mBluetoothHeadset == null){
    Toast.makeText(this, "蓝牙耳机对象null",Toast.LENGTH_SHORT).show();
    return;
    }
    if (mBluetoothDevice!=null){
    mBluetoothHeadset.startVoiceRecognition(mBluetoothDevice);
    }
    IntentFilter audioStateFilter = new IntentFilter();
    audioStateFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
    audioStateFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    registerReceiver(new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)){
    int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,-1);
    if (state==BluetoothHeadset.STATE_AUDIO_CONNECTED){
    Log.e("==============","开始蓝牙语音识别");
    recog();
    unregisterReceiver(this); // 别遗漏
    }
    }
    }
    },audioStateFilter);
    }
    @Override
    protected void onResume(){
    super.onResume();
    }
    }

android上使用蓝牙设备进行语音输入的相关教程结束。

《android上使用蓝牙设备进行语音输入.doc》

下载本文的Word格式文档,以方便收藏与打印。