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));
Related
I have made an Intent service and that is working as expected, And I know that intent service does it works and stop itself after its working , so there is not need to stop it. I have made my intent service as you can google it , but I have launched it in a separate process. the code goes like this in xml
android:process=":MYPROCESS"
so in my app , I launch the intent service in the following way on button click
Intent intent = new Intent(DownloadService.ALARM_SERVICE);
intent.setClass(this,DownloadService.class);
/* Send optional extras to Download IntentService */
intent.putExtra("url", "http://myurl.com");
intent.putExtra("receiver", mReceiver);
intent.putExtra("requestId", 101);
startService(intent);
this is just to give you idea How I am starting it , its normal.
What is Happening
I have made a button to stop a service , my this service is downloading something. so What I did , I killed the process , but that start the service again .
As I wanted my service to start again when it is killed by the system or when app is killed so I have set intent to redeliver like following
setIntentRedelivery(true);
So it is amazing situation :so simplifying my question as following
I want to stop service to not to start again , but when it is killed by system or it is killed when user removes app from recent apps , then service should start again (which is going good).
Please tell me how can I achieve this .
In order to do this, you'd have to further modify your custom DownloadService derived from IntentService. The IntentService base class is automatically starting a thread and servicing your Intent there, shutting down the thread and the service when it has no more work to do. You have 2 choices you could use to stop the service:
Implement onStop() in your service and have it set an internal (synchronized) shutdown boolean. In your onHandleIntent() you could check for this flag and prematurely exit the handler and possibly call stopSelf() to prematurely exit.
Alternatively, you could add your own onBind() implementation and have your Activity bind with the service. Then expose a binder method (see docs on AIDL) to be called by your Activity when you want to exit the service. Like above, your service's onHandleIntent() would need to watch for this early-exit type flag and cause itself to stop prematurely.
Note that in either case the service's process will most likely not get killed and this is normal. Android keeps processes cached and in a ready-to-go state so it is very responsive when new requests to start its components arrive. This does not mean your service is "running". It just means the process which will host the service is already created and ready to go.
The Situation:
Note: This is a followup of a previous question that takes care of how to setup the handler/message communication between activity/service. See: link
Activity connects to a started Service using binding. Activity gets a local binder with a reference to a service Handler back. Activity and Service exchange Message objects through eachothers Handlers. When user is done with App, user signals Service to quit the started Service (shutdown the service). Within the service (=mainThread) another thread is running, the serviceThread. The serviceThread is capable of running more subthreads, fully controlled by the serviceThread. Communication is handled between activity and the serviceThread, not through the mainThread of the service!!!
The Problem:
How do I gracefully shutdown the Service when inside the Service several threads are running endlessly (until I signal a message saying: "pack your backs, go home!", aka: EXIT_SERVICE.
Solution candidates:
Scenario 1: from the activity side, send a EXIT_SERVICE message to the serviceThread that is running within the service (not the mainThread!). When all subthreads of serviceThread have been cleanup/stopped send a message back to the activity indicating that it is now safe to call the stopService(Intent) method which actually stops the service. The activity can now call finish() and the App is exited gracefully.
Scenario 2: from the activity side, send a EXIT_SERVICE message to the serviceThread which will cleanup all subthreads. After that is done the serviceThread sends a message to the activity that the service is to be shutted down completely and after that message is sent, sends a message to the mainThread handler of the service to actually shutdown the service. The service receives the shutdown-message and cleans up varialbles and calls stopSelf(int).
The service is stopped and the activity knows that it can stop too, WITHOUT calling stopService(Intent)! The App is exited gracefully.
Scenario 3: from the activity side, call the stopService(Intent) method, which will deliver the Intent to the service to stop the service. In the service this Intent is intercepted (I don't know if this is possible and how to do that yet... but assuming this can be done) before the actual service code that stops the service is executed. Before the service actually stops, other code is executed first which cleans up the threads by sending a EXIT_SERVICE message to the serviceThread. After the serviceThread has cleaned up, it sends a message back to the mainThread (the service itself) and the code continues to execute the normal code that was normally executed when the Intent to stop the service wasn't intercepted. The App is exited gracefully.
So, I have three options on how to gracefully stop the Service. The problem is which scenario is the "best" (less error prone, quickest in shutting down, easiest to implement). For example: what happens when the activity is destroyed because the user switched portrait/landscape mode right at the moment the "stop service" message or Intent was sent?
I think scenario 3 is a nice solution, because it doesn't need a lot of extra coding on the activiy side, only stopService(Intent) and finish(). The service can also be in the process of stopping while the GUI is already gone. Only thing is how to intercept the stop Intent and act upon that signal.
Please share your thoughts....
I have a chat client activity which continously filtes incoming packets using a while(true) loop. On the basis of message contained in the packets, I need to start and stop a service. The service performs an intensive long running task. Since, the service starts in the same thread of the caller Activity, I cannot start the service and also continue to filter packets, otherwise it shows an ANR dialog.
How can I keep both the activity and the service doing their tasks and also the activity to be able to later inform/stop the service?
I started the service in a new thread but that still gave an ANR.
Edit: Using AsyncTask and BroadcastReceiver works only if packet-filtering is stopped at the time of calling the service. Simultaneously doing both gives ANR.
Use a Broadcast Receiver and register with a particular intent-filter. Broadcast an intent whenever you need to do any processing based on the content of your chat messages. Within the receiver you could take whatever action you need to.
I have an IntentService which is started from a BroadcastReceiver with startService(service). When I get new informations in the BroadcastReceiver the new infos are pushed through an intent with startService(service) again to the IntentService but then the service is restarted. Can I prevent this? I want to push new informations to the IntentService without restating it.
Intent service are intended to be started with an intent, execute their job and finish. They are more like an asynctask from this point of view. This is the reason why your intentservice is restarting.
onHandleIntent should do some work and finish. You could do some tricks to make it blocking but that would go against the nature of intent services.
What you should do is to have a classic Service. If you are getting ANR errors, you should perform all the time intensive operations inside a thread or an asynctask hosted inside the service itself.
I assume you need to share some state for handling subsequent Intents inside your Service. I see two solutions:
Use IntentService and save and restore this state inside onHandleIntent.
Use started Service, and hold this state as a field inside your Service class. To prevent ANRs, process the Intents outside of UI thread, just like the IntentService does. To keep the Service running, just remove the stopSelf call from handleMessage.
If you can get away with restoring and saving state for each processed Intent, the first solution is safer, because your Service may be killed by the OS in case of running out of memory.
Hi stackoverflow community. This is my first time asking a question so please forgive me if I have some errors in this post
I am trying to communicate an Activity with an Intent Service using the Result Receiver pattern explained in this post and discussed here in stackoverflow. Eveything is working OK in a sample app but I am not sure if this pattern is effective when Activity goes to background or gets killed by Android OS.
Basically, what I want to achieve is the following app behavior:
Activity: Starts IntentService to do some work. Passes ResultReceiver to receive progress updates
IntentService: Starts working, get Activity's ResultReceiver.
IntentService: Work is completed in 10%, notifies Activity by sending message to Result Receiver
Activity: Receives message in onReceiveResult
IntentService: Work is completed in 40%, notifies Activity by sending message to Result Receiver
Activity: Receives message in onReceiveResult
At this point, user goes to another app. Activity goes to background dettaching first the Result Receiver. Android OS could also have destroyed this Activity because of an incomming call
Intent Service: Work complete. Tries to notify Activity but no Result Receiver available. Saves message for later redelivery to Activity.
At this point, user gets back to the app. Activity goes to foreground, attaches Result Receiver and gets pending message from Intent Service that notifies that work is done.
So, my question is how to handle pending notifications of an IntentService to the Activity using the Result Receiver pattern?
Thank you very much.