I'm actually working on an android app based on a background service sharing data with activities.
I was wondering If it's better to call bindService so that activities can call service's methods or if it's better to use sendBroadcast from the Activity and registerReceiver from the service.
Both work, but which one is recommended?
Furthermore, my service instanciates classes handling Localisation, sensors... Those classes also need to pass data with the service. Same question should I better use bindservice or sendBroadcast from these classes to communicate with my service?
Thanks.
If at all if you want to pass data then use BroadcastReciever because its OnRecieve method expects an Intent as arguemnt.. So you can pass your data through intent using intent.putxxxxx().. and again you will find this Advantageous when you want do some periodic checking or invoke some actions etc..
Related
I have an Activity that starts and binds to a service. It sends an intent with a List of data and the service is responsible for periodically updating that data. This is done in the handleIntent (Intent) method. What I want to do is send the updated data back to the activity. Both the activity and the service are in the same application. How can I "listen" for requests from my service? Do I have to use a Messenger and/or Broadcast Receiver? what's the cleanest, easiest, most efficient way of doing this? Thanks.
I suggest you check EventBus. it will allow you to send events like local broadcast receiver. And from that in activity you can listen specific event and display result. you can even use interface to get callback from service also.
Without any library you can achieve this with LocalBroadcastManager.
http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
For this problem, you can use a ResultReceiver. If both the service and activity share the same ResultReceiver object then you can "push" data to the Activity from the Service using the "send(int, Bundle)" method and on the Activity side receive it with "onReceiveResult(int, Bundle)".
ResultReceiver | Android reference
I am developping a MusicPlayer app, and I use a local Service to be make the MediaPlayer run in the background. It seems that we can either send intent to start a Service or bind a Service. I understand the point of for startService, we leave it running and send intent to stopService, and for bindService, we get back a IBinder to communicate with the service. However, I'm wondering what's the point of doing this? Do we have to send intents to make it work?
If I just retrieve an static instance of Service, and directly call its methods, I can also implement both start it and communicate with it.
I found an example of not using startService nor bindService, but it works well as a simple MusicPlayer.
The fragment calls Service:
https://github.com/zacharytamas/spotify-sampler/blob/master/app/src/main/java/com/zacharytamas/spotifysampler/ui/PlayerFragment.java
The Service class:
https://github.com/zacharytamas/spotify-sampler/blob/master/app/src/main/java/com/zacharytamas/spotifysampler/services/PlayerService.java
However, I'm wondering what's the point of doing this?
To have the service be running, to tell the OS "hey, we are doing work here on behalf of the user, please let my process live a bit longer".
This is covered in the documentation.
Do we have to send intents to make it work?
Yes.
If I just retrieve an static instance of Service, and directly call its methods, I can also implement both start it and communicate with it.
Then it is merely a Java object, and there is no point in inheriting from Service. Also, it means that your process will live for less time when your UI is not in the foreground.
I found an example of not using startService nor bindService, but it works well as a simple MusicPlayer.
The service is started, via startService(), in ArtistSearchActivity. Until this is done, the service does not exist, and the singleton will be null.
startService is used when you don't need to communicate with the service.
BindService is used when yout need to communicate with it.
In your app, I think you will communicate with the service (for example, if you have an activity where you choose the song, your will send data to the service to say: "this is the song which you have to play now") and I think you will need BindService instead startService.
I hope this will help you :D
I have a Activity and a Service. I am using bindService to get the Binder object which gives my activity access to the service. So I am able to execute commands on the service easily. What I need is a way to have the service communicate back to the activity. Is the best way to handle this to make calls directly from my activity to the service via the service instance returned from the binder. Then use a local broadcast receiver to send messages back from the service to the activity?
Thanks,
Nathan
There are several ways to achieve this.
1.You can pass a handler object to the service, and have it implement the handler callback
2. You could send a broadcast
3. You could pass a listener object.
variant number 1 is usually best if you know exactly the activity you pass the reference to.
If you want several activities to handle it, better send a broadcast
Common scenario - Activity with a background Service to poll server.
The Service will run periodically via AlarmManager and also perform tasks for the Activity (user hits a button, go fetch something from server).
I'd like to know the best practices here. I think the best design would be the Android LocalService example:
http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
However in the example the Activity has a reference to the activity mBoundService but there is no reverse connection (the Service has no way to call the Activity).
What is the best way for the Service to call the Activity?
Do I use Intents, BroadcastReceivers, Messages? How?
I think the best design would be the Android LocalService example: http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
I wouldn't. Use the loosest possible coupling you can stand. Hence, on average, aim for the command pattern with startService() instead of the binding pattern with bindService(). Notably, binding is a bit of a pain when it comes to dealing with configuration changes (e.g., screen rotations).
What is the best way for the Service to call the Activity? Do I use Intents, BroadcastReceivers, Messages? How?
See Notify activity from service
If you need tight coupling between your activity using bindService(), the way you communicate depends on who is originating the communication.
If the Service is originating (due to say an Alarm that has some new information to share), it would typically send a broadcast.
If the Activity is originating (due to say your example "go fetch something from server"), it could be handled asynchronously using AsyncTask or similar. That is, you could fetch from the server in the AsyncTask.doInBackground(), and post the results back to the activity in AsyncTask.onPostExecute. This scenario be a bit more complicated if the requested operation is expected to take a very long time - in which case I would de-couple it, and send a broadcast back from the Service instead.
As written here
When you want to communicate from service to an Activity or Fragment
which did NOT started the service or to communicate from service to multiple activities/fragments then you can use Event Bus or
Broadcast Intents since they can receive callback for an event in any
activity or fragment wherever they are implemented.If you want to
communicate from service to an activity/fragment which started the
service then you can use Pending Intent or Messenger as they can be
put into an Intent extra and passed to Service.
Pending Intent
We can use createPendingResult() which creates a new PendingIntent
object which you can hand to service to use and to send result data
back to your activity inside onActivityResult(int, int, Intent)
callback.
Event Bus
You can have the service raise events which activities or fragments
can listen for and respond to using Event Bus.
Messenger
Messenger is parcelable ,and can therefore be put into an Intent
extra,so your activity can pass this Messenger to the service.Service
will populate Message object with whatever data needs to be
send.
Broadcast Intents
Service can send a broadcast which can be responded by the activity.
I'm trying to start a Service from my Activity to look out for changes on a web page, it's a private app so I don't bother the battery life...
But I'd like to pass data from my Service to my Activity... I can't seem to find a way to call the Activity from my Service. How can I achieve this?
As Alex indicated, you can bind to the service and pass some sort of listener or callback to the service to use on events.
Or, you can use a broadcast Intent, perhaps using methods like setPackage() on the Intent to limit the scope of the broadcast.
Or, you can use createPendingResult() to create a PendingIntent that you pass as an Intent extra to the service -- the service can then use that PendingIntent to trigger onActivityResult() in your activity.
Or, you can use a ResultReceiver.
Or, you can use a Messenger.
(admittedly, I have not tried those latter two approaches, but I think they will work here)
One more alternative: if your service updates content provider, activity can be notified via ContentObserver. This would be enough if your service downloads some data from server and you simply want to display fresh contents in the activity.
Some ugly ways:
1.) If the activity has not started yet, then use intent and startActivity, but remember intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2.) Otherwise if the activity has started already, you can write your own callback method in the activity and register the method in the service, then direct call the method in the service.
Hope to find some smart way.
I think broadcast also work well, you can write a static inner class for receive broadcast and start activity. But it is also ugly in my opinion.
The ResultReceiver mechanism has been explained in another post :-
Restful API service
However it would not work in all cases. Please refer to my comment on that post. The limited scope broadcast or PendingIntent mechanism seem more suitable.