显示许可

BluetoothHelper extends BluetoothHeadSetUtils在你的Activity或中创建一个内部类Service。声明一个类成员mBluetoothHelper并将其实例化onCreate()BluetoothHelper mBluetoothHelper;@Overridepublic void onCreate(){

mBluetoothHelper = new BluetoothHelper(this);}  @OverrideonResume(){

mBluetoothHelper.start();}@OverrideonPause(){

mBluetoothHelper.stop();}// inner class// BluetoothHeadsetUtils is an abstract class that has// 4 abstracts methods that need to be implemented.private class BluetoothHelper extends BluetoothHeadSetUtils{

public BluetoothHelper(Context context)

{

super(context);

}

@Override

public void onScoAudioDisconnected()

{

// Cancel speech recognizer if desired

}

@Override

public void onScoAudioConnected()

{

// Should start speech recognition here if not already started

}

@Override

public void onHeadsetDisconnected()

{

}

@Override

public void onHeadsetConnected()

{

}}

要将蓝牙耳机与文本转语音一起使用,您需要在调用speak之前将AudioManager设置为STREAM_VOICE_CALL。或者使用下面的代码protected void speak(String text){

HashMap myHashRender = new HashMap();

if (mBluetoothHelper.isOnHeadsetSco())

{

myHashRender.put(TextToSpeech.Engine.KEY_PARAM_STREAM,

String.valueOf(AudioManager.STREAM_VOICE_CALL));

}

mTts.speak(text, TextToSpeech.QUEUE_FLUSH, myHashRender);}

将BluetoothHeadsetUtils类复制到您的项目中。import java.util.List;import android.annotation.SuppressLint;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothClass;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.os.Build;import android.os.CountDownTimer;import android.util.Log;/**

* This is a utility to detect bluetooth headset connection and establish audio connection

* for android API >= 8. This includes a work around for  API

* before the application starts. This work around would only fails if Sco audio

* connection is accepted but the connected device is not a headset.

*

* @author Hoan Nguyen

*

*/public abstract class BluetoothHeadsetUtils{

private  Context mContext;

private BluetoothAdapter mBluetoothAdapter;

private BluetoothHeadset mBluetoothHeadset;

private BluetoothDevice mConnectedHeadset;

private AudioManager mAudioManager;

private boolean mIsCountDownOn;

private boolean mIsStarting;

private boolean mIsOnHeadsetSco;

private boolean mIsStarted;

private static final String TAG = "BluetoothHeadsetUtils"; //$NON-NLS-1$

/**

* Constructor

* @param context

*/

public BluetoothHeadsetUtils(Context context)

{

mContext = context;

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

}

/**

* Call this to start BluetoothHeadsetUtils functionalities.

* @return  The return value of startBluetooth() or startBluetooth11()

*/

public boolean start()

{

if (!mIsStarted)

{

mIsStarted = true;

if (Build.VERSION.SDK_INT

{

mIsStarted = startBluetooth();

}

else

{

mIsStarted = startBluetooth11();

}

}

return mIsStarted;

}

/**

* Should call this on onResume or onDestroy.

* Unregister broadcast receivers and stop Sco audio connection

* and cancel count down.

*/

public void stop()

{

if (mIsStarted)

{

mIsStarted = false;

if (Build.VERSION.SDK_INT

{

stopBluetooth();

}

else

{

stopBluetooth11();

}

}

}

/**

*

* @return  true if audio is connected through headset.

*/

public boolean isOnHeadsetSco()

{

return mIsOnHeadsetSco;

}

public abstract void onHeadsetDisconnected();

public abstract void onHeadsetConnected();

public abstract void onScoAudioDisconnected();

public abstract void onScoAudioConnected();

/**

* Register for bluetooth headset connection states and Sco audio states.

* Try to connect to bluetooth headset audio by calling startBluetoothSco().

* This is a work around for API

* the application starts.

*

* The official documentation for startBluetoothSco() states

*

* "This method can be used by applications wanting to send and received audio to/from

*  a bluetooth SCO headset while the phone is not in call."

*

* Does this mean that startBluetoothSco() would fail if the connected bluetooth device

* is not a headset?

*

* Thus if a call to startBluetoothSco() is successful, i.e mBroadcastReceiver will receive

* an ACTION_SCO_AUDIO_STATE_CHANGED with intent extra SCO_AUDIO_STATE_CONNECTED, then

* we assume that a headset is connected.

*

* @return  false if device does not support bluetooth or current platform does not supports

*                use of SCO for off call.

*/

@SuppressWarnings("deprecation")

private boolean startBluetooth()

{

Log.d(TAG, "startBluetooth"); //$NON-NLS-1$

// Device support bluetooth

if (mBluetoothAdapter != null)

{

if (mAudioManager.isBluetoothScoAvailableOffCall())

{

mContext.registerReceiver(mBroadcastReceiver,

new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));

mContext.registerReceiver(mBroadcastReceiver,

new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));

mContext.registerReceiver(mBroadcastReceiver,

new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));

// Need to set audio mode to MODE_IN_CALL for call to startBluetoothSco() to succeed.

mAudioManager.setMode(AudioManager.MODE_IN_CALL);

mIsCountDownOn = true;

// mCountDown repeatedly tries to start bluetooth Sco audio connection.

mCountDown.start();

// need for audio sco, see mBroadcastReceiver

mIsStarting = true;

return true;

}

}

return false;

}

/**

* Register a headset profile listener

* @return false    if device does not support bluetooth or current platform does not supports

*                  use of SCO for off call or error in getting profile proxy.

*/

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

private boolean startBluetooth11()

{

Log.d(TAG, "startBluetooth11"); //$NON-NLS-1$

// Device support bluetooth

if (mBluetoothAdapter != null)

{

if (mAudioManager.isBluetoothScoAvailableOffCall())

{

// All the detection and audio connection are done in mHeadsetProfileListener

if (mBluetoothAdapter.getProfileProxy(mContext,

mHeadsetProfileListener,

BluetoothProfile.HEADSET))

{

return true;

}

}

}

return false;

}

/**

* API

* Unregister broadcast receivers and stop Sco audio connection

* and cancel count down.

*/

private void stopBluetooth()

{

Log.d(TAG, "stopBluetooth"); //$NON-NLS-1$

if (mIsCountDownOn)

{

mIsCountDownOn = false;

mCountDown.cancel();

}

// Need to stop Sco audio connection here when the app

// change orientation or close with headset still turns on.

mContext.unregisterReceiver(mBroadcastReceiver);

mAudioManager.stopBluetoothSco();

mAudioManager.setMode(AudioManager.MODE_NORMAL);

}

/**

* API >= 11

* Unregister broadcast receivers and stop Sco audio connection

* and cancel count down.

*/

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

protected void stopBluetooth11()

{

Log.d(TAG, "stopBluetooth11"); //$NON-NLS-1$

if (mIsCountDownOn)

{

mIsCountDownOn = false;

mCountDown11.cancel();

}

if (mBluetoothHeadset != null)

{

// Need to call stopVoiceRecognition here when the app

// change orientation or close with headset still turns on.

mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);

mContext.unregisterReceiver(mHeadsetBroadcastReceiver);

mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);

mBluetoothHeadset = null;

}

}

/**

* Broadcast receiver for API

* Handle headset and Sco audio connection states.

*/

private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()

{

@SuppressWarnings({"deprecation", "synthetic-access"})

@Override

public void onReceive(Context context, Intent intent)

{

String action = intent.getAction();

if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED))

{

mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

BluetoothClass bluetoothClass = mConnectedHeadset.getBluetoothClass();

if (bluetoothClass != null)

{

// Check if device is a headset. Besides the 2 below, are there other

// device classes also qualified as headset?

int deviceClass = bluetoothClass.getDeviceClass();

if (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE

|| deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)

{

// start bluetooth Sco audio connection.

// Calling startBluetoothSco() always returns faIL here,

// that why a count down timer is implemented to call

// startBluetoothSco() in the onTick.

mAudioManager.setMode(AudioManager.MODE_IN_CALL);

mIsCountDownOn = true;

mCountDown.start();

// override this if you want to do other thing when the device is connected.

onHeadsetConnected();

}

}

Log.d(TAG, mConnectedHeadset.getName() + " connected"); //$NON-NLS-1$

}

else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))

{

Log.d(TAG, "Headset disconnected"); //$NON-NLS-1$

if (mIsCountDownOn)

{

mIsCountDownOn = false;

mCountDown.cancel();

}

mAudioManager.setMode(AudioManager.MODE_NORMAL);

// override this if you want to do other thing when the device is disconnected.

onHeadsetDisconnected();

}

else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED))

{

int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,

AudioManager.SCO_AUDIO_STATE_ERROR);

if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED)

{

mIsOnHeadsetSco = true;

if (mIsStarting)

{

// When the device is connected before the application starts,

// ACTION_ACL_CONNECTED will not be received, so call onHeadsetConnected here

mIsStarting = false;

onHeadsetConnected();

}

if (mIsCountDownOn)

{

mIsCountDownOn = false;

mCountDown.cancel();

}

// override this if you want to do other thing when Sco audio is connected.

onScoAudioConnected();

Log.d(TAG, "Sco connected"); //$NON-NLS-1$

}

else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED)

{

Log.d(TAG, "Sco disconnected"); //$NON-NLS-1$

// Always receive SCO_AUDIO_STATE_DISCONNECTED on call to startBluetooth()

// which at that stage we do not want to do anything. Thus the if condition.

if (!mIsStarting)

{

mIsOnHeadsetSco = false;

// Need to call stopBluetoothSco(), otherwise startBluetoothSco()

// will not be successful.

mAudioManager.stopBluetoothSco();

// override this if you want to do other thing when Sco audio is disconnected.

onScoAudioDisconnected();

}

}

}

}

};

/**

* API

* Try to connect to audio headset in onTick.

*/

private CountDownTimer mCountDown = new CountDownTimer(10000, 1000)

{

@SuppressWarnings("synthetic-access")

@Override

public void onTick(long millisUntilFinished)

{

// When this call is successful, this count down timer will be canceled.

mAudioManager.startBluetoothSco();

Log.d(TAG, "\nonTick start bluetooth Sco"); //$NON-NLS-1$

}

@SuppressWarnings("synthetic-access")

@Override

public void onFinish()

{

// Calls to startBluetoothSco() in onStick are not successful.

// Should implement something to inform user of this failure

mIsCountDownOn = false;

mAudioManager.setMode(AudioManager.MODE_NORMAL);

Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$

}

};

/**

* API >= 11

* Check for already connected headset and if so start audio connection.

* Register for broadcast of headset and Sco audio connection states.

*/

private BluetoothProfile.ServiceListener mHeadsetProfileListener = new BluetoothProfile.ServiceListener()

{

/**

* This method is never called, even when we closeProfileProxy on onPause.

* When or will it ever be called???

*/

@Override

public void onServiceDisconnected(int profile)

{

Log.d(TAG, "Profile listener onServiceDisconnected"); //$NON-NLS-1$

stopBluetooth11();

}

@SuppressWarnings("synthetic-access")

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

@Override

public void onServiceConnected(int profile, BluetoothProfile proxy)

{

Log.d(TAG, "Profile listener onServiceConnected"); //$NON-NLS-1$

// mBluetoothHeadset is just a headset profile,

// it does not represent a headset device.

mBluetoothHeadset = (BluetoothHeadset) proxy;

// If a headset is connected before this application starts,

// ACTION_CONNECTION_STATE_CHANGED will not be broadcast.

// So we need to check for already connected headset.

List devices = mBluetoothHeadset.getConnectedDevices();

if (devices.size() > 0)

{

// Only one headset can be connected at a time,

// so the connected headset is at index 0.

mConnectedHeadset = devices.get(0);

onHeadsetConnected();

// Should not need count down timer, but just in case.

// See comment below in mHeadsetBroadcastReceiver onReceive()

mIsCountDownOn = true;

mCountDown11.start();

Log.d(TAG, "Start count down"); //$NON-NLS-1$

}

// During the active life time of the app, a user may turn on and off the headset.

// So register for broadcast of connection states.

mContext.registerReceiver(mHeadsetBroadcastReceiver,

new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));

// Calling startVoiceRecognition does not result in immediate audio connection.

// So register for broadcast of audio connection states. This broadcast will

// only be sent if startVoiceRecognition returns true.

mContext.registerReceiver(mHeadsetBroadcastReceiver,

new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));

}

};

/**

*  API >= 11

*  Handle headset and Sco audio connection states.

*/

private BroadcastReceiver mHeadsetBroadcastReceiver = new BroadcastReceiver()

{

@SuppressWarnings("synthetic-access")

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

@Override

public void onReceive(Context context, Intent intent)

{

String action = intent.getAction();

int state;

if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED))

{

state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,

BluetoothHeadset.STATE_DISCONNECTED);

Log.d(TAG, "\nAction = " + action + "\nState = " + state); //$NON-NLS-1$ //$NON-NLS-2$

if (state == BluetoothHeadset.STATE_CONNECTED)

{

mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

// Calling startVoiceRecognition always returns false here,

// that why a count down timer is implemented to call

// startVoiceRecognition in the onTick.

mIsCountDownOn = true;

mCountDown11.start();

// override this if you want to do other thing when the device is connected.

onHeadsetConnected();

Log.d(TAG, "Start count down"); //$NON-NLS-1$

}

else if (state == BluetoothHeadset.STATE_DISCONNECTED)

{

// Calling stopVoiceRecognition always returns false here

// as it should since the headset is no longer connected.

if (mIsCountDownOn)

{

mIsCountDownOn = false;

mCountDown11.cancel();

}

mConnectedHeadset = null;

// override this if you want to do other thing when the device is disconnected.

onHeadsetDisconnected();

Log.d(TAG, "Headset disconnected"); //$NON-NLS-1$

}

}

else // audio

{

state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);

Log.d(TAG, "\nAction = " + action + "\nState = " + state); //$NON-NLS-1$ //$NON-NLS-2$

if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED)

{

Log.d(TAG, "\nHeadset audio connected");  //$NON-NLS-1$

mIsOnHeadsetSco = true;

if (mIsCountDownOn)

{

mIsCountDownOn = false;

mCountDown11.cancel();

}

// override this if you want to do other thing when headset audio is connected.

onScoAudioConnected();

}

else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED)

{

mIsOnHeadsetSco = false;

// The headset audio is disconnected, but calling

// stopVoiceRecognition always returns true here.

mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);

// override this if you want to do other thing when headset audio is disconnected.

onScoAudioDisconnected();

Log.d(TAG, "Headset audio disconnected"); //$NON-NLS-1$

}

}

}

};

/**

* API >= 11

* Try to connect to audio headset in onTick.

*/

private CountDownTimer mCountDown11 = new CountDownTimer(10000, 1000)

{

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

@SuppressWarnings("synthetic-access")

@Override

public void onTick(long millisUntilFinished)

{

// First stick calls always returns false. The second stick

// always returns true if the countDownInterval is set to 1000.

// It is somewhere in between 500 to a 1000.

mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset);

Log.d(TAG, "onTick startVoiceRecognition"); //$NON-NLS-1$

}

@SuppressWarnings("synthetic-access")

@Override

public void onFinish()

{

// Calls to startVoiceRecognition in onStick are not successful.

// Should implement something to inform user of this failure

mIsCountDownOn = false;

Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$

}

};}

(2013年4月30日)编辑以在必要时更改为@TargetApi(Build.VERSION_CODES.HONEYCOMB)。如果您对API 8或9的java.lang.NoClassDefFoundError有问题,只需删除所有API> = 11代码。startBluetoothSco()适用于所有API版本。

android 蓝牙耳机 sco,使用Android识别器内置蓝牙耳机相关推荐

  1. unity android 宏定义,Unity各平台内置宏定义

    属性 方法 UNITY_EDITOR #define directive for calling Unity Editor scripts from your game code. UNITY_EDI ...

  2. android 10.0 展讯 MTK内置可卸载app

    1.概述 在进行10.0的产品定制化开发中,展讯内置可卸载恢复的app 其实把apk编译到system/proloadapp 目录下即可 2.展讯 MTK内置可卸载app的实现步骤 实现方式: 1 预 ...

  3. android文件恢复功能,安卓设备内置存储中已删除的文件如何恢复

    在开始之前先介绍一些数据恢复方面的基础知识: 想必大家在平常使用可存储设备(包括电脑.手机.U盘.移动硬盘等等)都会有遇到这种情况:不小心删除(包括直接删除.清空回收站.格式化.重新分区等)了一些存储 ...

  4. Android获取手机中外置内存卡 内置内存卡 手机内存路径

    http://www.open-open.com/code/view/1433585940578 首先内部存储路径为/data/data/youPackageName/,下面讲解的各路径都是基于你自己 ...

  5. Android系统之路(初识MTK) ------ 内置三方apk到Rom可移动/可卸载

    客户给了一个内置他们自己apk的需求,定制到Rom里,我们需要在编译系统源码的时候配置好相关的文件即可将apk一起打包到ROM里面,下面我们就来一起打包apk到系统 首先需要在 device/medi ...

  6. Android中实现系统声音录制(内置声源的录制)-音频通道及framework调用流程分析

    推荐阅读 Android Audio音频系统 Android Framework学习路线

  7. android 蓝牙耳机 sco,java – Android:通过Sco蓝牙耳机播放声音

    在过去的几天里,我一直试图从我的 Android手机上播放我的sco蓝牙耳机上的任何声音.我这个项目的最终目标是最终制作一个车库门开启器,但首先我需要能够通过耳机播放声音. 这是我正在使用的当前代码的 ...

  8. Android语音便签快速调用-内置录音程序

    来源:http://www.android123.com.cn/androidkaifa/668.html Android平台下图表绘制相关方法 作者: Android开发网原创 时间: 2010-1 ...

  9. tcl电视原生android,TCL电视免ROOT精简内置应用教程分享,亲测可换当贝桌面

    本帖最后由 科技小白兔 于 2020-4-17 10:11 编辑 前言:各位old铁们,我又来了,这次小白兔分享的是关于TCL电视的免root精简应用,该方法适用于能够用利用"tclsu&q ...

最新文章

  1. 自定义View的三种构造方法
  2. puppet 执行source
  3. RouterOS配置脚本
  4. ESP8266的网状网络(Mesh Network)
  5. C#(9)——API调用
  6. 关于UIEdgeInsetsMake
  7. 浅谈JSP表单中的form传值
  8. python-格化输出format方法
  9. 【Python】字符串(String)
  10. 如何在maven repository手动下载jar包
  11. 别吹了!程序员自学Python,不如9岁小孩,网友:我不服.... ​
  12. mysql 去重 性能比较_mysql 去重方法distinct 与 group by 性能比较 | 学步园
  13. GPS 入门 5 —— 定位误差产生的原因和差分定位原理 (转)
  14. simulink简介
  15. 计算机格式怎么调,怎么改电脑硬盘格式?
  16. 读书笔记-别做正常的傻瓜
  17. sass 转换为 css
  18. 前端工资涨不上去?可能是你没掌握构建工具:关于 Webpack、Babel、esbuild、Vite、Rollup、Parcel、SWC......的那些事
  19. 某电子订单系统升级步骤
  20. conda创建虚拟环境

热门文章

  1. 腾讯企业IT部安全运营中心总监蔡晨:十年沉淀,腾讯iOA为企业安全保驾护航...
  2. 网络编程(32)—— linux中销毁僵尸进程的四种方法
  3. 互斥锁属性PTHREAD_MUTEX_RECURSIVE
  4. Dubbo 一篇文章就够了:从入门到实战
  5. 对象的克隆——原型模式
  6. Spark _15 _广播变量和累加器
  7. 解决idea maven的导入依赖过慢
  8. 【Python】from __future__ import absolute_import的作用
  9. 关于Storm Tick
  10. 如何解决分布式系统中的“幽灵复现”?-转载自 阿里技术 微信公众号