I am starting a foreground service from a fragment which gets destroyed after call to startService(), which is a reason I can't use ResultReceiver or Messanger. So the option remains PendingIntent. How can I communicate between foreground service(hosted in different process) from any activity/fragment using PendingIntent?
You have two separate issues:
How do you get data from the service process to the UI process?
How do you get the data from whatever you did for #1 to whatever portion of the UI needs that data?
There are any number of solutions for #1: PendingIntent, ResultReceiver, Messenger, AIDL-defined callback for a bound service connection, etc. #2 then mostly is a matter of using an event bus or something similar to alert all relevant Java objects about the new data.
So, for example, here is an off-the-cuff recipe for using a PendingIntent for this:
Implement a BroadcastReceiver or Service in your activity process, registered in the manifest, but with no <intent-filter>
As part of calling startService(), create a PendingIntent using its getBroadcast() or getService() factory method, with an Intent that identifies your BroadcastReceiver or Service, and put that PendingIntent in an extra for the Intent used with startService()
Your service in the other process, when it has data to deliver to the activity process, calls send() on the PendingIntent, including an Intent with data to fill into the broadcast or service request
Your BroadcastReceiver or Service from step #1 takes the Intent delivered to it and uses an event bus to let the rest of your activity process know about whatever happened, also handling the case where nothing in the activity process is registered for the event (e.g., raise a Notification if all activities were destroyed)
Related
I have an IntentSerivce that runs in the background sometimes and it can be quite a long running process in certain instances. I give an option for the user to quit the application which basically just stops and polling and ignores any GCM push notifications. But if a push notification came in and the IntentService is taking a while to finish doing what it has to (gets information from a server and sends a notification to the user if needed, like a new message arrived or something).
Here is the problem, if the user elects to "Quit" the app while the intentservice is still running they will still get the notification which I do not want. I know that there is the stopSelf() method for the service but I need to stop it in an activity when I know the user "Quit" the application via a menu button. Sending another intent to the service does not work since the intents get queued up and calling context.stopService(intent); in my activity does not work either so how else can I stop it?
Are you passing a new Intent into stopService(Intent) or the original one used in startService(Intent). Passing the original Intent should stop the service.
Failing that you could use a Handler to pass the service a Message. Have the IntentService implement the Handler.Callback interface and create a new Handler(Handler.Callback) in your Activity, passing your IntentService as callback. Then implement the onHandleMessage() in your IntentService to call stopSelf() and have your Activity pass a message to it when you want it to stop.
Below code is perfectly working fine for me to stop IntentService from Activity:
stopService(new Intent(getApplicationContext(), MyIntentService.class));
I read some similar questions (for example at this link), but the problem I'm asking is a bit different. In fact, in my case the service is started manually by the startService method, then as a consequence it can not be started using the bindService method.
Suppose we have a package that contains the MainService service and MainServiceActivity activity. In the file "AndroidManifest.xml" this activity is declared with action MAIN and category LAUNCHER. This activity is used to configure the service via the SharedPreferences and start the service by invoking startService method. In other words, typically the user launches the MainServiceActivity and configures/starts the MainService.
Now consider another activity (Let's call it SecondActivity) that is part of another package. Depending on the configuration, the service starts this activity using the startActivity method, so this other activity is running on a separate process than the MainService. As soon as the activity is running, it should inform the service.
At this point, a communication request/reply begins between the MainService and the SecondActivity: the service sends a request and the activity sends a reply.
The communication via messaging might fit, but the MainService is started through startService method, so the bindService method can not be invoked by activities that want to bind to the service.
Then I had an idea that makes use of an additional service (Let's call it UtilityService), which is part of the same package of MainService: the UtilityService could be started using the bindService method. As a consequence:
as soon as the MainService is running, it might perform the bind to the UtilityService;
when the MainService launches an external activity (for example the above SecondActivity), this activity bind to the UtilityService.
In this way, both the MainService and the SecondActivity are connected to the UtilityService, where the latter acts as an intermediary for communication.
Are there alternatives to this idea?
In fact, in my case the service is started manually by the startService method, then as a consequence it can not be started using the bindService method.
You can both bind and start a service, if you wish. It's a bit unusual, but it can be done.
Are there alternatives to this idea?
Binding has nothing in particular to do with services being able to communicate with activities. Using some sort of callback or listener object via binding is a possibility, but it is far from the only one.
You can:
Have the service send a broadcast Intent, to be picked up by the activity
Have the activity send a PendingIntent (e.g., via createPendingResult()) to the service in an Intent extra on the command sent via startService(), to be used by the service to send information back to the activity (or wherever the activity wants it to go, such as a broadcast)
Have the activity pass a Messenger tied to its Handler to the service in an Intent extra on the command sent via startService(), to be used by the service to send information back to the activity
All of those work perfectly well between processes, as well as within a process.
You can use Android Interface Definition Language (AIDL).
You can find an easy to use guide here
I am trying to develop an app where it locks down the Activity and starts a service which will set an AlarmManager to setRepeating() trigger to another Service which will send a SMS containing the phone's location.
I have achieved the periodic sending of the SMS. However, I now want to cancel the AlarmManager when I finish() the lockdown activity. Please help me as I cant seem to understand the approach to address this.
Program flow:
Lockscreen (Activity trigger Service) --> AlarmManager (in Service class) --> Coordinate (Another Service that send sms)
Call cancel() on AlarmManager with an equivalent PendingIntent to the one you used to register the alarm in the first place. By "equivalent" I mean that it is the same type of PendingIntent (activity, service, broadcast) and wraps an Intent that is the same on all routing elements (component, data, MIME type, categories).
So i have a class that listens to incoming calls, i want to make a service to all my app to receive calls even when i'm not in the application's UI.
How to trigger this class(broadcast receiver). I used "sendBroadcast" and have a FC.
sendBroadcast(new Intent(context, IncomingCallReceiver.class));
Thank you for your help.
In your case I would use the following approach:
Create Service and start it from your Activity (you mentioned that you have several applications, so starting first of them may also start the Service).
Make sure that Service does not work forever, so stop the service when you do not need it any more (last of your applications is finished). Service may terminate self even without Activity by calling stopSelf(). Please note that also System may terminate your Service and prevent it from working forever.
Make private class within Service that extends BroadcastReceiver and register it for the Intents you want to monitor using Service function registerReceiver().
Once you receive wanted Intent, you can call some Service function from within BroadcastReceiver onReceive(). For example, you may sendBroadcast() using some custom Intent that is recognized by your applications.
When Service is stopped make sure that you un-register the BroadcastReceiver extension using Service function unregisterReceiver().
UPDATE:
Service building guidelines
SDK example that illustrates BroadcastReceiver extension usage within Activity. All important related to register/unregister is the same if you do that within Service: android-sdk-windows\samples\android-8\Home\src\com\example\android\home\Home.java
Start Activity from Service
Handle the case of Activity already running in the background
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.