我正在尝试制作一个带有绑定服务的基本音乐播放器。问题是MP播放的时间越短。我比较了MP完成的时间,看到了发生了什么,但无法弄清楚原因。有人可以帮忙吗?
当MP完成时,这是我的logcat。
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(this, "Media Completed", Toast.LENGTH_SHORT).show();
Log.i("TEST", "TOTAL DUR: " + mp.getDuration() + " CURRENT DUR: " + mp.getCurrentPosition() + "");
}
I/TEST: TOTAL DUR: 193131 CURRENT DUR: 186932
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener{
private String msg = "Android : ";
private TextView tvTime;
private Button btnPlay, btnPause, btnRestart;
private LocalService mService;
private boolean mBound = false;
// ----- seekbar variables -----------
private SeekBar seekBar;
private int seekMax;
private boolean mBroadcastIsRegistered;
// ---- broadcast action and intent for fromuser seekbar
public static final String BROADCAST_SEEKBAR_FROMUSER = "ysfcyln.musicplayerdemo.send_seekbar_fromUser";
Intent mIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTime = (TextView) findViewById(R.id.textView);
seekBar = (SeekBar) findViewById(R.id.seekBar);
btnPlay = (Button) findViewById(R.id.btn_play);
btnPause = (Button) findViewById(R.id.btn_pause);
btnRestart = (Button) findViewById(R.id.btn_restart);
seekBar.setOnSeekBarChangeListener(this);
btnPlay.setOnClickListener(this);
btnPause.setOnClickListener(this);
btnRestart.setOnClickListener(this);
Log.d(msg, "The onCreate() event");
Intent intent = new Intent(this, LocalService.class);
startService(intent);
// set up seekbar intent for broadcasting new position to service
mIntent = new Intent(BROADCAST_SEEKBAR_FROMUSER);
}
/** Called when the activity is about to become visible. */
@Override
protected void onStart() {
super.onStart();
Log.d(msg, "The onStart() event");
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
/** Called when the activity has become visible. */
@Override
protected void onResume() {
// ---- register broadcast -----
goRegisterBroadcast();
super.onResume();
Log.d(msg, "The onResume() event");
}
/** Called when another activity is taking focus. */
@Override
protected void onPause() {
// ---- unregister broadcast ----
unRegisterBroadcast();
super.onPause();
Log.d(msg, "The onPause() event");
}
/** Called when the activity is no longer visible. */
@Override
protected void onStop() {
super.onStop();
Log.d(msg, "The onStop() event");
}
/** Called just before the activity is destroyed. */
@Override
public void onDestroy() {
super.onDestroy();
Log.d(msg, "The onDestroy() event");
Log.d("mbound value", mBound + "");
if (mBound) {
Intent intent=new Intent(this,LocalService.class);
stopService(intent);
unbindService(mConnection);
mBound = false;
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_play:
//do something
if (mBound)
mService.playSong2("http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood-piano.mp3");
break;
case R.id.btn_pause:
//do something
if (mBound)
mService.pauseSong();
break;
case R.id.btn_restart:
//do something
if (mBound)
mService.restartSong();
break;
default:
break;
}
}
/** Defines callbacks for service binding, passed to bindService() */
public ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
@Override
public void onBackPressed(){
// this moves to activity to the back of the stack, effectively pausing it
moveTaskToBack(true);
}
// ---- updating position of seekbar from service
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
private void updateUI(Intent intent){
String counter = intent.getStringExtra("counter");
String mediamax = intent.getStringExtra("mediamax");
int seekProgress = Integer.parseInt(counter);
seekMax = Integer.parseInt(mediamax);
seekBar.setMax(seekMax);
seekBar.setProgress(seekProgress);
final int HOUR = 60*60*1000;
final int MINUTE = 60*1000;
final int SECOND = 1000;
int durationInMillis = seekMax;
int curVolume = seekProgress;
int durationHour = durationInMillis/HOUR;
int durationMint = (durationInMillis%HOUR)/MINUTE;
int durationSec = (durationInMillis%MINUTE)/SECOND;
int currentHour = curVolume/HOUR;
int currentMint = (curVolume%HOUR)/MINUTE;
int currentSec = (curVolume%MINUTE)/SECOND;
if(durationHour > 0){
tvTime.setText(" 1 = "+String.format("%02d:%02d:%02d/%02d:%02d:%02d",
currentHour,currentMint,currentSec, durationHour,durationMint,durationSec));
}else{
tvTime.setText(" 1 = "+String.format("%02d:%02d/%02d:%02d",
currentMint,currentSec, durationMint,durationSec));
}
}
// --- unregister receiver for seekbar ---
private void unRegisterBroadcast(){
if(mBroadcastIsRegistered){
try {
unregisterReceiver(broadcastReceiver);
mBroadcastIsRegistered = false;
} catch (Exception e){
e.printStackTrace();
}
}
}
// --- register receiver for seekbar ---
private void goRegisterBroadcast(){
registerReceiver(broadcastReceiver, new IntentFilter(mService.BROADCAST_ACTION));
mBroadcastIsRegistered = true;
}
// Override methods for seekbar on change listener
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser){
int seekPos = seekBar.getProgress();
mIntent.putExtra("seekpos", seekPos);
sendBroadcast(mIntent);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
LocalService.java
public class LocalService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener{
private MediaPlayer player;
public LocalService() {
}
// Returns the MyService instance
public class LocalBinder extends Binder {
public LocalService getService(){
return LocalService.this;
}
}
private IBinder mBinder = new LocalBinder();
// ---- SeekBar Variables --------------
int mediaPosition;
int mediaMax;
private final Handler handler = new Handler();
public static final String BROADCAST_ACTION = "ysfcyln.musicplayerdemo.seekprogress";
Intent seekIntent;
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
Log.i("Service Demo", "In onBind");
return mBinder;
}
/** Called when the service is being created. */
@Override
public void onCreate() {
super.onCreate();
Log.i("Service Demo", "Service Created");
player = new MediaPlayer();
initMusicPlayer();
// ----- Setup intent for seekbar -----------
seekIntent = new Intent(BROADCAST_ACTION);
// --- register for fromuser seekbar ----
registerReceiver(broadcastReceiver, new IntentFilter(MainActivity.BROADCAST_SEEKBAR_FROMUSER));
}
/** The service is starting, due to a call to startService() */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
/** Called when The service is no longer used and is being destroyed */
@Override
public void onDestroy() {
// stop the seekbar handler from sending updates to UI
handler.removeCallbacks(sendUpdatesToUI);
// unregister receiver to user input from seekbar
unregisterReceiver(broadcastReceiver);
super.onDestroy();
Log.i("Service Demo", "Service Destroyed");
}
/** Called when all clients have unbound with unbindService() */
@Override
public boolean onUnbind(Intent intent) {
Log.i("Service Demo", "In onUnbind");
player.stop();
player.reset();
player.release();
return super.onUnbind(intent);
}
/** Called when a client is binding to the service with bindService()*/
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
// to initialize the media class
public void initMusicPlayer(){
player.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
}
@Override
public void onPrepared(MediaPlayer mp) {
//start playback
mp.start();
// ---- set up seekbar handler ----
setUpHandler();
}
// -------- Send seekbar info to Activity ------
private void setUpHandler(){
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 Second
}
private Runnable sendUpdatesToUI = new Runnable() {
@Override
public void run() {
LogMediaPosition();
handler.postDelayed(this,1000); // 1 Second
}
};
private void LogMediaPosition(){
if(player.isPlaying()){
mediaPosition = player.getCurrentPosition();
mediaMax = player.getDuration();
seekIntent.putExtra("counter", String.valueOf(mediaPosition));
seekIntent.putExtra("mediamax", String.valueOf(mediaMax));
sendBroadcast(seekIntent);
}
}
// ---------- Receive seekbar position if it has been changed by the user in the activity ----
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateSeekPos(intent);
}
};
private void updateSeekPos(Intent intent){
int seekPos = intent.getIntExtra("seekpos", 0);
if(player.isPlaying()){
handler.removeCallbacks(sendUpdatesToUI);
player.seekTo(seekPos);
setUpHandler();
}
}
public void playSong(){
//play a song
player.reset();
String songUrl = "http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood-piano.mp3";
try{
player.setDataSource(getApplicationContext(), Uri.parse(songUrl));
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
public void pauseSong(){
if(player.isPlaying()){
player.pause();
} else {
player.start();
}
}
public void restartSong(){
if(player.isPlaying()){
player.stop();
player.release();
} else {
player.release();
}
}
// With input
public void playSong2(String songUrl){
//play a song
player.reset();
try{
player.setDataSource(getApplicationContext(), Uri.parse(songUrl));
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(this, "Media Completed", Toast.LENGTH_SHORT).show();
Log.i("TEST", "TOTAL DUR: " + mp.getDuration() + "CURRENT DUR: " + mp.getCurrentPosition() + "");
}
}
我用两个设备测试了它,三星Galaxy A7和三星Galaxy S4。歌曲持续时间是3:13,A7完成3:12,S4完成3:06