Android 笔记-音乐播放器的几个关键点

来源:互联网 发布:桌面 知乎 编辑:程序博客网 时间:2024/05/17 07:07

1.动态更新SeekBar

以前的思路是MediaPlayer 隔几百ms notify注册了监听的activity,今天发现有更为简单的方式

定义变量

        SeekBar mProgressBar = null;//刷新对象        Handler mProgressRefresher;//通过handler刷新界面        private static final int DELAY_MILLIS = 200;//刷新间隔        MediaPlayer mPlayer = null;

OnCreate 变量初始化

        mProgressBar = (SeekBar) findViewById(R.id.audio_progress);        mProgressRefresher = new Handler();        mPlayer = new MediaPlayer();        mPlayer.setOnPreparedListener(this);        mPlayer.setOnCompletionListener(this);

当开始播放歌曲时(一般是调用play方法时)开始更新界面

        mProgressRefresher.removeCallbacksAndMessages(null);        mProgressBar.setMax(mPlayer.getDuration());        mProgressRefresher.postDelayed(new ProgressRefresher(), DELAY_MILLIS);        try {            mPlayer.setDataSource(this, uri);            mPlayer.prepareAsync();        } catch (IOException e) {            Log.d(TAG, "Failed to open file: " + e);            finish();        }

核心:递归调用handler 更新界面

    private class ProgressRefresher implements Runnable {        @Override        public void run() {            if (mPlayer != null) {                int position = mPlayer.getCurrentPosition();                mProgressBar.setProgress(position);            }            mProgressRefresher.removeCallbacksAndMessages(null);            mProgressRefresher.postDelayed(new ProgressRefresher(), DELAY_MILLIS);//此处为核心        }    }

2.OnAudioFocusChangeListener 的使用

OnAudioFocusChangeListener简介

OnAudioFocusChangeListener简单来说是当android系统同时有两个应用需要使用AudioManager时,为了处理两个应用的声音播放优先级而存在的.如果不使用OnAudioFocusChangeListener,会导致android 音频系统的混乱,比如会同时有两个应用在播放歌曲,歌曲播放中,有电话过来,通话结束音乐不再播放等等现象.
在其他博客中,这种机制称为AudioFocus竞争机制.当焦点变化时,OnAudioFocusChangeListener会收到AudioManager发出的以下通知

AUDIOFOCUS_GAIN:获得了Audio Focus;
AUDIOFOCUS_LOSS:失去了Audio Focus,并将会持续很长的时间。这里因为可能会停掉很长时间,所以不仅仅要停止Audio的播放,最好直接释放掉Media资源。而因为停止播放Audio的时间会很长,如果程序因为这个原因而失去AudioFocus,最好不要让它再次自动获得AudioFocus而继续播放,不然突然冒出来的声音会让用户感觉莫名其妙,感受很不好。这里直接放弃AudioFocus,当然也不用再侦听远程播放控制【如下面代码的处理】。要再次播放,除非用户再在界面上点击开始播放,才重新初始化Media,进行播放。
AUDIOFOCUS_LOSS_TRANSIENT:暂时失去Audio Focus,并会很快再次获得。必须停止Audio的播放,但是因为可能会很快再次获得AudioFocus,这里可以不释放Media资源;
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:暂时失去AudioFocus,但是可以继续播放,不过要在降低音量。

具体使用

    /**     * 焦点变化     */    OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {        @Override        public void onAudioFocusChange(int focusChange) {            Log.d(TAG, "mPlayer: [" + mPlayer + "] ,focusChange: ["                    + focusChange + "]");            Log.i(TAG, "onAudioFocusChange");            if (mPlayer == null) {                mAudioManager.abandonAudioFocus(this);                return;            }            switch (focusChange) {                //丢失焦点            case AudioManager.AUDIOFOCUS_LOSS:                mPlayer.pause();                break;                //Used to indicate a transient loss of audio focus.            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:                /**                 * Used to indicate a transient loss of audio focus where the loser of the audio focus can                 * lower its output volume if it wants to continue playing (also referred to as "ducking"), as                 * the new focus owner doesn't require others to be silent.                 */            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:                if (mPlayer.isPlaying()) {                    mPlayer.pause();                }                break;                //Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration.                //应理解为重新获取焦点            case AudioManager.AUDIOFOCUS_GAIN:                if (mPlayer != null) {                    mPlayer.start();                    return;                }                break;            }        }    };    

音乐播放器应该做到使用前申请AudioFocus,使用完毕后释放AudioFocus
使用前申请Focus:(基本在play方法中)

        if (AudioManager.AUDIOFOCUS_REQUEST_FAILED == mAudioManager                .requestAudioFocus(mAudioFocusListener,                        AudioManager.STREAM_MUSIC,                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)) {            Log.d(TAG, "start() AUDIOFOCUS_REQUEST_FAILED: "                    + AudioManager.AUDIOFOCUS_REQUEST_FAILED);            return;        }

使用完毕后释放Focus:(基本在onDestroy中)

mAudioManager.abandonAudioFocus(mAudioFocusListener);

参考资料:http://blog.csdn.net/thl789/article/details/7422931
好文,通俗易懂

3.拖动Seekbar使MediaPlayer播放指定position的音乐

思路:监听Seekbar
具体实现:

1.定义seek方法

    private void seek(int pos){        if(mPlayer != null){            mPlayer.seekTo(pos);        }    }

2.初始化SeekBar时,设置监听

            mProgressBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {            @Override            public void onStopTrackingTouch(SeekBar seekBar) {                // end touch SeekBar            }            @Override            public void onStartTrackingTouch(SeekBar seekBar) {                // start touch SeekBar            }            @Override            public void onProgressChanged(SeekBar seekBar, int progress,                    boolean fromUser) {                if(fromUser){                    seek(progress);                }            }        });