Android 蓝牙SCO在来电后失败
我正在尝试通过SCO发送应用程序的所有音频 我能够成功地发送音频 但当来电时,我需要断开与SCO的连接,以便应用程序音频不会干扰呼叫 问题是,当我尝试在通话后将音频重新路由到SCO时,它不起作用 以下是我用来向SCO发送音频的代码:Android 蓝牙SCO在来电后失败,android,bluetooth,bluetooth-sco,Android,Bluetooth,Bluetooth Sco,我正在尝试通过SCO发送应用程序的所有音频 我能够成功地发送音频 但当来电时,我需要断开与SCO的连接,以便应用程序音频不会干扰呼叫 问题是,当我尝试在通话后将音频重新路由到SCO时,它不起作用 以下是我用来向SCO发送音频的代码: public class BluetoothManager { // For Bluetooth connectvity private static String TAG = "BluetoothManager"; private static Bluetooth
public class BluetoothManager {
// For Bluetooth connectvity
private static String TAG = "BluetoothManager";
private static BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private static AudioManager aM;
/**
* Set the audio manager of the device.
* @param c: The context this method is called from
*/
public static void setAudioManager(Context c) {
aM = (android.media.AudioManager)c.getSystemService(Context.AUDIO_SERVICE);
}
/**
* Check if a Bluetooth headset is connected. If so, route audio to Bluetooth SCO.
*/
private static void initializeAudioMode(Context context) {
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
BluetoothHeadset bh = (BluetoothHeadset) proxy;
List<BluetoothDevice> devices = bh.getConnectedDevices();
if (devices.size() > 0) {
enableBluetoothSCO();
}
}
mBluetoothAdapter.closeProfileProxy(profile, proxy);
}
public void onServiceDisconnected(int profile) {}
};
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
}
/**
* Bluetooth Connectvity
* The following methods are associated with enabling/disabling Bluetooth.
* In the future we may want to disable other sources of audio.
*/
private static void enableBluetoothSCO() {
aM.setMode(AudioManager.MODE_IN_CALL);
aM.startBluetoothSco();
aM.setBluetoothScoOn(true);
}
/** Right now, this simply enables Bluetooth */
@SuppressLint("NewApi")
public static boolean enableBluetooth(Context c) {
// If there is an adapter, enable it if not already enabled
if (mBluetoothAdapter != null) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
setAudioManager(c);
initializeAudioMode(c);
Log.e(TAG, "SCO: " + aM.isBluetoothScoOn());
Log.e(TAG, "A2DP: " + aM.isSpeakerphoneOn());
return true;
} else {
Log.v(TAG, "There is no bluetooth adapter");
return false;
}
}
/** Right now, this simply disables Bluetooth */
public static void disableBluetooth() {
// If there is an adapter, disabled it if not already disabled
if (mBluetoothAdapter != null) {
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
}
} else {
Log.v(TAG, "There is no bluetooth adapter");
}
}
public static void restartBluetooth(){
aM.setMode(AudioManager.MODE_IN_CALL);
}
public static void stopBluetooth(){
aM.setMode(AudioManager.MODE_NORMAL);
}
}
公共类BluetoothManager{
//蓝牙连接
私有静态字符串TAG=“BluetoothManager”;
私有静态BluetoothAdapter mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
专用静态音频管理器aM;
/**
*设置设备的音频管理器。
*@param c:调用此方法的上下文
*/
公共静态void setAudioManager(上下文c){
aM=(android.media.AudioManager)c.getSystemService(Context.AUDIO\u服务);
}
/**
*检查蓝牙耳机是否已连接。如果已连接,请将音频路由到蓝牙SCO。
*/
私有静态void initializeAudioMode(上下文){
BluetoothProfile.ServiceListener mProfileListener=新的BluetoothProfile.ServiceListener(){
服务连接上的公共void(int配置文件、Bluetooth配置文件代理){
if(情景模式==蓝牙情景模式.耳机){
蓝牙耳机bh=(蓝牙耳机)代理;
List devices=bh.getConnectedDevices();
如果(devices.size()>0){
enableBluetoothSCO();
}
}
mBluetoothAdapter.closeProfileProxy(profile,proxy);
}
服务断开连接(int配置文件){}
};
getProfileProxy(上下文、mProfileListener、蓝牙模式、耳机);
}
/**
*蓝牙连接
*以下方法与启用/禁用蓝牙相关。
*将来,我们可能希望禁用其他音频源。
*/
私有静态void启用bluetoothsco(){
aM.setMode(AudioManager.MODE在通话中);
aM.startBluetoothSco();
aM.setBluetoothScoOn(真);
}
/**现在,这只是启用蓝牙*/
@SuppressLint(“新API”)
公共静态布尔启用蓝牙(上下文c){
//如果有适配器,请启用它(如果尚未启用)
if(mBluetoothAdapter!=null){
如果(!mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.enable();
}
音乐经理(c);
初始化模式(c);
Log.e(标记“SCO:+aM.isBluetoothScoOn());
Log.e(标记为“A2DP:+aM.isSpeakerphoneOn());
返回true;
}否则{
Log.v(标记“没有蓝牙适配器”);
返回false;
}
}
/**现在,这只是禁用蓝牙*/
公共静态无效禁用蓝牙(){
//如果有适配器,则禁用它(如果尚未禁用)
if(mBluetoothAdapter!=null){
if(mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.disable();
}
}否则{
Log.v(标记“没有蓝牙适配器”);
}
}
公共静态void restartbooth(){
aM.setMode(AudioManager.MODE在通话中);
}
公共静态void stopBluetooth(){
aM.setMode(AudioManager.MODE_正常);
}
}
当我正确调用stopBluetooth()
时,应用程序的音频不再发送到耳机
但是,当我呼叫
restartbooth()
时,音频不是从耳机播放的,而是从手机扬声器播放的。通话结束后,SCO链路是否可能中断?如果是这种情况,则SCO链路也必须与音频路由一起启动
您是否尝试在restartBluetooth()中调用enableBluetoothSCO()您可能需要调用:
aM.startBluetoothSco();
aM.setBluetoothScoOn(真)代码>
设置模式后。在重新启动功能中,再次初始化所有内容,并查看其是否工作。像这样:
public static void restartBluetooth(){
enableBluetooth(getApplicationContext());
}
如果这样做有效,则意味着当通话结束时,由于某种原因,最后一次初始化将丢失。
“电话应用程序始终优先使用SCO连接进行电话。如果在通话中调用此方法,则会忽略此方法。类似地,如果在应用程序使用SCO连接时接收或发送呼叫,则应用程序的连接将丢失,并且在呼叫结束时不会自动返回。”
因此,当通话中断时,您必须通过呼叫startBluetoothSco()重新建立连接。对于仍有此问题的任何人,需要做一些事情。您需要做的第一件事是跟踪电话状态。您可以在此处看到如何做到这一点:
当状态为空闲时,表示传入呼叫已结束。现在,如果此时尝试重新连接蓝牙,您会发现它仍然无法工作,因为呼叫需要一段时间(大约2秒)才能“释放”蓝牙设备。
因此,您有两个选择,请稍等,然后尝试重新连接,或者您可以向BluetoothHeadset添加另一个侦听器。操作\音频\状态\已更改
然后,您可以添加一个全局布尔值isIdle,当TelephonyManager.CALL\u STATE\u空闲时为true,当TelephonyManager.CALL\u STATE\u挂起时为false(否则,您将在传入呼叫期间重新连接蓝牙)。此时,当BluetoothHeadset.STATE_断开连接且isIdle为真时,请重新连接蓝牙
@Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals((BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED))){
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
switch(state) {
case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
if (isIdle){
//reconnect bluetooth
}
break;
}
}
if(("OFFHOOK").equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE))) {
isIdle = false;
// turn bluetooth off
}
if(("IDLE").equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE))) {
isIdle = true;
}
}
我还试图通过蓝牙将音频发送到spcific应用程序,但无法到达该应用程序。这是我的查询