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

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);
                }
            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值