Android音乐播放器
使用到Android的Actiivity和Service组件
播放音频的代码应该运行在服务中,定义一个播放服务MusicService,服务里定义play、stop、pause、continuePlay等方法
把这几个方法抽取成一个接口MusicInterface
定义一个中间人类,继承Binder,实现MusicInterface
操作按钮等使用Activity与用户交互
同时为了把服务所在进程变成服务进程,防止Activity销毁时依旧执行Service,需要使用Service启动的混合调用,即先使用startService(),然后使用bindService()方法。
原理:使用bindService()方法,启动service。在ServiceConnection的onServiceConnected()方法中返回一个iBinder对象,通过该对象可以操作音乐service中的播放音乐的方法。
播放服务
代码:
MainActivity:
1 import android.app.Activity; 2 import android.content.ComponentName; 3 import android.content.Intent; 4 import android.content.ServiceConnection; 5 import android.os.Bundle; 6 import android.os.Handler; 7 import android.os.IBinder; 8 import android.view.View; 9 import android.widget.SeekBar; 10 import android.widget.SeekBar.OnSeekBarChangeListener; 11 12 public class MainActivity extends Activity { 13 14 private MusicInterface mi; 15 16 static Handler handler = new Handler() { 17 public void handleMessage(android.os.Message msg) { 18 Bundle bundle = msg.getData(); 19 //取出消息携带的数据 20 int duration = bundle.getInt("duration"); 21 int currentPosition = bundle.getInt("currentPosition"); 22 //刷新播放进度 23 sb.setMax(duration); 24 sb.setProgress(currentPosition); 25 }; 26 }; 27 28 29 30 private static SeekBar sb; 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 sb = (SeekBar) findViewById(R.id.sb); 36 //给sb设置一个拖动侦听 37 sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 38 //停止拖动时调用 39 @Override 40 public void onStopTrackingTouch(SeekBar seekBar) { 41 //根据拖动进度,改变音乐播放进度 42 mi.seekTo(seekBar.getProgress()); 43 } 44 //开始拖动时调用 45 @Override 46 public void onStartTrackingTouch(SeekBar seekBar) { 47 // TODO Auto-generated method stub 48 49 } 50 //拖动的时候不断调用 51 @Override 52 public void onProgressChanged(SeekBar seekBar, int progress, 53 boolean fromUser) { 54 // TODO Auto-generated method stub 55 56 } 57 }); 58 Intent intent = new Intent(this, MusicService.class); 59 //先start启动MusicService,再bind 60 startService(intent); 61 MyServiceConn conn = new MyServiceConn(); 62 bindService(intent, conn, BIND_AUTO_CREATE); 63 } 64 65 class MyServiceConn implements ServiceConnection { 66 67 @Override 68 public void onServiceConnected(ComponentName name, IBinder service) { 69 mi = (MusicInterface) service; 70 } 71 72 @Override 73 public void onServiceDisconnected(ComponentName name) { 74 75 } 76 77 } 78 79 public void play(View v) { 80 mi.play(); 81 } 82 83 public void continuePlay(View v) { 84 mi.continuePlay(); 85 } 86 87 public void pause(View v) { 88 mi.pause(); 89 } 90 91 public void stop(View v) { 92 mi.stop(); 93 } 94 }
MusicService:
1 import java.util.Timer; 2 import java.util.TimerTask; 3 4 import android.app.Service; 5 import android.content.Intent; 6 import android.media.MediaPlayer; 7 import android.media.MediaPlayer.OnPreparedListener; 8 import android.os.Binder; 9 import android.os.Bundle; 10 import android.os.IBinder; 11 import android.os.Message; 12 13 public class MusicService extends Service { 14 private MediaPlayer player; 15 private Timer timer; 16 17 @Override 18 public IBinder onBind(Intent intent) { 19 // TODO Auto-generated method stub 20 return new MusicMiddleMan(); 21 } 22 23 class MusicMiddleMan extends Binder implements MusicInterface { 24 public void play() { 25 MusicService.this.play(); 26 } 27 28 public void pause() { 29 MusicService.this.pause(); 30 } 31 32 public void continuePlay() { 33 MusicService.this.continuePlay(); 34 } 35 36 public void stop() { 37 MusicService.this.stop(); 38 } 39 40 @Override 41 public void seekTo(int progress) { 42 // TODO Auto-generated method stub 43 MusicService.this.seekTo(progress); 44 } 45 46 47 } 48 49 @Override 50 public void onCreate() { 51 // TODO Auto-generated method stub 52 super.onCreate(); 53 player = new MediaPlayer(); 54 55 } 56 57 public void play() { 58 System.out.println("播放"); 59 if (player == null) { 60 player = new MediaPlayer(); 61 } 62 player.reset(); 63 try {
//设置网络资源 64 player.setDataSource("http://192.168.5.100:8080/HEYJUDE.mp3"); 65 // 异步获取网络资源 66 player.prepareAsync(); 67 player.setOnPreparedListener(new OnPreparedListener() { 68 69 @Override 70 public void onPrepared(MediaPlayer mp) { 71 player.start(); 72 addTimer(); 73 74 } 75 }); 76 } catch (Exception e) { 77 e.printStackTrace(); 78 } 79 80 } 81 82 public void continuePlay() { 83 System.out.println("继续播放"); 84 player.start(); 85 } 86 87 public void pause() { 88 System.out.println("暂停"); 89 player.pause(); 90 } 91 92 public void stop() { 93 System.out.println("停止"); 94 player.stop(); 95 player.release(); 96 player = null; 97 if (timer!=null) { 98 timer.cancel(); 99 timer=null; 100 } 101 } 102 103 public void seekTo(int progress){ 104 player.seekTo(progress); 105 } 106 107 public void addTimer() { 108 //播放进度需要不停的获取,不停的刷新进度条,使用计时器每1000毫秒获取一次播放进度 109 //发消息至Handler,把播放进度放进Message对象中,在Handler中更新SeekBar的进度 110 if (timer == null) { 111 112 timer = new Timer(); 113 timer.schedule(new TimerTask() { 114 115 @Override 116 public void run() { 117 // 获取到歌曲总时长 118 int duration = player.getDuration(); 119 // 获取歌曲当前进度 120 int currentPosition = player.getCurrentPosition(); 121 Message msg = MainActivity.handler.obtainMessage(); 122 Bundle bundle = new Bundle(); 123 bundle.putInt("duration", duration); 124 bundle.putInt("currentPosition", currentPosition); 125 msg.setData(bundle); 126 MainActivity.handler.sendMessage(msg); 127 128 } 129 }, 5, 1000); 130 } 131 132 } 133 134 }
把MusicControl类抽取出来为接口,这样可以在MainActivity中只可以访问接口的方法,MusicControl类中的其他方法不被方法
MusicInterface:
1 public interface MusicInterface { 2 3 void play(); 4 void continuePlay(); 5 void stop(); 6 void pause(); 7 void seekTo(int progress); 8 9 }