Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Communication between service and activity in an android mediaplayer app

I’m working on a media player app that will play music in the background using a service, but I am confused about all the different ways to communicate with the service. I want the service to tell the activity when it is playing so the button can change to pause. I also want a seek bar so I will need information about what is currently playing in the service.

I have been looking at different examples for a while now and it seems like everyone of them is doing it a different way. Some are binding the activity to the service, some just use global broadcasts, and the android music player is using aidl.

As far as a media player goes, which method should I be using? Is one going to allow me to do stuff that won't work on the other methods? What did using the aidl allow them to do?

like image 714
yukongt300ex Avatar asked Feb 20 '23 18:02

yukongt300ex


1 Answers

I've had roughly the same questions over the last several months. It's not a real easy question to answer because there are several variables that go into the decision. Likely, you'll end up using a combination of the options.

Q: Is the communication one way? Just from the service to the activity?
A: If so, then the LocalBroadcastManager is your friend. I've found this to be very useful and one of the easiest ways to communicate from service to activity.

Q: Do you expect other applications to receive your broadcasts?
A: If so, then you'll not be able to use the LocalBroadcastManager. You'll have to use global ones with Context.sendBroadcast() instead.

Q: Are you expecting to communicate back to the service from your activity?
A: This one is tricky. If you just need to tell the service something and don't expect anything in return then you can just use intents. But, if you need information back from the service then you'll definitely want to look into binding to that service.

I've found that when binding to your service I sometimes find myself playing a waiting game while the activity binds to the service. So, this can be a little difficult when time is important. You'll have to work to ensure that you've bound to the service well before you expect to communicate with it.

Given your example and assuming that your not expecting other applications to receive your broadcasts you could do something like the following within your media player service.

Intent broadcastIntent = new Intent(PlayerService.AUDIO_PLAYING);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);

Then, within your player activity you need to register as a listener for this intent. Maybe within your onCreate() or onStart(). This can vary depending on your application.

IntentFilter broadcastsToListenFor = new IntentFilter();
broadcastsToListenFor.addAction(PlayerService.AUDIO_PLAYING);
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, broadcastsToListenFor);

Your broadcastReceiver would look something like this...

// Set up broadcast receiver
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {

    @Override
    public synchronized void onReceive(Context context, Intent intent) {

        if(action.equals(PlayerService.AUDIO_PLAYING)) {

          // Set your play button image to pause here
        }
    }
};

Finally, make sure that you unregister your activity from receiving these broadcasts in the onStop() or onPause() method. Again, depending on your specific scenario...

LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);

We've done something very similar to this recently and it's working pretty well. I really think it's worth it to test and play around with each of the options because you'll probably find a situation where each of them is the right choice.

like image 92
Kevin Avatar answered Mar 13 '23 03:03

Kevin