android上使用蓝牙设备进行语音输入
主要实现步骤如下:
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上使用蓝牙设备进行语音输入的更多相关文章
- speex编解码在android上实现
以前在应用中使用到了Speex编解码,近来总结了一下Speex在android上的实现.Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式.Speex工程着力于通过提供一个可以替代高性能 ...
- 在Android上使用qemu-user运行可执行文件
在Android上使用qemu-user运行可执行文件 作者:寻禹@阿里聚安全 前言 QEMU简要介绍: QEMU可以解释执行可执行程序.既然QEMU可以解释执行可执行程序,那么QEMU就能够知道执行 ...
- 编译可在Android上运行的qemu user mode
前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...
- 系列篇|编译可在Android上运行的依赖库(一):glib库
前言 这是系列文章,它们由<编译可在Android上运行的glib库>及其他4篇文章组成,这4篇文章在“编译依赖库”一节中列出.由于glib库依赖于其他第三方库,所以需要先将依赖的第三方库 ...
- ZT 理解 Android 上的安全性
理解 Android 上的安全性 http://www.ibm.com/developerworks/cn/xml/x-androidsecurity/ 利用沙箱.应用程序签名和权限增强应用程序安全性 ...
- HoloLens开发手记 - Unity之语音输入
对于HoloLens,语音输入是三大基本输入方式之一,广泛地运用在各种交互中.HoloLens上语音输入有三种形式,分别是: 语音命令 Voice Command 听写 Diction 语法识别 Gr ...
- cocos2dx实现android的对讯飞语音的合成(语言朗读的实现)
事实上非常easy,只是有些细节须要注意. 关于讯飞语音在android上的应用,大家须要自己去下载SDK,然后依照讯飞语音提供的api在自己的android的Demo上执行成功,那东西也相当的简单. ...
- Android:创建耐磨应用 - 语音操作
加入语音处理能力(Adding Voice Capabilities) 语音操作为用户体验可穿戴的重要组成部分,它允许用户快速.免提方式来运行操作. Wear它提供了两种类型的语音操作的: 该系统提供 ...
- 使用OLAMISDK实现一个语音输入数字进行24点计算的iOS程序
前言 在目前的软件应用中,输入方式还是以文字输入方式为主,但是语音输入的方式目前应用的越来越广泛.这是一个利用 Olami SDK 编写的一个24点iOS程序,是通过语音进行输入. Olami SDK ...
随机推荐
- Oracle Profile 的简单说明
1. 查看已经有的oracle 的profile 首先profile的解释 我理解为 是一个 简略的配置文件, 跟linux的 bash文件的配置信息类似 bash_profile . select ...
- Jquery 获取屏幕及滑块及元素的高度及距离
alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(document).height()); //浏览器时下窗口文档的高度 alert($(docum ...
- NOIP2018划水记
// 6次NOIP里最爽的一次 去年的NOIP的游记:https://www.cnblogs.com/GXZlegend/p/7880740.html Day 0 特意请了一天假复习NOIP 实际上是 ...
- Java多线程与线程同步
六.多线程,线程,同步 ①概念: 并行:指两个或多个在时间同一时刻发生(同时发生) 并发:指两个或多个事件在同一时间段内发生 具体概念: 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多 ...
- c++11 decltype
c++11 decltype decltype实际上有点像auto的反函数,auto可以让你声明一个变量,而decltype则可以从一个变量或表达式中得到类型.decltype在C++11标准制定时引 ...
- tomcat Failed creating java C:\Program Files\Java\jre6\bin\client\jvm.dll %1 不是有效的 Win32 应用程序。
jdk版本搞的鬼 请下载64位的jdkj进行安装
- Nginx多进程高并发、低时延、高可靠机制缓存代理中的应用
1. 开发背景 现有开源缓存代理中间件有twemproxy.codis等,其中twemproxy为单进程单线程模型,只支持memcache单机版和redis单机版,都不支持集群版功能. 由于twemp ...
- 循环取月的三位英语名 Jan Feb
CultureInfo ci = new CultureInfo("en-US"); DateTime now = DateTime.Now; for (int i = 0; i ...
- Java后台面试 常见问题
Java后台面试 常见问题 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米.百度.阿里.京东.新浪.CVTE.乐视家的研发岗offer.我找的是java后台开发,把常见的问题分享 ...
- Andrew Ng机器学习课程,第一周作业,python版本
Liner Regression 1.梯度下降算法 Cost Function 对其求导: theta更新函数: 代码如下: from numpy import * import numpy as n ...