Android音频开发(四):音频播放模式

一、Android音频开发(一):音频基础知识
二、Android音频开发(二):录制音频(WAV及MP3格式)
三、Android音频开发(三):使用ExoPlayer播放音频
四、Android音频开发(四):音频播放模式
五、Android音频开发(五):感应(息屏/亮屏)管理

附GitHub源码:MultimediaExplore


音频播放模式主要有:

1、耳机模式 2、外放模式 3、听筒模式

音频播放模式所需权限:

    <!--音频模式切换权限-->
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <uses-permission android:name="android.permission.BLUETOOTH" />

通过系统自带的 AudioManager 管理类来进行播放模式的切换,使用之前我们需初始化该类:

AudioManager audioManager = (AudioManager)appContext.getSystemService(Context.AUDIO_SERVICE);

然后设置其相应播放模式:

    /**
     * 切换到外放
     */
    private void changeToSpeaker() {
        if (audioManager != null) {
            audioManager.setMode(AudioManager.MODE_NORMAL);
            audioManager.setSpeakerphoneOn(true);
        }
    }

    /**
     * 切换到耳机模式
     */
    private void changeToHeadset() {
        if (audioManager != null) {
            audioManager.setSpeakerphoneOn(false);
        }
    }

    /**
     * `
     * 切换到听筒
     */
    private void changeToReceiver() {
        if (audioManager != null) {
            audioManager.setSpeakerphoneOn(false);
            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        }
    }

这里注意一点的是,我们需要监听耳机(包含有线耳机 / 蓝牙耳机)的插拔操作,系统专门的广播通知,我们需要注册监听广播如下:

        //监听有线耳机
        intentFilter.addAction(Intent.ACTION_HEADSET_PLUG);
        intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
        //监听蓝牙耳机
        intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        //注册监听耳机的插拔
        appContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                Log.d(TAG, "onReceive -- 耳机");
                String action = intent.getAction();
                if (Objects.requireNonNull(action).equals(Intent.ACTION_HEADSET_PLUG)) {
                    int state = intent.getIntExtra("state", 0);
                    Log.d(TAG, "state:" + state);
                    if (state == 1) {
                        Log.d(TAG, "有线耳机插入");
                        playMode = PlayMode.Headset;
                        changeMode(playMode);
                    } else if (state == 0) {
                        Log.d(TAG, "有线耳机拔出");
                        if (isSpeakerOn()) {
                            playMode = PlayMode.Speaker;
                        } else {
                            playMode = PlayMode.Receiver;
                        }
                        changeMode(playMode);
                    }
                } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
                    //此处 有线/蓝牙拔出状态应该均能监听到
                    Log.d(TAG, "有线耳机拔出");
                } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                    int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
                    switch (state) {
                        case BluetoothProfile.STATE_CONNECTED:
                            Log.d(TAG, "蓝牙耳机连接");
                            playMode = PlayMode.Headset;
                            changeMode(playMode);
                            break;

                        case BluetoothProfile.STATE_DISCONNECTED:
                            Log.d(TAG, "蓝牙耳机断开");
                            if (isSpeakerOn()) {
                                playMode = PlayMode.Speaker;
                            } else {
                                playMode = PlayMode.Receiver;
                            }
                            changeMode(playMode);
                            break;
                    }
                }
            }

        }, intentFilter);

如上代码所示,根据需要的监听,自行添加即可。

另外,我们可能还需要得知当前耳机的已插入状态【比如我们插入/拔出耳机时还未打开APP无法接收到上面的广播通知】:

    /**
     * 耳机是否插入【有线耳机】
     * @return
     */
    public boolean isWiredHeadsetOn() {
        if (audioManager == null) {
            return false;
        }
        return audioManager.isWiredHeadsetOn();
    }

    /**
     * 耳机是否插入【蓝牙耳机】
     * @return
     */
    public boolean isBlueToothHeadsetConnected() {
        boolean result = true;
        try {
            result = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET)
                    != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;

        } catch (Exception ignored) {
        }
        return result;
    }

最后,播放语音时还会涉及到与第三方音乐播放器音频焦点的抢夺:

/**
 * 播放时语音时 调用该方法 屏蔽第三方音乐 同时使当前播放模式生效
 */
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
/**
 * 语音停止播放时 调用该方法 恢复第三方音乐播放  恢复播放模式
 */
audioManager.abandonAudioFocus(null);

另外,也可以结合APP前后台操作的监听,来控制当前音频的播放跟暂停等。

完整源码:

音频播放模式管理类-AudioModeManager源码

猜你喜欢

转载自blog.csdn.net/u012440207/article/details/121725566