我们今天的目的是学习如何创建一个简单的音乐播放器,可支持播放,暂停,继续播放,以及进度显示,已经进度拖拽。
既然我们的目的已经很明确,那我们先分析一下:
1: 我们播放音乐的任务可以放在Activity中吗?
假设我们当前音乐播放,我们切到别的应用,这时候播放音乐的Activity所在的进程就属于后台进程,因为后台进程会由于系统资源不足时,会杀死当前进程,会导致音乐不播放了。所以采用Activity是不行的。
2:播放音乐的任务放在一个服务中,那服务有2中启动方式,应该使用那种服务?
a:如果采用StartServer启动服务,那服务里的播放音乐的方法是没法拿到的。
b:如果采用BindService启动服务,但是BindService启动的服务,当Activity退出时,服务也会退出的。
3:所以,我们就将2中服务结合起来,用StartServer启动服务,然后用BindService绑定服务,这时候即便是Activity退出了,服务也照常工作。同时也可以拿到服务里的音乐控制方法。
那既然分析清楚了如何做。那我们就开始行动。
第一步: 先创建一个简单的Activity,里面有播放,暂停,继续播放,退出按钮(布局文件就不贴出了)。然后启动服务
//启动服务,然后需要绑定服务 conn = new MyServiceConn(); intent = new Intent(this, MusicService.class); startService(intent); bindService(intent, conn, BIND_AUTO_CREATE);
@Override public void onCreate() { // 服务创建时,我们创建MediaPlayer super.onCreate(); player = new MediaPlayer(); }
我们先看一张关于如何启动音乐的图
从上图中可以看到,启动音乐播放需要几个步骤:
1:reset(重置)
2:setDataSource(设置数据源)
3:prepare(准备)
4:start(播放)
如果当前正在播放,需要暂停就需要调用pause()
如果想从暂停回到播放就需要调用(onstart)
如果向停止播放就需要调用(onstop),如果向接着播放就需要重新prepare,start
一下是如何启动音乐播放:
//服务的播放方法 public void play() { //1: 先重置 player.reset(); try { //2:设置数据 player.setDataSource("sdcard/smallapple.mp3"); //3.准备 player.prepare(); //4.开始播放 player.start(); //5.启动定时器 addTimer(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
//服务的暂停服务 public void pause() { player.pause(); }
//服务的继续播放 public void continuePlay() { player.start(); }
既然需要每秒都使得进度条的进度改变,那就需要增加一个定时器,定时器每秒得到当前播放进度,然后通知UI显示更新
//添加定时器,用于每秒更新播放进度 public void addTimer() { if(timer == null) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { //获取音乐的总时间 int duration = player.getDuration(); //获取音乐的当前播放时间 int currposition = player.getCurrentPosition(); //获得到的数据,需要传入到UI更新,我们用msg传送 Message msg = MainActivity.handler.obtainMessage(); //通过bundle传送数据 Bundle data = new Bundle(); data.putInt("duration", duration); data.putInt("currposition", currposition); msg.setData(data); //发送消息给Activity MainActivity.handler.sendMessage(msg); } //开始计时任务后的5毫秒,第一次执行run方法,以后每1000毫秒执行一次 }, 5, 1000); } }
static Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { Bundle data = msg.getData(); sBar.setMax(data.getInt("duration")); sBar.setProgress(data.getInt("currposition")); }; };第五步: 如果我们想实现拖拽,就可以给SeekBar增加Seekbar改变监听
sBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub mInterface.seekTo(seekBar.getProgress()); } @Override public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } @Override public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub } });
到这里大概就完事了,以下是详细 代码
MainActivity中代码:
public class MainActivity extends Activity { MusicInterface mInterface; private static SeekBar sBar; private MyServiceConn conn; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sBar = (SeekBar) findViewById(R.id.seekBar1); sBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub mInterface.seekTo(seekBar.getProgress()); } @Override public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } @Override public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub } }); //启动服务,然后需要绑定服务 conn = new MyServiceConn(); intent = new Intent(this, MusicService.class); startService(intent); bindService(intent, conn, BIND_AUTO_CREATE); } static Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { Bundle data = msg.getData(); sBar.setMax(data.getInt("duration")); sBar.setProgress(data.getInt("currposition")); }; }; class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { //获得服务中间人 mInterface = (MusicInterface)arg1; } @Override public void onServiceDisconnected(ComponentName arg0) { // TODO Auto-generated method stub } } //开始播放 public void start(View v) { mInterface.play(); } //暂停播放 public void pause(View v) { mInterface.pause(); } //继续播放 public void continuePlay(View v) { mInterface.continuePlay(); } //退出 public void exit(View v) { //先解绑服务 unbindService(conn); //在停止服务 stopService(intent); finish(); } }
public class MusicService extends Service { MediaPlayer player; private Timer timer; @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return new MusicController(); } @Override public void onCreate() { // 服务创建时,我们创建MediaPlayer super.onCreate(); player = new MediaPlayer(); } @Override public void onDestroy() { // 销毁服务时,需要先停止播放,再释放资源 super.onDestroy(); //停止服务 player.stop(); //释放底层硬件占有的资源 player.release(); player = null; if(timer != null) { //取消定时器 timer.cancel(); timer = null; } } class MusicController extends Binder implements MusicInterface { @Override public void play() { // TODO Auto-generated method stub MusicService.this.play(); } @Override public void pause() { // TODO Auto-generated method stub MusicService.this.pause(); } @Override public void continuePlay() { // TODO Auto-generated method stub MusicService.this.continuePlay(); } @Override public void seekTo(int progress) { // TODO Auto-generated method stub MusicService.this.seekTo(progress); } } //服务的播放方法 public void play() { //1: 先重置 player.reset(); try { //2:设置数据 player.setDataSource("sdcard/smallapple.mp3"); //3.准备 player.prepare(); //4.开始播放 player.start(); //5.启动定时器 addTimer(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //服务的暂停服务 public void pause() { player.pause(); } //服务的继续播放 public void continuePlay() { player.start(); } //服务的拖动移动 public void seekTo(int progress) { player.seekTo(progress); } //添加定时器,用于每秒更新播放进度 public void addTimer() { if(timer == null) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { //获取音乐的总时间 int duration = player.getDuration(); //获取音乐的当前播放时间 int currposition = player.getCurrentPosition(); //获得到的数据,需要传入到UI更新,我们用msg传送 Message msg = MainActivity.handler.obtainMessage(); //通过bundle传送数据 Bundle data = new Bundle(); data.putInt("duration", duration); data.putInt("currposition", currposition); msg.setData(data); //发送消息给Activity MainActivity.handler.sendMessage(msg); } //开始计时任务后的5毫秒,第一次执行run方法,以后每1000毫秒执行一次 }, 5, 1000); } } }
public interface MusicInterface { void play(); void pause(); void continuePlay(); void seekTo(int progress); }显示效果如下:
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/longwang155069/article/details/47168567