Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update MusicPlayer SeekBar in Service

I'm trying to update music player SeekBar in service, but nothing happens. The service start ok in my activity and bind correctly (because I can use some of the methods in my service and music play fine). Here is my service code:

public class MusicPlayerService extends Service {

MediaPlayer myMusicPlayer;
String path;
Intent getMusicId = new Intent();

// Binder given to clients
private final IBinder mBinder = new LocalBinder();

/**
 * Class used for the client Binder.  Because we know this service always
 * runs in the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {
    MusicPlayerService getService() {
        // Return this instance of LocalService so clients can call public methods
        return MusicPlayerService.this;
    }
}


@Override
public void onCreate() {
    // TODO Auto-generated method stub
    myMusicPlayer = new MediaPlayer();
    Log.d(getClass().getSimpleName(),"onCreate()");
    super.onCreate();
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // TODO Auto-generated method stub

    Log.d(getClass().getSimpleName(), "onStartCommand()");

    return super.onStartCommand(intent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
    path = intent.getStringExtra("musicID");

    Log.e("Music path on SD received from intent", path);

    try {
        myMusicPlayer.setDataSource(path);
        myMusicPlayer.setLooping(true);
        myMusicPlayer.prepare();
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    myMusicPlayer.start();

    Log.d(getClass().getSimpleName(), "onBind()");

    return mBinder;
}

/** method for clients */
public int getMusicDuration() {
  return myMusicPlayer.getDuration();
}

public int getMusicCurPos(){
    return myMusicPlayer.getCurrentPosition();
}

public void pauseMusic(){
    myMusicPlayer.pause();
    Log.d(getClass().getSimpleName(), "pauseMusic()");
}

public void playMusic(){
    myMusicPlayer.start();
    Log.d(getClass().getSimpleName(), "start()");
}
public void stopMusic(){
    myMusicPlayer.stop();
    Log.d(getClass().getSimpleName(), "stop()");
}
public void seekToPos (int pos){
    myMusicPlayer.seekTo(pos);
}

}

Interesting part is, after binding the service to my activity and run it some methods of the service returning null value like getDuration() and some of them work find like onStart() and onDestroy().

Thanks in advance.

Update:

In your activity you have to check if the service bound because it take a while to do, then use the public methods that it provide like:

//Bound Music service and pass the music path
    Intent musicIntent = new Intent(this, MusicPlayerService.class);
    musicIntent.putExtra("musicID", path); //Put Extra data for music player to play the exact file
    bindService(musicIntent, mConnection, Context.BIND_AUTO_CREATE); //Bound the Music player service

    //Music Handler for methods
    musicMethodsHandler = new Handler();
    musicRun = new Runnable() {

        @Override
        public void run() {
            if (mBound == true){ // Check if service bounded
                if (musicTotTime == null){ // Put data in it one time
                    musicTotTime = myMusicPlayer.getMusicDuration();
                    Log.v("Music Duration of Player in thread", musicTotTime.toString());
                    seekBar.setMax(musicTotTime);
                }
                musicCurTime = myMusicPlayer.getMusicCurPos();
                Log.v("Music Duration of Player in thread", musicCurTime.toString());
                seekBar.setProgress(musicCurTime);
            }else if(mBound == false){ // if service is not bounded log it
                Log.v("Still waiting to bound", Boolean.toString(mBound));
            }
            musicMethodsHandler.postDelayed(this, 1000);
        }
    };
    musicMethodsHandler.postDelayed(musicRun, 1000);


/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className,
            IBinder service) {
        // We've bound to LocalService, cast the IBinder and get LocalService instance
        LocalBinder binder = (LocalBinder) service;
        myMusicPlayer = binder.getService();
        mBound = true;

    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
    }
};

and keep in mind that the onCreate() method of services run first and one time.

like image 974
Sasan Avatar asked Jun 22 '13 05:06

Sasan


1 Answers

You shouldn't update the UI directly from your Service class, this is not its responsibility.

In your Activity you can run a CountDownTimer or similar to periodically poll your Service to handle SeekBar updates.

If you need to send messages from your Service to your Activity (such as when the track is finished, etc.) you can use a LocalBroadcastManager

Some examples:

  • https://stackoverflow.com/a/6256166/833647
  • https://stackoverflow.com/a/14695943/833647
like image 94
Ken Wolf Avatar answered Sep 28 '22 08:09

Ken Wolf