安卓学习笔记---实现简易播放器(带有进度条,开始与结束时间,暂停与播放)

最近需要实现一个简易的播放器的功能,来播放本地的音乐功能,首先想到了MediaPlayer,但是有些方法又不是记得很清楚,查找了一些比较不错的例子,基于基础上来完成自己想要的功能:

 功能:

1.播放本地音频文件,显示进度条seekbar,显示播放的开始时间与结束时间,随播放的进度而改变,

2.监听来电,当打电话进来的时候,暂停播放音频,记录当前播放位置,电话结束后,用户再次点击播放,从上一次的位置继续播放

3.用户在播放过程中可以随时移动seekbar的位置,来听自己想要听得位置

4.用户在点击停止的时候,也可以随时移动seekbar的位置,同时开始时间也随之改变,用户点击播放的时候,从当前位置开始播放


附上几张实现的功能图


下面附上自己实现的代码,有需要的直接复制到项目中运行即可,看到效果

1.activity_play_music.xml

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:textSize="20sp"
    android:text="Android实现简易音乐器播放"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="40dp"
    >

    <TextView
        android:layout_marginLeft="10dp"
        android:layout_width="40dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_start"
        />

    <SeekBar
        android:layout_width="270dp"
        android:layout_height="wrap_content"
        android:id="@+id/seekbar"
        />

    <TextView
        android:layout_width="40dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_end"
        />
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="30dp"
    android:gravity="center_horizontal"
    >
    <ImageButton

        android:layout_width="60dp"
        android:layout_height="60dp"
        android:id="@+id/bt_media"
        android:src="@android:drawable/ic_media_play"
        />

</LinearLayout>

2.PlayMusicActivity.class

public class PlayMusicActivity extends BaseActivity {
   
    private String loaclStorageAudioPath;//audioPath本地保存路径.wav

    private MediaPlayer mediaPlayer;
    private TextView tv_start;
    private TextView tv_end;
    private SeekBar seekbar;
    private ImageButton imageButton;

    private MyPhoneStateListener myPhoneStateListener;//电话监听
    private Timer timer;
    private boolean isSeekBarChanging;//互斥变量,防止进度条与定时器冲突。
    private boolean isCellPlay;/*在挂断电话的时候,用于判断是否为是来电时中断*/
    private  boolean isFitstInit=true;//用户第一次打开时

    private int currentPosition;//记录当前播放位置

    @Override
    public int getContentView() {
        return R.layout.activity_play_music;
    }

    @Override
    public void initViews(Bundle savedInstanceState) {

        //开始时间
        tv_start = (TextView) findViewById(R.id.tv_start);
        //结束时间
        tv_end = (TextView) findViewById(R.id.tv_end);

        //进度条
        seekbar = (SeekBar) findViewById(R.id.seekbar);
        //设置监听
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            /**
             *
             * @param seekBar  当前被修改进度的SeekBar
             * @param progress 当前的进度值。此值的取值范围为0到max之间。Max为用户通过setMax(int)设置的值,默认为100
             * @param fromUser 如果是用户触发的改变则返回True
             */
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //获取音乐总时间
                int duration2 = mediaPlayer.getDuration() / 1000;
                //获取音乐当前播放的位置
                int position = mediaPlayer.getCurrentPosition();
                //开始时间
                tv_start.setText(calculateTime(position / 1000));
                //结束时间
                tv_end.setText(calculateTime(duration2));
            }

           // 通知用户已经开始一个触摸拖动手势。客户端可能需要使用这个来禁用seekbar的滑动功能。
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                isSeekBarChanging = true;
            }

            //通知用户触摸手势已经结束。户端可能需要使用这个来启用seekbar的滑动功能。
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                isSeekBarChanging = false;
                //在当前位置播放
                mediaPlayer.seekTo(seekBar.getProgress());

                //停止时播放时间
                //开始时间
                tv_start.setText(calculateTime(mediaPlayer.getCurrentPosition() / 1000));
            }
        });

        imageButton = (ImageButton) findViewById(R.id.bt_media);
        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //按钮点击事件
                isPlayOrPause();
            }
        });


        myPhoneStateListener=new MyPhoneStateListener();
        //监听来电事件
        TelephonyManager phoneyMana = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        phoneyMana.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    @Override
    public void initDatas() {
        coverImagePath = getIntent().getStringExtra("coverImagePath");
        localStoragePath = getIntent().getStringExtra("localStoragePath");
        loaclStorageAudioPath = getIntent().getStringExtra("loaclStorageAudioPath");

        //初始化
        initMediaPlayer();

    }

    //初始化
    private void initMediaPlayer()
    {
        File file = new File(loaclStorageAudioPath);
        //判断音频文件是否为空
        if (file.exists()) {
            if(mediaPlayer==null)
            {
                LoggerUtil.i("Novate","mediaPlayer 为空");

                //为空则创建音乐文件并播放改变按钮样式
                mediaPlayer = new MediaPlayer();
                try {
                    mediaPlayer.reset();//处于空闲状态
                    mediaPlayer.setDataSource(file.getAbsolutePath());//文件路径
                    mediaPlayer.prepare();// 准备
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //获取音乐总时间
                int duration2 = mediaPlayer.getDuration() / 1000;
                //获取音乐当前播放的位置
                int position = mediaPlayer.getCurrentPosition();
                //开始时间
                tv_start.setText(calculateTime(position / 1000));
                //结束时间
                tv_end.setText(calculateTime(duration2));

            }
        }
    }

    //按钮点击事件
    public void isPlayOrPause() {
        LoggerUtil.i("Novate", "loaclStorageAudioPath-->" + loaclStorageAudioPath);
        File file = new File(loaclStorageAudioPath);
        //判断音频文件是否为空
        if (file.exists()) {
            if (mediaPlayer!=null&&isFitstInit==true) {

                isFitstInit=false;

                LoggerUtil.i("Novate","mediaPlayer!=null&&isFitstInit==true");

//                //为空则创建音乐文件并播放改变按钮样式
//                mediaPlayer = new MediaPlayer();
//                try {
//                    mediaPlayer.reset();//处于空闲状态
//                    mediaPlayer.setDataSource(file.getAbsolutePath());//文件路径
//                    mediaPlayer.prepare();// 准备
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
                mediaPlayer.start();//播放
                imageButton.setImageResource(android.R.drawable.ic_media_pause);
                //获取音乐总时间
                int duration = mediaPlayer.getDuration();
                //将音乐总时间设置为SeekBar的最大值
                seekbar.setMax(duration);

                //-------------------------
                //监听播放时回调函数
                timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        if(!isSeekBarChanging){
                            seekbar.setProgress(mediaPlayer.getCurrentPosition());
                        }

                    }
                },0,50);
            }
            //音乐文件正在播放,则暂停并改变按钮样式
            else if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
                LoggerUtil.i("Novate","音乐文件正在播放,则暂停并改变按钮样式");
                mediaPlayer.pause();
                imageButton.setImageResource(android.R.drawable.ic_media_play);
            }
            //如果为暂停状态则继续播放,同时改变按钮样式
            else if(mediaPlayer!=null&&(!mediaPlayer.isPlaying())){
                LoggerUtil.i("Novate","如果为暂停状态则继续播放,同时改变按钮样式");

                if(currentPosition>0)
                {
                    mediaPlayer.seekTo(currentPosition);
                    currentPosition=0;
                }
                //启动播放
                mediaPlayer.start();
                imageButton.setImageResource(android.R.drawable.ic_media_pause);

            }

            //播放完监听
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    //播放位置变为0
                    mediaPlayer.seekTo(0);
                    imageButton.setImageResource(android.R.drawable.ic_media_play);
                }
            });

        } else {
            ToastUtil.showToast(PlayMusicActivity.this, "您要播放的音乐不存在");
        }
    }


    //计算播放时间
    public String calculateTime(int time) {
        int minute;
        int second;

        String strMinute;

        if (time >= 60) {
            minute = time / 60;
            second = time % 60;

            //分钟在0-9
            if(minute>=0&&minute<10)
            {
                //判断秒
                if(second>=0&&second<10)
                {
                    return "0"+minute+":"+"0"+second;
                }else
                {
                    return "0"+minute+":"+second;
                }

            }else
            //分钟在10以上
            {
                //判断秒
                if(second>=0&&second<10)
                {
                    return minute+":"+"0"+second;
                }else
                {
                    return minute+":"+second;
                }
            }

        } else if (time < 60) {
            second = time;
            if(second>=0&&second<10)
            {
                return "00:"+"0"+second;
            }else
            {
                return "00:" + second;
            }

        }
        return null;
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        this.loaclStorageAudioPath = savedInstanceState.getString("filename");
        this.currentPosition = savedInstanceState.getInt("position");
        super.onRestoreInstanceState(savedInstanceState);
        LoggerUtil.i("Novate", "回到当前音乐文件onRestoreInstanceState()");
    }

    //当内存空间不足,关闭应用时
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putString("filename", loaclStorageAudioPath);
        outState.putInt("position", currentPosition);
        super.onSaveInstanceState(outState);
        LoggerUtil.i("Novate", "保存音乐onSaveInstanceState()");
    }

    //如果突然电话到来,停止播放音乐
    @Override
    protected void onPause() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            currentPosition = mediaPlayer.getCurrentPosition();//保存当前播放点
            mediaPlayer.pause();
            timer.purge();//移除所有任务;
            imageButton.setImageResource(android.R.drawable.ic_media_play);
        }
        super.onPause();
        ToastUtil.showToast(PlayMusicActivity.this,"onPause");
    }

    //如果电话结束,继续播放音乐
    @Override
    protected void onResume() {
        super.onResume();

    }

    /*来电事件处理*/
    private class MyPhoneStateListener extends PhoneStateListener
    {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING://来电,应当停止音乐
                    if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
                        currentPosition = mediaPlayer.getCurrentPosition();//记录播放的位置
                        mediaPlayer.pause();//暂停
                        isCellPlay = true;//标记这是属于来电时暂停的标记
                        imageButton.setImageResource(android.R.drawable.ic_media_play);
                        timer.purge();//移除定时器任务;
                    }
                    break;
                case TelephonyManager.CALL_STATE_IDLE://无电话状态
                    if(isCellPlay){
                        isCellPlay = false;
                    }
                    break;
            }
        }
    }

    /*销毁时释资源*/
    @Override
    protected void onDestroy() {

        if(timer!=null)
        {
            timer.cancel();
            timer.purge();
            timer = null;
        }

        if(mediaPlayer!=null)
        {
            mediaPlayer.release();
            mediaPlayer = null;
        }

        //关闭监听
        TelephonyManager tmgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        tmgr.listen(myPhoneStateListener, 0);

        super.onDestroy();

        ToastUtil.showToast(PlayMusicActivity.this,"onDestroy");
    }
}
3.需要的权限

<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 拦截号码权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

以上3步就基本可以实现一个简易的音频播放器了。

同时要感谢以下博主写的博客,是看到他们的博客,找到思路,最终实现了自己需要的功能

http://blog.csdn.net/qq_33201020/article/details/56841339

http://blog.csdn.net/hubiao_0618/article/details/43470783

同时还有一篇关于MediaPlayer的使用,有需要的可以看一下

android Mediaplayer各种属性和方法简单介绍

http://www.cnblogs.com/dyllove98/p/3192090.html



发布了90 篇原创文章 · 获赞 39 · 访问量 23万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览