Android开发之音乐播放器的实现

时间:2022-10-11 17:44:00

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 }