Android音频开发:音频播放模式

Posted 红日666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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源码

以上是关于Android音频开发:音频播放模式的主要内容,如果未能解决你的问题,请参考以下文章

Android音频开发:感应(息屏/亮屏)管理

android WebView 通过听筒或蓝牙播放音频

Android音频开发:音频播放模式

Android音频开发:音频播放模式

Android音频开发:音频播放模式

Android音频开发:使用ExoPlayer播放音频