Android自带Music播放器更新播放时间和进度条的代码在packages/appsMusic/MediaPlaybackActivity.java文件中。
源码参考:http://www.oschina.net/code/explore/android-2.2-froyo/com/android/music/MediaPlaybackActivity.java
1.在onStart()函数中,启动更新播放时间和进度条的操作
先调用更新时间和进度条的操作,根据返回值来确定下次更新的时间点,这个返回值决定了下次更新的时间间隔。
0505 long next = refreshNow(); 0506 queueNextRefresh(next);
2.更新进度条函数refreshNow
默认返回的下次更新时间间隔是500ms。
下次更新的时间间隔是通过取得当前的播放位置计算出来的,取得当前播放位置后,1000ms减去模除1000ms的值就是下次更新的时间间隔。所以下次更新的时间间隔最大不超过1秒。如果减少最大更新时间间隔,可以修改此处。例如修改为最大不超过500ms:
long remaining = 500 - (pos % 500);
refreshNow函数的代码:
1179 private long refreshNow() { 1180 if(mService == null) 1181 return 500;// 默认返回值500ms 1182 try { 1183 long pos = mPosOverride < 0 ? mService.position() : mPosOverride;// 取得当前的播放位置 1184 long remaining = 1000 - (pos % 1000); // 计算出下次更新进度条的时间间隔(1秒以内) 1185 if ((pos >= 0) && (mDuration > 0)) { 1186 mCurrentTime.setText(MusicUtils.makeTimeString(this, pos / 1000)); // 设置当前的播放时间 1187 1188 if (mService.isPlaying()) { 1189 mCurrentTime.setVisibility(View.VISIBLE); 1190 } else { 1191 // blink the counter 1192 int vis = mCurrentTime.getVisibility(); 1193 mCurrentTime.setVisibility(vis == View.INVISIBLE ? View.VISIBLE : View.INVISIBLE); 1194 remaining = 500; 1195 } 1196 1197 mProgress.setProgress((int) (1000 * pos / mDuration)); // 设置当前的进度条位置 1198 } else { 1199 mCurrentTime.setText("--:--"); 1200 mProgress.setProgress(1000); 1201 } 1202 // return the number of milliseconds until the next full second, so 1203 // the counter can be updated at just the right time 1204 return remaining;// 返回下次更新的时间间隔 1205 } catch (RemoteException ex) { 1206 } 1207 return 500;// 默认返回值500ms 1208 }
取得当前播放位置的函数mService.position(),是调用MediaPlaybackService类的position()函数取得的。
MediaPlaybackService类的position()函数又调用他的子类MultiPlayer类的position()函数。
MultiPlayer类的position()函数又是通过调用MediaPlayer类的getCurrentPosition()函数来取得当前播放位置的。
3.发送下次更新的消息函数queueNextRefresh函数
此函数用于发送在延迟下次更新的时间间隔后更新进度条的message
1171 private void queueNextRefresh(long delay) { 1172 if (!paused) { 1173 Message msg = mHandler.obtainMessage(REFRESH); // 得到REFRESH消息 1174 mHandler.removeMessages(REFRESH); // 从队列中移除未处理的消息 1175 mHandler.sendMessageDelayed(msg, delay); // 重新发送REFRESH消息,在接受到REFRESH消息后,又会调用到此处,这样就可以循环更新 1176 } 1177 }
4.Handler处理异步消息REFRESH
用Handler处理异步消息,并更新主线程的播放时间和进度条。
1210 private final Handler mHandler = new Handler() { 1211 @Override 1212 public void handleMessage(Message msg) { 1213 switch (msg.what) { 1214 case ALBUM_ART_DECODED: 1215 mAlbum.setImageBitmap((Bitmap)msg.obj); 1216 mAlbum.getDrawable().setDither(true); 1217 break; 1218 1219 case REFRESH: 1220 long next = refreshNow(); // 更新music播放界面进度条 1221 queueNextRefresh(next); // 下次更新进度条的时间间隔,延迟next时间后更新进度条 1222 break;