Right now the main Activity (Act. A) starts a Service which holds the Bluetooth Connection.
(It binds the Service)
The Service is a modified version of BluetoothChatService (Android BluetoothChat Sample)...
... modified with an added Messenger and Handler in accordance with MessengerService (Android Remote Messenger Sample)
Activity A makes sure that the Bluetooth is connected to an external device, and later starts another activity (Act. B).
The problem is to get the Service to keep running and serve the Bluetooth Connection to the new activity smoothly. I don't know how to:
Make sure that the Service is not restarted or reinstanced, when it switches from activity A to B
Make sure that the messenging functionality works as desired (from the currently active activity)
Do I need to rebind the Service to the new activity, and how do I assure that the BT connection is not lost (due to other instance of Service)?
Or do i need to pass along the Messenger object to the new activity to communicate with the alread instantiated Service. If so, how do I do that best?
Very thankful for answers!
Make the service "sticky" so that it will continue to run. And create a base Activity class for your 2 activities. The base Activity class can handle all the common functionality of binding with the service and providing the proper communication. I would definitely recommend unbinding your service when the activities pause and re binding them in the activities when they resume. But this can be done once in the common base class activity.
Binding to the service should only start it if it is not already running and if you bind/unbind in Resume/Pause you should have only one active connection to the service at any given time.
You either subclass Application and store information in there (see here), or you could make your "service" a singleton, so it has a static member of its own type that you initialize only if it's null.
This is an old question, but I ran across this situation today and came up with a solution that works based on the other responses. Since I couldn't find a working implementation, I will post it up for others who may be curious. I created a "sticky service" and then a ServiceManager class that is responsible for managing the life-cycle and binding for the Service. Then I put the ServiceManager class into a sub-class of Application so the Activities can access it as a scoped global. It works well. Source is available on GitHub.
Related
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.
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
It's my understanding that Android services are supposed to be singletons - no more than one class instance running at a time. So you're supposed to start them via intents, as opposed to
MyService mse = new MyService();
However, in Google's in-app billing sample, that's exactly what they do in Dungeons.java, line 235. So it's obviously legal.
I'm wondering, if I start a service like this, will the framework later recognize that it's running? In other words, if I try to call startService() on the same service later on, will the framework recognize that an instance of the service already exists and dispatch startService() calls to it?
I don't know what example you are referring to. But you absolutely positively cannot instantiate an Android component (Activity, BroadcastReceiver, Service, Provider) yourself using the new keyword. These components can only be instantiated by the Android framework, as the framework needs to set up the Context of the component.
There is (unfortunately) nothing stopping you from writing Service s = new MyService();, but it will do you no good. Android will never call any of the lifecycle mathods on this Service and any calls you make to methods of the Service will probably fail spectacularly because the instance has no Context.
If you instantiate the service directly instead of using intents that guarantees the service will run within your Activities process. If that activity should be killed then down goes the service too. Is that a bad practice? Well it depends on what you wanted. If you need that service to live through potential shutdowns of activities then yes that's a bad thing to do. If you don't care or your app can tolerate those shutdowns then it's ok. However, I'd argue if you need a background job running that can be stopped when your Activity stops then you need to use AsyncTask and NOT a service.
I have a service running on my android application, the service is a socket class that has to run through the whole application, i create it when my first activity loads.
How can i get an instance of this socket class so that i can call a function in this class.
For example
//how can i get an instance of the running service?
MyService s = getService();
s.writeDataToServer("hello");
There's two ways you can go about doing this depending on if you want to keep the socket open when the user isn't actively using your UI.
The first is a LocalService it's the same as a regular Service except it runs in the same process as your Activitys UI thread and therefore you can gain a direct reference to it. This is a much lighter method of creating and using a Service than using AIDL. I only recommend using AIDL if you wish to create an out-of-process service that needs to be accessed either by different processes in your application or in different applications. This is most likely not what you need. The LocalService method will allow you to keep the service running in the background and in turn keep the socket open even when the UI isn't in use.
If you don't have the requirement of keeping the socket open and only wish to have access to it from multiple Activitys then you can extend the Application class and register it in your manifest. It allows you to manage global application state. You can put the socket creation and management functions into that class and then provide methods for your various Activitys to gain access to it. The Application class dies when the process dies so it is not suitable for keeping a socket open for long periods of time or during times when the user is not actively using your application.
There is the built in Activity#getApplication() method that helps with this process. You can specify your custom Application class in the AndroidManifest.xml via the android:name attribute.
The Android Interface Definition Language (AIDL) is the correct way to connect to a service.
Check out http://developer.android.com/guide/developing/tools/aidl.html
For information how to communicate with a service.
Check out Intents and the bindService method.
I'm working on establishing a two-way communication between an Activity and a Service which runs in a different process.
Querying the process from the Activity is no big deal. But I want the process to notify the Activity on events. The idea behind it is this: the service runs independently from the actual app. It queries a webserver periodically. If a new task is found on the webserver the process should notify the activity.
I found this thread over at AndDev.org but it doesn't seem to work for me. I've been messing around with BroadcastReceiver. I've implemented an interface which should notify the Activity but the problem is that the listener is always null since the Broadcast from the process is done via Intent, hence the class that extends BroadcastReceiver will be newly instantiated.
How can I establish a 2-way communication? This has to be possible.
Thanks for any help,
steff
Either use BroadcastReceiver or have the Activity register a callback or listener object that the Service calls on key events. The links above are to book example projects demonstrating each of those techniques.
I think you should have the BroadcastReceiver start your activity again with the result in the Intent.
Or you could use AIDL about AIDL. The samples also have an (multiple?) example how to use AIDL and services. But AIDL might be to much of a hassle for your purpose.
You have to use BroadcastReceiver to receive intents, and when you want to communicate simply make an Intent with appropriate values.
This way you should be able to make a 2-way communication between any component.