0

I'm using bound service so that I am able to communicate between an activity and a service.

I'm binding to a service in onStart:

@Override
protected void onStart() {
    super.onStart();
    Intent bindIntent = new Intent(this, MusicService.class);
    bindService(bindIntent, this, BIND_AUTO_CREATE);
}

waiting for service to bind:

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
    mMusicService = ((MusicService.LocalBinder) service).getService();
    mMusicService.setCallback(this);
}

handling disconnect from service:

@Override
public void onServiceDisconnected(ComponentName name) {
    mMusicService = null;
}

unbinding from service in onDestroy:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mMusicService != null && isFinishing()) {
        mMusicService.setCallback(null);
        unbindService(this);
    }  
}

My problem is that when app is minimized, onDestroy gets called immediately and then onUnbind in Service gets called and music is stopped.

Here is onUnbind method (where mPlayer is MediaPlayer):

@Override
public boolean onUnbind(Intent intent) {
    mPlayer.stop();
    mPlayer.release();
    mPlayer = null;

    return super.onUnbind(intent);
}

If I don't implement onUnbind music continues to play (sometimes and sometimes it stops after some time) and when I open the app again (from minimized applications) I am able to play another song and then those two song play at same time.

I've red couple articles about music players and services on android and I thought that this was correct approach (thinking that onDestroy will be called when OS is out of memory).

Any ideas how I can re-implement my app workflow so that I will work as expected?

EDIT

At first I thought that "Don't keep activities" under developer options is a problem, but problem is still there even if I uncheck it.

And if some code from my service is needed please say I will edit my question (there's a lot of code and I'm not sure which part is important for this issue)

SOLUTION:

startForeground(<notification id>, <notification>);

to run service even if app gets killed. And when user dismisses the notification:

stopForeground(true);
stopSelf();

More about startForeground here.

Dusan Malic
  • 231
  • 4
  • 15
  • why do you stop the player in onUnbind??? your player has to keep playing when you quit your app or not? control your mPlayer directly from your Binder API, not from binding/unbinding events – pskink Sep 14 '15 at 09:47
  • Even if I move that code in Services `onDestroy()` it is called right after Activitys `onDestroy()`. – Dusan Malic Sep 14 '15 at 10:02
  • then `startService` just before `bindService` (in that case you can pass 0 flag in `bindService(bindIntent, this, 0)`), thats all – pskink Sep 14 '15 at 10:02
  • check this https://github.com/protocol10/ASplayer – Akshay Mukadam Sep 15 '15 at 11:05

1 Answers1

0

It's not obvious, but you should start a Thread that runs in background and use the service to control it's state.

A service isn't a thread that hold some run state like a thread. Unless it's an IntentService. (Correct me if I'm wrong)

While activity can (and probably will) get destroyed, your app will keep running.

Activity:

@Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, BackgroundService.class);
        startService(intent);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        finishOnPause = true;
    }

@Override
    protected void onStop() {
        super.onStop();
        unbindService(mServiceConnection);
    }

Service:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        ensureServiceThread();

        if (intent != null) {

        }

        return START_NOT_STICKY;
    }

private void ensureServiceThread() {
        if (service_thread == null) {
            service_thread = new ServiceThread(this);
            service_thread.start();
        }
    }

@Override
    public void onDestroy() {
        stopServiceThread();
        super.onDestroy();
    }

private void stopServiceThread() {
        if (service_thread != null) {
            service_thread.interrupt();
            service_thread = null;
        }
    }

And you should do your work inside the Thread. If you need context, it's your Service. If you need to do something on Main thread - create a Handler in Service.OnCreate and do a handler.postRunnable inside a worker thread safely.

What I would do is: - Create a service - Create a thread - Create a media player inside a thread (if possible, otherwise on Service creation and pass it to thread) - Inside a thread - continuously poll media player state - On song finished send an intent to service that change track - stop thread/service if needed.

Anfet
  • 397
  • 4
  • 8