Android音频焦点详解(上)

来源:互联网 发布:视频会议软件好? 编辑:程序博客网 时间:2024/05/16 07:53

一 焦点在Android应用中的作用

我们的手机里经常会安装一些媒体类的应用,例如网易云音乐,QQ音乐,爱奇艺视频,优酷视频等等,你有没有想过,当我们听QQ音乐的歌曲时,切换到网易云音乐播放歌曲,或者打开爱奇艺观看视频时,QQ音乐播放的歌曲就会暂停,这是为什么呢?又是如何实现的呢?如果不暂停会是什么效果呢? 
以上这些疑问都可以用音频焦点来解释,在下面的内容中你将找到答案。

二 焦点讲解

众所周知Android是一个开放的系统,为了协调各媒体应用之间的关系,Android增加了音频焦点管理机制,各应用开发者应尽量遵循该机制进行开发。 
我们通过一个例子来讲解Android的焦点机制。 
新建一个Activity,在其中增加一个播放暂停按钮,来控制音乐播放。 
看一下部分关键代码,全部代码在文末会给出

    private void initData() {        //1 初始化AudioManager对象        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);        //2 申请焦点        mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);        AssetFileDescriptor fileDescriptor;        try {            //3 获取音频文件,我从网上下载的歌曲,放到了assets目录下            fileDescriptor = this.getAssets().openFd("littlelucky.mp3");            //4 实例化MediaPlayer对象            mMediaPlayer = new MediaPlayer();            //5 设置播放流类型            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);            //6 设置播放源,有多个参数可以选择,具体参考相关文档,本文旨在介绍音频焦点            mMediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),                    fileDescriptor.getStartOffset(),                    fileDescriptor.getLength());            //7 设置循环播放            mMediaPlayer.setLooping(true);            //8 准备监听            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {                @Override                public void onPrepared(MediaPlayer mp) {                    //9 准备完成后自动播放                    mMediaPlayer.start();                }            });            //10 异步准备            mMediaPlayer.prepareAsync();        } catch (IOException e) {            e.printStackTrace();        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

涉及到的MediaPlayer播放音乐流程请自行查询相关文档,不在本文介绍范围 
我们重点看一下第2步 申请焦点 
通过AudioManager对象调用requestAudioFocus方法,有三个参数 
OnAudioFocusChangeListener l,int streamType,int durationHint 
1 焦点变化的监听器

private AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new AudioManager.OnAudioFocusChangeListener() {        @Override        public void onAudioFocusChange(int focusChange) {            switch (focusChange){                case AudioManager.AUDIOFOCUS_LOSS:                    //长时间丢失焦点,当其他应用申请的焦点为AUDIOFOCUS_GAIN时,                    //会触发此回调事件,例如播放QQ音乐,网易云音乐等                    //通常需要暂停音乐播放,若没有暂停播放就会出现和其他音乐同时输出声音                    Log.d(TAG, "AUDIOFOCUS_LOSS");                    stop();                    //释放焦点,该方法可根据需要来决定是否调用                    //若焦点释放掉之后,将不会再自动获得                    mAudioManager.abandonAudioFocus(mAudioFocusChange);                    break;                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:                    //短暂性丢失焦点,当其他应用申请AUDIOFOCUS_GAIN_TRANSIENT或AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE时,                    //会触发此回调事件,例如播放短视频,拨打电话等。                    //通常需要暂停音乐播放                    stop();                    Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT");                    break;                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:                    //短暂性丢失焦点并作降音处理                    Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");                    break;                case AudioManager.AUDIOFOCUS_GAIN:                    //当其他应用申请焦点之后又释放焦点会触发此回调                    //可重新播放音乐                    Log.d(TAG, "AUDIOFOCUS_GAIN");                    start();                    break;            }        }    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

2 streamType音源类型,在AudioManager中定义

/** 通话 */public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;/** 系统声音 */public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;/** 铃声 */public static final int STREAM_RING = AudioSystem.STREAM_RING;/** 音乐 */public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;/** 闹铃声 */public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;/** 通知音 */public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;/** @hide 蓝牙电话 */public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;/** @hide 强制的系统声音 */public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;/** DTMF拨号音 */public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;/** @hide 文本识别音 */public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3 durationHint 获得焦点的时间长短 
在AudioManager中定义了四种类型 

AUDIOFOCUS_GAIN //长时间获得焦点 
AUDIOFOCUS_GAIN_TRANSIENT //短暂性获得焦点,用完应立即释放 
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK //短暂性获得焦点并降音,可混音播放 
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE //短暂性获得焦点,录音或者语音识别 

我们可根据自己的应用的使用场景来合理的配置每个参数,并在焦点变化监听器来做相应的处理。 
调试代码已上传github,欢迎访问

原创粉丝点击