using synchronous and async communication between Activity and Service on Android - android

I am currently writing an app, which consists of a service and an activity. The service is running in the background, doing some live audio processing. If the user want to get some information about the running service or want to change the settings of the service, the activity gets started and bind to the service.
Currently i am using the asynchronous messenger system to communicate between the service and the activity. For example, the service can send some results to the activity through a message and the activity can handle this message and show the results. This works fine, but it is stressful to write the messaging stuff for each communication. And it is not always needed. Sometimes i only want to ask the service, if a flag is set or not. If i do this asynchronous, i have to send a message to the service which asks for the value of the flag and the service has then to send a message back to the activity to answer the request.
So i want to have some getter and setter which can synchronously access the service. This can be done by using a binder, which works too.
The problem is, that i sometimes need synchronous communication to get the value of flags etc. and sometimes i need asynchronous communication to push the results from the service to the activity. So what i need is a binder and a messenger. But i dont know how this can be done, because the service can only return one object from the onBind() method, either a binder object or a messenger object.
Do you have any suggestions how this can be done or some other approach to realise asynchronous and synchronous communication between an activity and a service?
Thanks in advance!
Tobias

If you are already binding to the service, your activity can supply a listener object to the service, which the service will then call when events occur.
You just need to make sure that you unregister that listener object before unbinding from the service, and do both before the activity is destroyed, so your service does not wind up with a strong reference to a defunct activity.

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 activity - remote service aidl two way connection

I have two problems:
I know that for connection activity and remote-service I have to use AIDL.
I tried this and it's work but I can find only one way connections example. In simple words - reading something from service (by activity). But I need solve for sending some data to activity (by or from service). It's so important because the service have to send some information to activity immediatly after some its events (obtain data from the net).
Is it way to bring to front again closed application (activity) from the remote service?
Any suggestions would be greatly appreciated.
Regards
Artik
It's so important because the service have to send some information to activity immediatly after some its events (obtain data from the net).
You can use AIDL for two-way communication. You would need to expose not only the service interface, but a callback interface, via AIDL, with the client having the .Stub of the callback and supplying an instance of it in a parameter to a method on the service interface. This gets a bit complex -- here are a pair of sample apps from my book that demonstrate the technique:
Service
Client
Is it way to bring to front again closed application (activity) from the remote service?
Your service can call startActivity(), but generally that is a bad idea. The user may be in the middle of doing something else, when all of a sudden your activity pops into the foreground. Occasionally, the user may deem your activity to be more important, but not always. Consider using a Notification instead, to let the user know that there is something in your app that needs the user's attention.
First, create a private resultreceiver variable in your service. Then create a method to set this resultreceiver via a connected activity. Then use AIDL to pass on a resultreceiver to the running service from the activity via the method you just made. Then in the service use resultreceiver.send if the resultreceiver is not null.
A few examples to get you started
http://lalit3686.blogspot.com/2012/06/how-to-update-activity-from-service.html?m=1
http://chrisrisner.com/31-Days-of-Android--Day-28–Intents-Part-3--Service-Intents

missing broadcast intents when the device is rotated?

We have a network client application, and we are trying to validate our approach to processing responses from the server in conjunction with device rotation. essentially, we do this,
activity registers a receiver for network responses
activity initiates a network operation by starting an intent service
service responds by broadcasting an intent it's finished
our (perceived) problem is that when the device is rotated, the activity is destroyed / recreated. during the time between when the activity's receiver is unregistered in onPause() and when it's re-registered in onResume(), we may have missed the intent that is broadcast by the service.
is this a real problem?
if so, we have hypothesized the following solution,
first, don't use intents to communicate between activity and service
create two blocking queues: network requests and responses in say the application class
service starts a thread that take()'s from the request queue
activity starts a thread that take()'s from the response queue
activity offer()'s to the request queue when it wants to start a network operation
service offer()'s to the response queue when post the result of a network operation
Yes this can happen in rare circumstances but it will happens for sure if the user receives a call. Again your activity will be paused and then resumed, If the user talks for a long time your activity will loose a bunch of broadcasts from the service.
My advice is that you must not use broadcasts to do two way communications between application's in situations that a response from a component such as a service, requires immediate attention. What mechanism you will use is depending from the situation. In my latest project I am using a service in order to update an app-widget, in this scenario I am using static code in the service in order to do some queries or to request some actions.
Your thinking sounds good but it may hides a complex implementation, If I was in your position I would consider to use the built in service mechanism called Bound Services. I have not used it so far but it seems that it is covering your needs.
EDIT
So based on the bound services concept I propose the following flow:
Activity starts, a so called, sticky service.
Service registers the receiver for network responces.
Service maintains an Ibinder object with the needed information based on the network responces.
Activity bounds to the service whenever it wants and retrieve the Ibinder object with the info and does the required actions.
When it's time to end the application, Activity stops the service and finishes itself.
Hope this helps...

starting a service and returning data

today I was learning about Intents and binding an activity to service, I found it quite easy and great way to transfer data from the service to the activity. I wanted to test out an activity that would start a service, this service would call on a webpage to get some data. I binded the activity to the service so that the activity could call on the service method and then toast the results. In the service method I call on a webpage and return the data. When I tested it I was getting a null pointer exception, im pretty sure I am not doing it the right way , does anyone have any suggestions how to implement this properly.
You're dealing with some fairly solid thread synchronization issues here. You would be far better served registering some kind of listener paradigm such that you register your Activity as a listener to the data that your Service is producing. As it currently stands, there's no synchronization between your Service and Activity at all, resulting in the Activity trying to fetch the results from the Service before they're ready. There are a ton of resources out there discussing the listener pattern or Observer pattern.
I should note, I have no idea whether your Service is actually pulling things down correctly. I'm just looking at your communication between the two.
When returning results from service , its better to implement ResultReceiver interface in you activity and pass receiver object to the service via putExtra. In your service fetch the receiver object and call receiver.send() function to send anything in Bundle. [I have tested this pattern in IntentService at least].
Edit:check out this post for complete implementation.

android : communication between service running in background and activity

I have a service running in the background. Based on some condition it has to start some activity. Activity has to send back the response.
I did google search and found out we have to use Notification mechanism. But I am not clear how to send the response back from activity to the service running.
Also service is collecting sensor data(acclerometer, gps). So should activity be started in separate thread so that collecting sensor data is not affected.
Please clarify.
Activity would be started in main UI thread, instead, your long-running service should run in and manage its own thread, since according to the document, service is also created in main thread.
Basically the best way to communicate is to use Intent. This allows loose couple of sender/receiver (i.e., activity/service in your case). Intent is a large topic in terms of android, and yet it is one of the most fundamental one, I think you should look for tutorials online about it.
If your activity is opened and return the result after completing the task of Activity then you can use startActivityForResult and then return the result.
Using of notification is simple, just create a interface class, and implement the class in your service. When you need to send data back to service, you can just call the appropriate method with data.

Categories

Resources