最近需要实现一个简易的播放器的功能,来播放本地的音乐功能,首先想到了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.需要的权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<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的使用,有需要的可以看一下