【问题标题】:Android : Switching audio between Bluetooth and Phone Speaker is inconsistentAndroid:在蓝牙和电话扬声器之间切换音频不一致
【发布时间】:2014-03-31 19:21:21
【问题描述】:

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

//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

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

谢谢!

【问题讨论】:

    标签: android audio bluetooth


    【解决方案1】:

    我得到了音频路由不一致的原因,是因为我将手机扬声器设置为false,而且我使用了不合适的模式...... 以下组合对我有用:

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

    安卓版本:4.3

    谢谢!

    【讨论】:

    • 我发现对于扬声器,如果来自BT,我必须更改为MODE_NORMAL,否则MODE_IN_COMMUNICATION
    【解决方案2】:

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

    (在三星 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);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      为此使用 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。

      【讨论】:

        猜你喜欢
        • 2022-06-16
        • 2018-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-03
        相关资源
        最近更新 更多