当前位置: 首页 > 知识库问答 >
问题:

如何在android 10中以编程方式切换音频输出?

严景焕
2023-03-14

我的使用案例是,我有一个应用程序,用户可以在其中按下按钮,然后在外部扬声器和有线耳机/蓝牙设备之间切换。如果用户连接到有线耳机或蓝牙耳机设备,我想将该有线耳机或蓝牙的音频输出切换到外部扬声器,然后当他们再次单击时,重新启动有线耳机/蓝牙音频输出。

有人知道Android 10可以做到这一点吗?我在这篇文章中尝试了以下示例,但它并不总是适用于蓝牙情况。我的代码如下:

if (shouldEnableExternalSpeaker) {
     audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
     audioManager.isSpeakerphoneOn = true
     if (isBlueToothConnected) {
         audioManager.stopBluetoothScoOn()
     }
} else {
     if (isBlueToothConnected) {
         audioManager.startBluetoothSco()
     }

     audioManager.mode = AudioManager.NORMAL
     audioManager.isSpeakerphoneOn = false
}

我还拥有用户音频的必要权限:

<代码>

共有2个答案

魏朗
2023-03-14

线:

audioManager.isSpeakerphoneOn = true
audioManager.isSpeakerphoneOn = false

将不起作用。您必须使用set方法:

案例1-蓝牙

mAudioManager.startBluetoothSco(); // This method can be used by applications wanting to send and received audio to/from a bluetooth SCO headset while the phone is not in call. 
mAudioManager.setBluetoothScoOn(true); // set true to use bluetooth SCO for communications; false to not use bluetooth SCO for communications

案例2-有线

mAudioManager.stopBluetoothSco(); // stop wanting to send and receive
mAudioManager.setBluetoothScoOn(false); // turn off bluetooth
mAudioManager.setSpeakerphoneOn(false); //set true to turn on speakerphone; false to turn it off

案例3-内部扬声器

mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setSpeakerphoneOn(true); // turn on speaker phone

您可以按如下方式保持事情自动发生:

public class BluetoothReceiver extends BroadcastReceiver {
    private AudioManager localAudioManager;
    private static final int STATE_DISCONNECTED  = 0x00000000;
    private static final String EXTRA_STATE = "android.bluetooth.headset.extra.STATE";
    private static final String TAG = "BluetoothReceiver";
    private static final String ACTION_BT_HEADSET_STATE_CHANGED  = "android.bluetooth.headset.action.STATE_CHANGED";
    private static final String ACTION_BT_HEADSET_FORCE_ON = "android.bluetooth.headset.action.FORCE_ON";
    private static final String ACTION_BT_HEADSET_FORCE_OFF = "android.bluetooth.headset.action.FORCE_OFF";

    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.i(TAG,"onReceive - BluetoothBroadcast");
        localAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        final String action = intent.getAction();
        if (action.equals(ACTION_BT_HEADSET_STATE_CHANGED)) {
            final int extraData = intent.getIntExtra(EXTRA_STATE, STATE_DISCONNECTED);
            if (extraData == STATE_DISCONNECTED) {
                //no headset -> going other modes
                localAudioManager.setBluetoothScoOn(false);
                localAudioManager.stopBluetoothSco();
                localAudioManager.setMode(AudioManager.MODE_NORMAL);
                Log.i(TAG, "Bluetooth Headset Off " + localAudioManager.getMode());
                Log.i(TAG, "A2DP: " + localAudioManager.isBluetoothA2dpOn() + ". SCO: " + localAudioManager.isBluetoothScoAvailableOffCall());
            } else {            
                localAudioManager.setMode(0);
                localAudioManager.setBluetoothScoOn(true);
                localAudioManager.startBluetoothSco();
                localAudioManager.setMode(AudioManager.MODE_IN_CALL);
                Log.i(TAG, "Bluetooth Headset On " + localAudioManager.getMode());
                Log.i(TAG, "A2DP: " + localAudioManager.isBluetoothA2dpOn() + ". SCO: " + localAudioManager.isBluetoothScoAvailableOffCall());
            }
        }   

        if (action.equals(ACTION_BT_HEADSET_FORCE_ON)) {
            localAudioManager.setMode(0);
            localAudioManager.setBluetoothScoOn(true);
            localAudioManager.startBluetoothSco();
            localAudioManager.setMode(AudioManager.MODE_IN_CALL);
            Log.i(TAG, "Bluetooth Headset On " + localAudioManager.getMode());
            Log.i(TAG, "A2DP: " + localAudioManager.isBluetoothA2dpOn() + ". SCO: " + localAudioManager.isBluetoothScoAvailableOffCall());
        }

        if (action.equals(ACTION_BT_HEADSET_FORCE_OFF)) {
            localAudioManager.setBluetoothScoOn(false);
            localAudioManager.stopBluetoothSco();
            localAudioManager.setMode(AudioManager.MODE_NORMAL);
            Log.i(TAG, "Bluetooth Headset Off " + localAudioManager.getMode());
            Log.i(TAG, "A2DP: " + localAudioManager.isBluetoothA2dpOn() + ". SCO: " + localAudioManager.isBluetoothScoAvailableOffCall());
        }
    }
}
汪博艺
2023-03-14

我认为您应该将操控分为3种情况,通过以下方式播放声音:

  1. 通过蓝牙连接的外部设备
  2. 有线耳机/设备
  3. 电话扬声器

然后生成的代码可以像这样loke。

if(shouldEnableExternalSpeaker) {
    if(isBlueToothConnected) {
        // 1. case - bluetooth device
        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        mAudioManager.startBluetoothSco();
        mAudioManager.setBluetoothScoOn(true);
    } else {
        // 2. case - wired device
        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        mAudioManager.stopBluetoothSco();
        mAudioManager.setBluetoothScoOn(false);
        mAudioManager.setSpeakerphoneOn(false);
    }
} else {
   // 3. case - phone speaker
   mAudioManager.setMode(AudioManager.MODE_NORMAL);
   mAudioManager.stopBluetoothSco();
   mAudioManager.setBluetoothScoOn(false);
   mAudioManager.setSpeakerphoneOn(true);
}

尽管我最近没有使用AudioManager,但这在过去对我有用。

 类似资料:
  • 问题内容: 一次只显示一个标签。用户使用鼠标/键盘选择一个。假设TabPane上有三个选项卡,并且第一个有一个按钮。当用户按下按钮时,我希望打开第二个选项卡。然后必须有一些代码才能切换到绑定到该按钮的第二个Tab。 有可能以编程方式吗?如果是这样,怎么办? 问题答案: 尝试 要么 要么 要么…

  • 问题内容: 我正在尝试通过按“感觉幸运”按钮切换到第二个视图。当我尝试模拟器并按下它时,它只会显示黑屏。我该如何解决? 问题答案: 您可以通过控制从第一个场景顶部的视图控制器图标拖动到第二个场景来在情节提要中的两个场景之间添加序列: 然后,您可以选择该segue并为其指定一个唯一的情节提要标识符,然后可以使用该标识符执行segue: 或者,您可以执行以下操作: 其中“第二个”是我在Interfac

  • 问题内容: 我有一个标签栏应用程序,并且在我的第一个视图上有一个按钮,当我按下该按钮时,需要在标签栏中以编程方式切换到第二个标签页。 我似乎不太明白如何获取索引等以切换到它,我已经尝试过类似的东西。 没有成功。 问题答案: 多数民众赞成在非常简单的tabBarController被声明为可选类型 视图控制器层次结构中最接近的祖先,它是一个标签栏控制器。如果视图控制器或其祖先之一是标签栏控制器的子代

  • 我想创建一个应用程序,它可以将屏幕行为记录为视频,并以编程方式保存在设备上。有人能帮我吗?

  • 有没有人可以帮助我如何做到这一点,因为很难知道如何在我的简单程序中实现宋。我只是初学者程序员,我想知道如何做到这一点,因为我有一个关于这方面的项目。请用最简单的方式帮助我,因为我还不太擅长java编程,谢谢^_^ //这是我的代码。你不认为这是可能的吗?

  • 问题内容: 是否有免费的库可根据图像序列创建MPEG(或任何其他简单的视频格式)? 它也必须在Linux上运行,并且最好具有Python绑定。 问题答案: 我知道有一个mencoder(是mplayer项目的一部分)和ffmpeg,它们都可以做到这一点。