I have a few applications that connect to a network service in order to call a few messages. As the communication with this network service is planned to change, I was thinking to implement a service that will deal with the communication with the network service, and the applications will just send intents or messages to this service. My idea is to have this service standalone, started after boot up, so it needs to be started service. It will connect to the network service and will wait for commands from the applications. So far, I found that Messenger is nearest to what I need, but I think it can only work as a bound service.
Is there already something I can use for my case?
If not, then am I correct that I would need to:
implement a started service
use HandlerThread to handle the input messages - my preferred way is to use intents, but so far I don't know how to do it
So as pskink pointed out, the way to go is using Messenger.
I used com.example.android.apis.app.MessengerService (from Android SDK samples) as an example of such service.
The service is started on reception of ACTION_BOOT_COMPLETED and (on my device with Android 4.2) when the first client tries to bind to the service, the service's onCreate and onBind are called. The communication occurs by sending Message objects and I have defined an enum with the supported messages listed (so I am not using AIDL directly).
Related
I have never worked with services before, but I looked at many posts and tutorials and I never quite understood how this works.
So what I need is something (like a Service) that runs in the background independently of the apps lifecycle to receive and execute requests asynchronically.
In more detail I want this to be a download queue.
I planned on doing this by having a service started if the user requests a download. If another download is requested while the first isn't finished the service puts it into its queue. The service sends periodical messages so the UI gets updated. The user can also pause or cancel a download (so the activity has to have the ability to send messages to the service).
I know how to do the download stuff and I think I know how to start the Service, but I don't understand how to send messages to the service.
For messages to the Activity I would do something like this:
private void sendUpdateMessage(Bundle data) {
Intent intent = new Intent("DownloadUpdate");
intent.putExtra("data", data);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
For messages to the Service I guess there has to be some sort of binding (which I don't understand well). I found this Communication between Activity and Service or this https://developer.android.com/reference/android/app/Service.html#remote-messenger-service-sample, but this seems very complicated and I sadly do not understand it.
It would be nice if anyone had a simple explenation for how to communicate between Activity and Service.
(Again, I know there are post on this topic on Stackoverflow, but for some reason I do not understand how to do it properly)
I found a very helpful page with great examples:
Effective communication between Service and Activity
There are three possible ways:
Broadcasts and BroadcastReceivers
The simplest solution uses Broadcasts and BroadcastReceivers. However, this method has the following disadvantages:
The message sender does not know who will receive the data (it broadcasts the message).
Broadcasts consume a lot of bandwidth and are not suited for high traffic.
Binder
For Activities and Services used in one application the “Binder” solution is recommended. After binding with the service, the Binder will allow the activity (or other class bound to the service) to call any public method of the service.
Messenger
The recommended method of communication between Activities and Services for different applications’ Inter-Process Communication (IPC) is by using Messengers. In this case, the service defines a handler for different incoming messages. This handler is then used in Messenger for transferring data via messages.
To get bi-directional communication, the activity also has to register a Messenger and Handler. This Messenger is passed to the service in one of messages. Without this the service wouldn’t know to who it should respond.
For my project I chose the last one.
I'm developing an app that communicates with an embedded device via BLE (Bluetooth Low Energy). The app allows the user to send commands via an activity. Meanwhile the app needs to send location data in the background. The location data must be sent constantly, even if the activity is closed and opened multiple times over the day.
I cannot separate the continues location updates from the command requests. Because all BLE transmissions must be synchronized by one queue to prevent simultaneous transmissions which would cause package loss.
After reading the official guide (https://developer.android.com/guide/components/services#Basics), my first idea was to use a foreground service because the service must not be terminated when the activity is closed. That works fine for sending the location data. However, for sending the commands I have to communicate with the service after it has been started. I read that it's not recommended to use both startService() and bindService() but instead to decide for one way. As far as I understood a bound service can be destroyed when the referencing context (the activity in my case) is destroyed. So I guess binding to the service is not an option for me.
Another approach to talk to a started service is to send commands using broadcasts and receiving them in the service (sending commands from Activity to Service in android).
But I think there must be a better solution that I miss. What came to my mind is simply calling startService() every time I want to send a Bluetooth command. I guess that would work. But is it good practice? Effectively, I would call startService() dozens of times during a typical use case before calling stopService().
Oh wow... I read through the whole guide but overlooked this sentence in the method documentation:
startService()
Every call to this method will result in a corresponding call to the target service's onStartCommand(Intent, int, int) method, with the intent given here. This provides a convenient way to submit jobs to a service without having to bind and call on to its interface.
https://developer.android.com/reference/android/content/Context#startService(android.content.Intent)
Hope it helps in case that someone stumbles across it..
You don't have to bind the service to anything. It's enough to start it and then make sure you call startForeground on it. That will keep your process running without being killed by the system. You don't have to place your BLE code in the service class but can have it wherever you want.
I'am developing something like a Push Notification SDK, when users integrate the SDK to their application, the SDK create a Service and receive Notifications through a TCP connection.
Now here is the question: Assume that many applications will use the SDK on the some android device, all of the application need to receive their own notifications, if we create TCP connection in each Service, it will cost too much resources and battery power, so I want to use a main Service(maybe the first Service start by SDK) to set up TCP connection, the other Services reuse the connection by some kind of IPC. But I don't known what kind of techniques is best to use.
Is there anyone who can give some advice?
thanks~
Finally I solved the problem this way:
Make a public Service(android:export="true") to set up TCP connection to the server, when the APP starts, first check if the public Service exists, if not, call startService(). Then call bindService() in the APP. To communication with the public Service, use a Messenger class:
http://developer.android.com/guide/components/bound-services.html#Messenger
I have a class that starts a Bluetooth reading thread and another that receives/decodes what's read from that port and produces some output logs depending on the information read.
In my design, those 2 components form a service for my application (multiple activities) from where I would like to start/stop getting the output logs on a continuous basis (typical frequency of 2-3 logs per second).
My questions:
1) Should I derive from Service or IntentService. The doc says about IntentService: "This is the best option if you don't require that your service handle multiple requests simultaneously". This may be my case since the main activity will start/stop the service...
2) What would be the appropriate way to catch the service events? Does the BroadcastReceiver is appropriate for this type of communication?
3) I may need to occasionally send some stuff to the Bluetooth port. So, I'll have to pass information from my application to the service. Does the PendingIntent should be used for that?
Thank you!
Should I derive from Service or IntentService
IntentService is designed for discrete tasks, not stuff that would run indefinitely until the user manually stops it. I would use Service.
What would be the appropriate way to catch the service events? Does the BroadcastReceiver is appropriate for this type of communication?
That is certainly one approach. You might use the LocalBroadcastManager from the Android Support package to reduce overhead and keep everything private to your app. Have your activities register a receiver in onResume() and remove it in onPause(). The foreground activity will then be notified of events.
I may need to occasionally send some stuff to the Bluetooth port. So, I'll have to pass information from my application to the service. Does the PendingIntent should be used for that?
No, I would have the activity simply send a command to the service via startService(), with the data to be passed included in extras on the Intent. If you have data that cannot be packaged as extras, you may need to consider binding to the service, so you can get a richer API, though this makes configuration changes more annoying.
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)