android -best way to communicate between activity and background service - android

I'm trying to build a small MusicPlayer for learning purposes, and I'm stuck at a point on how to make communication between a background process and the activity. I've haven't seen anyone else's code but in my(almost amateur design) the activity and the service must be updating each other every second since the activity's control should be reflected in the services controls(like if the service had a GUI in android's notification bar) and the music playing should update the Activity's seekbar etc.
What would be the best way to implement the service, so that it can run independent but in sync with the activity?

I followed these instructions:
https://developer.android.com/guide/components/bound-services
A bound service is an implementation of the Service class that allows other applications to bind to it and interact with it. To provide binding for a service, you must implement the onBind() callback method. This method returns an IBinder object that defines the programming interface that clients can use to interact with the service.
Basically you implement your service and your activity as you have done and then when the activity resumes it can bind the service so that they can communicate.
In that same page you can find some code of how is it done in java and kotlin.

Related

Bound Service vs Unbound + singleton for communication

I have a service, I need to communicate to with it (one service - many fragments/activities). There are two options for this:
Have a singleton that controls the service - starts it and then binds to it (using the app context)
Have a singleton that controls the service - starts it, the service when ready registers back as a delegate to the singleton (in a WeakReference)
Solution no 2 seems simpler to me, but whenever I read about communication with services there is the concept of the bound service.
Is there any benefit of having a bound service instead of the service registering itself as a delegate (and unregistering with onDestroy)?
Edit 1: The service is to keep the communication alive, it's expensive to set up a new communication channel. Even if no one requested any data it should keep the channel alive (heartbeat).
The service is foreground, it should run even if the activity that requested the data gets killed by the system. The next time it is created the data will be there.
The data requested by one screen might be useful for some other (therefore has to be stored in a singleton).
Bound and unbound services are both usable patterns and you should pick whatever pattern is better for you use case.
You should pick bound service if you want your service to have the same lifecycle as the components that bind to it. If you need an independent service use an unbound version.
The only benefit of one approach versus another is the simplicity of implementation.
In you case, I think you need the service only while there are running activities and fragments, then the easiest way, in my opinion, would be to make a bound service and make every activity bind to it. With that, you'll get a simple communication interface between you activities (and fragments, since they have access to containing activity) and your service.
The benefits of this approach are:
the service will stop itself if all activities unbind and start itself when first activity binds to it.
you won't need to track all running activities in the singleton and manually unbind
you won't need to maintain a singleton manager, less code -> less bugs
sometimes onDestroy can be skipped by the system and you can leak the service with the 2 approach.
Since you need your service to be running the correct option will be to use a started service and make each activity bind to it when needed. It's a common pattern.
Started service will run until you explicitly stop it or it stops itself, you can have a singleton manager that will be responsible for that.
But at the same time you can communicate with the service from your activity using binding.
So basically comparing with the first suggested approach, you'll need some instance that will start and stop the service, but the communication between activities and service will be the same - using binding.
Yes, using a bound service in Android is a much better option when communicating with Views like Activities/Fragments. This is because of the following reasons,
It runs synchronously.
You can have more control on the service data when to show on UI thread of the view. You can choose when to call it in async/sync way.
LocalBroadcastManager only runs Asynchronously.

Android Bound Service vs Started Service for music app

I am trying to dive deep into service architecture.
Just for testing purpose I am creating music app.
Without doubts music should be played in service, but what kind of communication to use ?
As far as I know service can be bound or started (or both at the same time)
Firstly, I need to play/stop/pause/set source...
Secondly, I need to notify UI if music player is opened about events like progress, buffering...
Here my thoughts about this.
I think about mixing bound and started service.
As far as song can be set only from UI as well as paused/played/stopped/seek I choose communication with service from UI using binder. (Bound service inside activity and get binder back to communicate with service)
Notifications like track completed, next track , current track position coming from the service. I decided to use Broadcast receiver to send such notifications, because it can be multiple interested components.
So my question are
What is the best choice of communication (bound or broadcast) for music player service ?
How does System knows what kind of service is ? I mean that even if the service is bound I need to call startService method at first and than bind it. Does it mean that if even one bindService method was called it is considered as bound service and it would be killed when unbind method is called ?
Does LocalBroadcastManager make sense in communication with service ? As far as LocalBroadcastManager is local for each app, why not to use bound service than ? Global broadcast makes sense in case other apps are interested in events.
Please help to understand this mechanism.
Best choice of communication is using both LocalBroadcasts as well as Binder methods as per your requirement. If you want to do something in service from your bound component like activity then you should use binders. If you need to send result back to application you should use LocalBroadcast.
There is one more option available to use messaging. In this case both activity and service use same ibinder hence two way communication is easy. You can send message from activity to service and service to your activity
In this point you are wrong about starting bound service. You don't need to call startservice in this case. Just a call of bindservice method is required.
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
you can bind multiple components to this service. When all of them are unbound then service will be stopped.
Yes LocalBroadcastmanagers make sense. Lets say you want to broadcast something in your app. There are 4-5 components that you want to update.How will you achieve this. Hence the use of localbroadcasts is a good feature.
For example lets say there are two services starting from different activities and second service starts its work when first service has done its work. So, only way to achieve this is send a broadcast and second service will be registering for this broadcast. Hence it will receive it.
Yeah. Services are pretty hard to understand.
There are some things that are easy. A bound service is always started with a bindService method. A started service is always started with a startService method. You do not need to start a bound service, or bind a started service.
A lot of what follows is gross generalization...
Started Service
A started service is nearly useless, unless it is an IntentService. IntentServices are pretty good tools for running asynchronous tasks. You send them a small bundle of parameters and they go off and do whatever those parameters indicate. They are like void methods in that one expects to use their side-effects, not a return value.
Bound Service
A bound service is harder to explain. Although the metaphor breaks down on careful examination, a bound service something like a singleton factory. It is, for instance, a way of providing a single object, with is single state, to all of the Activities in a application. Among its interesting features is that, as long as the service that provided the singleton object is bound, the hosting process is less likely to be killed off. Note that, the "singleton" object that the bound service provides has little to do with the service that provides it. Unbinding the service does not invalidate it.
Bound services are also the main means of doing inter-process communication, in Android.
What should you do?
Well, that's a pretty general question. Here's a thought. Putting your music player in a service makes a lot of sense. If the communication to it is mostly one way -- commands to the service -- there is a chance that you can do it with an IntentService. Until there's a specific reason to do something more complex, an IntentService has the advantage of being simpler.

Need Android background service

I am building an Android application.
I am trying to do a running app. this means I will need a background service running and counting my GPS data and report that to the activity.
But - I want the activity to be able to send actions to this service too (Start, Stop , etc).
I have struggled with a few methods of doing this 2-way service<->activity communications.
Any reference? what is the best approach to do that?
Thanks
Did you try service bind mechanism?
You can create service for collecting GPS data (http://developer.android.com/guide/components/services.html), start it on application startup (http://developer.android.com/guide/components/services.html#StartingAService), bind this service on starting your activity and use binder object for transferring data between the service and activity (http://developer.android.com/guide/components/bound-services.html), unbind on closing your activity and service will continue working on background.
In this model, your service will work always and will transfer data when it needed.
Binding might be an overkill when you deal with the same process. I would recommend using Otto from Square as an event bus mechanism to post events to your service and vice versa.
If you dont want to add a library to your project then consider using the LocalBroadcastManager that is part of the support library.

Service or Bound Service?

I'm creating an application that connects to an XMPP server on Android. I want to keep the connection on till the user logs out.
Should I use a regular Service or a Bound Service to keep the connection on?
Any tips, advice and helpful information are welcomed.
I like this explanation:
Started services are easy to program for simple one way interactions
from an activity to a service, however, they require more complex and
ad hoc programming for extended two-way conversations with their
clients.
In contrast, bound services may be a better choice for more
complex two-way interactions between activities and services. For
example, they support two-way conversations.
So, as you said, If you want to interact with the service use bound service. With started services (or intent services) you could do it, only it would require more complex programming.
(by Douglas Schmidt: https://www.youtube.com/watch?v=cRFw7xaZ_Mg (11'10'')):
Here is a summary that helped me understand (thanks Doug):
Finally, one last link that helped me also:
http://www.techotopia.com/index.php/An_Overview_of_Android_Started_and_Bound_Services
Started services are launched by other application components (such as an activity or even a broadcast receiver) and potentially run indefinitely in the background until the service is stopped, or is destroyed by the Android runtime system in order to free up resources. A service will continue to run if the application that started it is no longer in the foreground, and even in the event that the component that originally started the service is destroyed
A bound service is similar to a started service with the exception that a started service does not generally return results or permit interaction with the component that launched it. A bound service, on the other hand, allows the launching component to interact with, and receive results from, the service.
A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC). A bound service typically lives only while it serves another application component and does not run in the background indefinitely.
If all the code exists in one activity from user connected to user logout then go for bound service
But if it is code exists in multiple activities try with service
I found out the difference between the two and when to use it. If you want to interact with the service (for example send arguments etc), use bound service and it return the service object in the onServiceConnected method (where you can call methods in the service). You cannot interact with a regular service (from another class)

Binding to Service from Activity or starting service in different process?

I want to do Bluetooth connection in Service. And there needs to be interaction between Activities and Services. The service should be started as soon as the app is started and should be able to communicate with UI Activities on certain situations.
What should be the appropriate way of doing it? If I bind the service from only one Activity then that service will be communicating only with that Activity. So, do I need to take AIDL based approach or is there any other way out for this?
Otherwise, can I have a class that extends Application class and then start the service from there and bind the Application class instead?
This is quite a broad question, so I'll answer as best as I can. From what I know of services, multiple activities can bind a single service, all having access to it. Only once all activities that bound the service end their connections (by unbinding), does the service actually stop.
The android documentation on services tells us:
... the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated
So my recommendation would be to bind the service from all activities that need to communicate with it. When binding with a service an IBinder is returned, which you can use to communicate with the service. Again according to the Android documentation on services:
Usually the IBinder returned is for a complex interface that has been written in aidl.
Although if you only need to perform simple communication with the service, you could use the Messenger class instead of writing full AIDL files. A sample of this can be found here.
Hope this answers your question!
You could bind directly to the Service as the above answer states, however there is no need for Messengers. Your service will be running in the same process as your activity 99.9% of the time. Messengers are designed for inter-process communication (IPC). Also no need for AIDL - that was designed for advanced IPC.
Instead, you should use: BroadcastReceivers and Intents. This is what they were designed for (communication between components in an app).

Categories

Resources