How to communicate back to a service from a broadcast receiver? - android

Hope someone can help me out here. I will try to be concise!
I have a widget which starts a service. The service registers two broadcast receivers. I would like to send back intents from the receivers to the service, so that the service can react.
I believe I read somewhere that 'starting' the service multiple times works, e.g. do the following in the receivers:
serviceIntent.setAction("me.SERVICE");
intent.putExtra("me.SERVICE", somedata);
context.startService(serviceIntent);
I remember reading (on some blog) that this won't start a new service, but will simply pass the intent to the already running service. Is this correct? Is it a bad way of doing it? Is there a better way?
Thanks very much!
Jack

Yes, I've used that approach in a pre-2.0 app.

I accomplished this using a singleton. I set a private variable (pointing to 'this') in the service's onCreate, and then used a static method called getInstance() which would return it. So later on, I simply call MyService.getInstance() to get hold of the service.

Related

Android Service, do we have to use startService or BindService?

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

Android "speak" with a service

I have an android class that extends a service. I can start the service with startService(intent) and stop it with stopService(intent).
But what if I need send some information to the service after I've started it?
In my case for example I need to call some methods. How can I do it?
I thought is a simple thing but I looked for it on the web without find an easy way. Do I need to use a remote service or there is something easier?
Thank in advance
or just use startService() and send an Intent with some data along. No need to be complex.
Use Broadcasts and Broadcast Receivers.
To call methods in the Service from an Activity you need to bind the Service in an Activity. Check out Bound services from the official developers guide.
If you don't want to use an Activity then resort to Nieks suggestion with Broadcasts and Broadcast Receivers.
But then again if you need to call methods in you service on a regular basis, maybe it shouldn't be a service.
Convert your service over to an IntentService and it will handel the service life cycle for you.
Each startService(intent) will represent a new "job" for the service.
If you need notification of progress or completion Use Broadcasts and Broadcast Receivers.

Start Again Already Running Service?

I have a broadcast receiver listening called PACKAGE_ADDED and an other broadcast receiver listening called BOOT_COMPLETED. The bootcompleted broadcast receiver starts my service.When the new app is installed, I want to send a message to my service .The first solution that came to my mind was to start the service again with
intent.setAction("NEW_APP_INSTALLED");
startService(intent);
without stopping the service and check the intent.getAction() value in theservice.onStart() method. If the result is NEW_APP_INSTALLED, then call newAppInstalled().I don't think this is an elegant solution.
Is starting the service repeatedly a problem? And what happens when my activity binds to it via ipc(aidl) while fetching data and the new app installed broadcast receiver starts it again? Lastly what is the best way to solve my problem?
Is starting the service again and again problem?
Lastly what is the best way to solve my problem?
It is perfectly fine for you to call startService on an already running service. And you can either do it the way you suggested or have two different services (one for boot, one for new_app) or you can register a BroadcastReceiver in the service after it's started, but that wouldn't be effective because then if you try to send a message to it and it's not running already, it won't get the message.. I prefer one service as you suggested and using startService.
And what happens when my activity bind it via ipc (AIDL) fetching data
and new app installed broadcast receiver starts it again?
Well, I don't know anything about AIDL, really. This might help. That page does state "Most applications should not use AIDL to create a bound service". This is because it makes multi-threading needed and makes it more complicated.
Please let me know if I failed to answer to your satisfaction - though I can't really elaborate on AIDL specifically because I don't know anything about it.

Service, Broadcast Receiver Instead of startActivityForResult?

I'm developing a service and I've been following an example that unfortunately uses an Activity to get its work done. The example uses startActivityForResult() to get values after doing something. I'm wondering do I just use BroadcastReceiver to accomplish the same thing? sendBroadcast(intent) and then capture the broadcast to do whatever?
Yes, for me is the best solution, but you can bind the service to the activity if you want another solution.

Notify activity from service

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.

Categories

Resources