<span style="font-size:18px;"> </span><span style="font-family: Arial, Helvetica, sans-serif;font-size:18px;">上次和大家简单谈了播放器关于MP3列表界面的创建以及MP3文件相关信息的获取。这次主要谈播放界面的工作原理,界面再上一篇已经展示过了,就不再重复展示了。播放的基本原理是开启一个播放的服务(以至于切换到其他应用的界面可以继续播放),对播放界面的操作都作用于播放的服务。</span>
播放界面中有三个按钮,分别代表三种状态“开始”、“暂停”、“停止”,点击这三个按钮的其中一个,都会作用于播放服务。先看这三个按钮的监听事件:
开始:
class BeginListener implements OnClickListener{ @Override public void onClick(View arg0) { Toast.makeText(PlayActivity.this, "播放",Toast.LENGTH_SHORT).show(); //音乐播放与否的标志 stopMusic = false; Intent intent = new Intent(); //intent对象准备开启播放服务 intent.setClass(PlayActivity.this, PlayService.class); intent.putExtra("mp3Info", mp3Info); intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG); //歌词的初始化 preparelrc(mp3Info.getLrcName()); startService(intent); //绑定播放服务 bindService(intent, conn,BIND_AUTO_CREATE); //Runnable对象加入消息队列,在handler绑定的线程中执行,用于歌词更新 handler.post(updateTimeCallback); start = System.currentTimeMillis(); isPlaying = true; } }
将从列表界面传来的某条MP3的文件信息以及当前的状态(此时为播放状态AppConstant.PlayerMsg.PLAY_MSG)装入Intent对象中,然后开启播放服务PlayService,将Intent携带的对象传入该服务中。至于歌词初始化、播放服务绑定的作用、歌词更新这部分将在下一篇细讲,今天只要知道是什么作用的即可。
暂停和停止也基本一样。
暂停:
class PauseListener implements OnClickListener{ @Override public void onClick(View arg0) { Intent intent = new Intent(); //intent对象准备开启播放服务 intent.setClass(PlayActivity.this, PlayService.class); intent.putExtra("mp3Info", mp3Info); intent.putExtra("MSG", AppConstant.PlayerMsg.PAUSE_MSG); startService(intent); if(isPlaying){ Toast.makeText(PlayActivity.this, "暂停",Toast.LENGTH_SHORT).show(); //停止歌词的更新 handler.removeCallbacks(updateTimeCallback); pauseTime = System.currentTimeMillis(); }else{ //Runnable对象加入消息队列,在handler绑定的线程中执行,用于歌词更新 handler.postDelayed(updateTimeCallback, 5); Toast.makeText(PlayActivity.this, "继续播放",Toast.LENGTH_SHORT).show(); start = System.currentTimeMillis() - pauseTime+start;//保存现场 } isPlaying = isPlaying?false:true; } }
停止:
class StopListener implements OnClickListener{ @Override public void onClick(View arg0) { Toast.makeText(PlayActivity.this, "停止",Toast.LENGTH_SHORT).show(); stopMusic = true; seekBar.setProgress(0); Intent intent = new Intent(); intent.setClass(PlayActivity.this, PlayService.class); intent.putExtra("mp3Info", mp3Info); intent.putExtra("MSG", AppConstant.PlayerMsg.STOP_MSG); startService(intent); //停止歌词的更新 handler.removeCallbacks(updateTimeCallback); } }
来看下播放服务的代码:
@Override public int onStartCommand(Intent intent, int flags, int startId) { if(intent.getIntExtra("progress", 0) != 0){/////////////////////// if(isPlay){ //进度条进度 int progress = intent.getIntExtra("progress", 0); if(progress != 0) mediaPlayer.seekTo(progress*totalLength/100); } }////////////////////////// else{ mp3Info = (MP3Info) intent.getSerializableExtra("mp3Info"); int MSG = intent.getIntExtra("MSG", 0); if(mp3Info != null){ if(MSG == AppConstant.PlayerMsg.PLAY_MSG){ play(mp3Info); } else if(MSG == AppConstant.PlayerMsg.PAUSE_MSG){ pause(); } else if(MSG == AppConstant.PlayerMsg.STOP_MSG){ stop(); } } } return super.onStartCommand(intent, flags, startId); }
当startService()被调用时,服务实例就会被创建,并且调用服务的onStartCommand()方法,在该方法中关于进度条进度的,下篇再细讲。这里该方法主要获得从播放界面传过来的Intent对象,获得Intent对象携带的关于播放状态的信息。然后根据不同的状态调用不同的方法。
开始播放:
public void play(MP3Info mp3Info){ if(!isPlay){ //获得了被点击的mp3文件名 String path = getPath(mp3Info); //由MP3文件路径创建一个MediaPlayer mediaPlayer = MediaPlayer.create(PlayService.this,Uri.parse("file://"+path)); //获得音乐长度 totalLength = mediaPlayer.getDuration();///////////////////// //是否循环播放 mediaPlayer.setLooping(false); //开始播放 mediaPlayer.start(); //设置标志位 isPlay = true; isStop = false; } }
暂停:
public void pause(){ if(mediaPlayer != null){ if(!isStop){ if(!isPause){ mediaPlayer.pause(); isPause = true; } else{ mediaPlayer.start(); isPause = false; } } } }
public void stop(){ if(isPlay) if(!isStop){ mediaPlayer.stop(); mediaPlayer.release(); isStop = true; // } isPlay = false; }
播放中获得被挑选来播放的MP3文件路径的方法getPath():
public String getPath(MP3Info mp3Info){ String SDPath = Environment.getExternalStorageDirectory().getAbsolutePath(); String path = SDPath + File.separator+"MP3"+File.separator+mp3Info.getMp3Name(); return path; }好了,不难理解,下一篇我会重点聊歌词显示和进度条调整播放进度部分,也是最复杂的一部分。整个项目源码将在下一篇博文给出。