Android:在蓝牙和手机扬声器之间切换音频是不一致的

时间:2014-03-31 19:21:22

标签: android audio bluetooth

我的要求是根据用户选择在蓝牙和手机扬声器之间切换音频。 以下是代码段:

//AudioTrack for incoming audio to play as below:

    int mMaxJitter = AudioTrack.getMinBufferSize(8000,               AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);                                  
    new AudioTrack(AudioManager.STREAM_VOICE_CALL,8000,
           AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
           mMaxJitter, AudioTrack.MODE_STREAM);


//To register broadcast receiver for bluetooth audio routing
    IntentFilter ifil = new IntentFilter();
    ifil.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
    this.registerReceiver(<receiver instance>,ifil);

//To get AudioManager service
    AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

//Whenever user select to route audio to Bluetooth
    mAudioManager.setMode(AudioManager.MODE_IN_CALL);//tried setting with other mode also viz. MODE_NORMAL, MODE_IN_COMMUNICATION but no luck
    mAudioManager.startBluetoothSco();//after this I get AudioManager.SCO_AUDIO_STATE_CONNECTED state in the receiver
    mAudioManager.setBluetoothScoOn(true);
    mAudioManager.setSpeakerphoneOn(false);

//Whenever user select to route audio to Phone Speaker
    mAudioManager.setMode(AudioManager.MODE_NORMAL);
    mAudioManager.stopBluetoothSco();//after this I get      AudioManager.SCO_AUDIO_STATE_DISCONNECTED state in the receiver
    mAudioManager.setBluetoothScoOn(false);
    mAudioManager.setSpeakerphoneOn(true);

问题: 1.我能够路由音频,但行为不一致,有时它会路由到手机扬声器,即使用户选择路由到蓝牙(蓝牙已连接) 2.如果音频路由到手机扬声器,音量会变低(请不要说检查手机音量) 3.根据我的选择,我只能观察几次音频路由是正确的,如果我重复它,就像我上面提到的那样变得奇怪。

Android版:Jellybean 4.3

有没有人遇到类似的行为?

谢谢!

3 个答案:

答案 0 :(得分:9)

我得到了音频路由不一致的原因,那是因为我设置了手机扬声器假,我也使用了不合适的模式... 以下组合为我工作:

//For BT
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mAudioManager.startBluetoothSco();
mAudioManager.setBluetoothScoOn(true);

//For phone ear piece
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setSpeakerphoneOn(false);

//For phone speaker(loadspeaker)
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setSpeakerphoneOn(true);

Android版:4.3

谢谢!

答案 1 :(得分:1)

如果它仍然与某人有关,这是我的解决方案:

(在samsung s7 sm-g9307上测试,安卓版6.0.1)

public class AudioSourceUtil {

private static void reset(AudioManager audioManager) {
    if (audioManager != null) {
        audioManager.setMode(AudioManager.MODE_NORMAL);
        audioManager.stopBluetoothSco();
        audioManager.setBluetoothScoOn(false);
        audioManager.setSpeakerphoneOn(false);
        audioManager.setWiredHeadsetOn(false);
    }
}

public static void connectEarpiece(AudioManager audioManager) {
    reset(audioManager);
    audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
}

public static void connectSpeaker(AudioManager audioManager) {
    reset(audioManager);
    audioManager.setSpeakerphoneOn(true);
}

public static void connectHeadphones(AudioManager audioManager) {
    reset(audioManager);
    audioManager.setWiredHeadsetOn(true);
}

public static void connectBluetooth(AudioManager audioManager) {
    reset(audioManager);
}

}

通过单击按钮(标签布局中的选项卡)进行使用:

/**
 * There are 3 scenarios for the audio source:
 * 1. No headphones and no bluetooth device: toggle phone/ speaker
 * 2. Headphones connected: toggle headphones/ speaker
 * 3. Bluetooth connected: toggle  phone/ speaker/ bluetooth
 *
 * @param tab
 */
private void handleTabAudioSourceClick(TabLayout.Tab tab) {
    View view = tab.getCustomView();
    ImageView icon = (ImageView) view.findViewById(R.id.imageViewIcon);
    int currentAudioSourceIdentifier = (Integer) view.getTag();

    if (audioManager.isWiredHeadsetOn() == false && BluetoothManager.isBluetoothHeadsetConnected() == false) {
        // No headphones and no bluetooth device: toggle phone/ speaker.
        if (currentAudioSourceIdentifier == R.drawable.tab_speaker) {
            // Current audio source is earpiece, moving to speaker.
            view.setTag(android.R.drawable.stat_sys_speakerphone);
            icon.setImageResource(android.R.drawable.stat_sys_speakerphone);
            AudioSourceUtil.connectSpeaker(audioManager);
        } else {
            // Current audio source is speaker, moving to earpiece.
            view.setTag(R.drawable.tab_speaker);
            icon.setImageResource(R.drawable.tab_speaker);
            AudioSourceUtil.connectEarpiece(audioManager);
        }
    } else if (audioManager.isWiredHeadsetOn()) {
        // Headphones connected: toggle headphones/ speaker.
        if (currentAudioSourceIdentifier == android.R.drawable.stat_sys_speakerphone) {
            // Current audio source is speaker, moving to headphones.
            view.setTag(android.R.drawable.stat_sys_headset);
            icon.setImageResource(android.R.drawable.stat_sys_headset);
            AudioSourceUtil.connectHeadphones(audioManager);
        } else {
            // Current audio source is headphones, moving to speaker.
            view.setTag(android.R.drawable.stat_sys_speakerphone);
            icon.setImageResource(android.R.drawable.stat_sys_speakerphone);
            AudioSourceUtil.connectSpeaker(audioManager);
        }
    } else if (BluetoothManager.isBluetoothHeadsetConnected()) {
        // Bluetooth connected: toggle  phone/ speaker/ bluetooth.
        if (currentAudioSourceIdentifier == R.drawable.tab_speaker) {
            // Current audio source is earpiece, moving to speaker.
            view.setTag(android.R.drawable.stat_sys_speakerphone);
            icon.setImageResource(android.R.drawable.stat_sys_speakerphone);
            AudioSourceUtil.connectSpeaker(audioManager);
        } else if (currentAudioSourceIdentifier == android.R.drawable.stat_sys_speakerphone) {
            // Current audio source is speaker, moving to bluetooth.
            view.setTag(android.R.drawable.stat_sys_data_bluetooth);
            icon.setImageResource(android.R.drawable.stat_sys_data_bluetooth);
            AudioSourceUtil.connectBluetooth(audioManager);
        } else {
            // Current audio source is bluetooth, moving to earpiece.
            view.setTag(R.drawable.tab_speaker);
            icon.setImageResource(R.drawable.tab_speaker);
            AudioSourceUtil.connectEarpiece(audioManager);
        }
    }
}

答案 2 :(得分:0)

为此使用MediaRouter api: https://developer.android.com/guide/topics/media/mediarouter

为此专门设计的。 像这样:

mediaRouter = MediaRouter.getInstance(VideoCallingApp.getContext());
mediaRouteSelector = new MediaRouteSelector.Builder()
            .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
            .build();
....

public void onStart() {
    mediaRouter.addCallback(mediaRouteSelector, mMediaRouterCallback,
            MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
    super.onStart();
}

@Override
public void onStop() {
    mediaRouter.removeCallback(mMediaRouterCallback);
    super.onStop();
}

...,当您要切换音频设备时,请使用mediaRouter.getRoutes()和mediaRouter.selectRoute(route)API。