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 @Override32 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 @Override40 public void onStopTrackingTouch(SeekBar seekBar) {41 //根据拖动进度,改变音乐播放进度42 mi.seekTo(seekBar.getProgress());43 }44 //开始拖动时调用 45 @Override46 public void onStartTrackingTouch(SeekBar seekBar) {47 // TODO Auto-generated method stub48 49 }50 //拖动的时候不断调用51 @Override52 public void onProgressChanged(SeekBar seekBar, int progress,53 boolean fromUser) {54 // TODO Auto-generated method stub55 56 }57 });58 Intent intent = new Intent(this, MusicService.class);59 //先start启动MusicService,再bind60 startService(intent);61 MyServiceConn conn = new MyServiceConn();62 bindService(intent, conn, BIND_AUTO_CREATE);63 }64 65 class MyServiceConn implements ServiceConnection {66 67 @Override68 public void onServiceConnected(ComponentName name, IBinder service) {69 mi = (MusicInterface) service;70 }71 72 @Override73 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 @Override116 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 }