Ошибка Bluetooth SCO после входящего вызова

Я пытаюсь отправить все аудио приложения через 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(), звук воспроизводится НЕ из гарнитуры, как предполагалось, а из динамиков телефона.


person Lisa Anne    schedule 08.06.2014    source источник
comment
Я также пытаюсь отправить аудио через Bluetooth в конкретное приложение, но не могу туда добраться. Вот мой запрос stackoverflow.com/questions/24134223/   -  person Namrata    schedule 10.06.2014


Ответы (5)


Возможно ли, что канал SCO был прерван после завершения вызова? Если это так, то канал SCO также должен быть поднят вместе с маршрутизацией звука.

Вы пытались вызвать enableBluetoothSCO() в функции restartBluetooth()?

person Preeti    schedule 12.06.2014

Вероятно, вам нужно позвонить:

aM.startBluetoothSco(); aM.setBluetoothScoOn(true);

после установки режима.

person SoundsDangerous    schedule 13.06.2014

внутри вашей функции перезапуска снова инициализируйте все и посмотрите, работает ли это. вот так:

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

если это работает, то это означает, что при завершении вызова последняя инициализация по какой-то причине теряется.

person M D P    schedule 16.06.2014

Для тех, у кого все еще есть проблемы с этим, есть несколько вещей, которые необходимо сделать. Первое, что вам нужно сделать, это отслеживать состояние телефона. Вы можете увидеть, как это сделать здесь: Как узнать, что телефонный звонок закончился?< /а>

Когда состояние бездействует, это означает, что входящий вызов завершен. Теперь, если вы попытаетесь переподключить bluetooth в этот момент, вы обнаружите, что он по-прежнему не работает, поскольку требуется некоторое время (примерно 2 секунды) для вызова, чтобы «освободить» устройство bluetooth. Таким образом, у вас есть два варианта: немного подождать, а затем попытаться снова подключиться, или вы можете добавить еще один прослушиватель в BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED.

Затем вы можете добавить глобальное логическое значение isIdle, которое имеет значение true, если TelephonyManager.CALL_STATE_IDLE, или false, если TelephonyManager.CALL_STATE_OFFHOOK (в противном случае вы повторно подключитесь к BlueTooth во время входящего вызова). В этот момент, когда BluetoothHeadset.STATE_DISCONNECTED и isIdle имеют значение true, повторно подключитесь к Bluetooth.

@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;
    }
}
person Chris Abraham    schedule 13.06.2020

Документы Google утверждают, что

«Телефонное приложение всегда имеет приоритет при использовании соединения SCO для телефонии. Если этот метод вызывается во время разговора по телефону, он будет проигнорирован. Аналогично, если вызов получен или отправлен, когда приложение использует соединение SCO. , соединение будет потеряно для приложения и НЕ будет восстановлено автоматически после завершения вызова."

Поэтому, когда вызов отключен, вам необходимо восстановить соединение, вызвав startBluetoothSco().

person Shivaraj Patil    schedule 11.02.2015