今天的播放器利用了service,播放音乐在service端,进度条在activity端,因此主要的工作就是activity和service的交互,本文将利用IBinder进行交互,主要是activity可以调用service的函数,可以参考我的这篇博客。
本文关键点:利用利用IBinder实现activity 控制service
实现功能:
1 控制播放进度:
activity调用service的函数,对MediaPlayer进行控制。包括启动时的播放和滑动seekbar时,对MediaPlayer进行设置,达到控制播放进度的控制。
2 播放进度更新:
在activity开启多线程,后台每隔100ms就发送一次message,在UI线程中利用handler对message进行判定,之后activity调用service的函数,得到播放的进度(百分比),及时更新seekbar的进度条。
效果图如下:
布局很简单,如下所示:
复制代码
activity的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="play"/> <Button android:id="@+id/playButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="play" /> <Button android:id="@+id/pauseButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pause" /> <SeekBar android:id="@+id/seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:max="100" android:progress="10" /> </LinearLayout>
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205<pre name="code" class="java">public class MainActivity extends Activity { Boolean mBound = false; MusicService mService; SeekBar seekBar; //多线程,后台更新UI Thread myThread; //控制后台线程退出 boolean playStatus = true; //处理进度条更新 Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg){ switch (msg.what){ case 0: //从bundle中获取进度,是double类型,播放的百分比 double progress = msg.getData().getDouble("progress"); //根据播放百分比,计算seekbar的实际位置 int max = seekBar.getMax(); int position = (int) (max*progress); //设置seekbar的实际位置 seekBar.setProgress(position); break; default: break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //定义一个新线程,用来发送消息,通知更新UI myThread = new Thread(new MyThread()); //绑定service; Intent serviceIntent = new Intent(this , MusicService.class); //如果未绑定,则进行绑定 if(!mBound){ bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE); } //初始化播放按钮 Button playButton = (Button)findViewById(R.id.playButton); playButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { // TODO Auto-generated method stub if(mBound){ mService.play(); } } }); //初始化暂停按钮 Button pauseButton = (Button)findViewById(R.id.pauseButton); pauseButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { // TODO Auto-generated method stub //首先需要判定绑定情况 if(mBound){ mService.pause(); } } }); seekBar = (SeekBar)findViewById(R.id.seekbar); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { //手动调节进度 // TODO Auto-generated method stub //seekbar的拖动位置 int dest = seekBar.getProgress(); //seekbar的最大值 int max = seekBar.getMax(); //调用service调节播放进度 mService.setProgress(max, dest); } @Override public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub } @Override public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } }); } //实现runnable接口,多线程实时更新进度条 public class MyThread implements Runnable{ //通知UI更新的消息 //用来向UI线程传递进度的值 Bundle data = new Bundle(); //更新UI间隔时间 int milliseconds = 100; double progress; @Override public void run() { // TODO Auto-generated method stub //用来标识是否还在播放状态,用来控制线程退出 while(playStatus){ try { //绑定成功才能开始更新UI if(mBound){ //发送消息,要求更新UI Message msg = new Message(); data.clear(); progress = mService.getProgress(); msg.what = 0; data.putDouble("progress", progress); msg.setData(data); mHandler.sendMessage(msg); } Thread.sleep(milliseconds); //Thread.currentThread().sleep(milliseconds); //每隔100ms更新一次UI } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder binder) { // We've bound to LocalService, cast the IBinder and get LocalService instance MyBinder myBinder = (MyBinder) binder; //获取service mService = (MusicService) myBinder.getService(); //绑定成功 mBound = true; //开启线程,更新UI myThread.start(); } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onDestroy(){ //销毁activity时,要记得销毁线程 playStatus = false; super.onDestroy(); } }
复制代码
service的代码如下:
1
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101public class MusicService extends Service { IBinder musicBinder = new MyBinder(); //获取到activity的Handler,用来通知更新进度条 Handler mHandler; //播放音乐的媒体类 MediaPlayer mediaPlayer; //本地歌曲的路径 String path = "/storage/sdcard1/Music/浪漫满屋.mp3"; private String TAG = "MyService"; @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate() executed"); init(); } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub //当绑定后,返回一个musicBinder return musicBinder; } class MyBinder extends Binder{ public Service getService(){ return MusicService.this; } } //初始化音乐播放 void init(){ //进入Idle mediaPlayer = new MediaPlayer(); try { //初始化 mediaPlayer.setDataSource(path); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // prepare 通过异步的方式装载媒体资源 mediaPlayer.prepareAsync(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //返回当前的播放进度,是double类型,即播放的百分比 public double getProgress(){ int position = mediaPlayer.getCurrentPosition(); int time = mediaPlayer.getDuration(); double progress = (double)position / (double)time; return progress; } //通过activity调节播放进度 public void setProgress(int max , int dest){ int time = mediaPlayer.getDuration(); mediaPlayer.seekTo(time*dest/max); } //测试播放音乐 public void play(){ if(mediaPlayer != null){ mediaPlayer.start(); } } //暂停音乐 public void pause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } //service 销毁时,停止播放音乐,释放资源 @Override public void onDestroy() { // 在activity结束的时候回收资源 if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } super.onDestroy(); } }
最后
以上就是复杂硬币最近收集整理的关于android 利用 service 实现音乐播放的全部内容,更多相关android内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复