android 蓝牙SCO在来电后失败

xytpbqjk  于 2023-05-15  发布在  Android
关注(0)|答案(5)|浏览(227)

我试图通过SCO发送应用程序的所有音频。
我可以成功发送音频,
但是当有来电时,我需要断开SCO的连接,这样应用程序音频就不会干扰通话,
问题是,当我尝试在通话后将音频重路由到SCO时,它不起作用。
下面是我用来将音频发送到SCO的代码:

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

}

}

当我正确调用stopBluetooth()时,应用程序的音频不再发送到耳机,
但是当我打电话给restartBluetooth()时,音频不是按照预期从耳机播放,而是从手机扬声器播放。

xdnvmnnf

xdnvmnnf1#

有没有可能是通话结束后上合组织的链接被切断了?如果是这种情况,则SCO链路也必须与路由音频沿着被提出。
是否尝试在restartBluetooth()中调用enableBluetoothSCO()

chy5wohz

chy5wohz2#

您可能需要拨打:
aM.startBluetoothSco(); aM.setBluetoothScoOn(true);
在你设定好模式之后。

tnkciper

tnkciper3#

在restart函数中,再次初始化所有内容,并查看它是否有效。就像这样:

public static void restartBluetooth(){
    enableBluetooth(getApplicationContext());
}

如果这起作用,则意味着当呼叫结束时,由于某种原因丢失了最后的初始化。

a8jjtwal

a8jjtwal4#

对于任何仍然有问题的人来说,有几件事需要做。你需要做的第一件事是跟踪手机状态。你可以在这里看到如何做到这一点:How to know Phone call has ended?
当状态为空闲时,这意味着来电已结束。现在,如果您尝试重新连接蓝牙在这一点上,你会发现它仍然不工作,因为它需要一段时间(约2秒)的呼吁,以“释放”蓝牙设备。所以你有两个选择,等待一段时间,然后尝试重新连接,或者你可以添加另一个监听器到蓝牙耳机。ACTION_AUDIO_STATE_CHANGED。
然后,您可以添加一个全局布尔值isIdle,在TelephonyManager.CALL_STATE_IDLE时为true,在TelephonyManager.CALL_STATE_OFFHOOK时为false(否则您将在来电期间重新连接到蓝牙)。此时,当BluetoothHeadset.STATE_DISCONNECTED和isIdle为true时,重新连接到蓝牙。

@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;
    }
}
zu0ti5jz

zu0ti5jz5#

谷歌文档说
电话应用程序始终优先使用SCO电话连接。如果在电话处于通话状态时调用此方法,则将忽略此方法。类似地,如果在应用程序使用SCO连接时接收或发送呼叫,则应用程序的连接将丢失,并且在呼叫结束时不会自动返回。
因此,当呼叫断开时,您必须通过调用**startBluetoothSco()**重新建立连接

相关问题