control a service from an activity - android

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.

Related

LocationManager and Networking in a Service

I'm working on this project where I need Location updates plus data uploads even when the main Application is not in the foreground. I'm thinking of placing all location and networking functions in a Service (XService, for argument's sake) and communicate between the Activity (Main) and XService using broadcasts within the same process (no access for other apps).
I have not yet written the code, but the work flow goes something like:
1. Main -- Start. In onCreate, start a new Thread, and on it
instantiate and bind XService. 2. Main -- Login screen. Get data,
package it in an Intent and broadcast to XService. 3. XService --
Receive broadcast, unpack intent. Setup socket and data streams. Setup
LocationManager for updates. Broadcast to Main that the network is
ready. Upload data every time LocationManager updates.
4. Main -- Upon receiving the network-ready broadcast, prepare Intent for initialization and broadcast. 5. XService -- Receive
initialization-request broadcast, unpack, perform network task,
broadcast response. 6. Repeat ad nauseam as per user
interaction and any timed updates. x. Main -- On logout,
broadcast to XService. x+1. XService -- Send logout info to
server, close sockets, broadcast to Main that it is exiting
gracefully, then stopSelf(). x+2 Main -- Complete logout
procedure.
My main question is -- is this the right way of going about it?
Another question is: What happens when XService broadcasts a Location update to Main, but Main is stopped (i.e. not running in foreground)? I assume that since the BroadcastReceiver on Main is not instantiated due to Main being in a stopped state, the broadcast essentially does nothing. How does this unreceived broadcast impact (or not, as the case may be) XService or the process / device in general?
That makes sense. My suggestion is starting the service on the main thread, then forming your new thread within the Service class. This would package the Service nicely so that you don't have to spawn a thread to use it, you can just call it.
If Main is stopped and the Broadcast sends a message, it's a lost message. You want to avoid those by registering the receiver at OnStart and unregistering at OnStop. You can save any pertinent information that the Activity may need to know in the Service itself.
An alternative to the Broadcast Receiver is the Messenger class. (http://developer.android.com/reference/android/os/Messenger.html)

How to gracefully shutdown android service with threads running in the service

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....

Sending broadcast from the service to killed activity

i am working on my first android application and what it does is that it has an activity which after signing in starts a service that pings user location to the server after a certain time period or whenever user location changes. Now for the communication from the service to the activity I am using BroadcastReceiver.
The service after logging the location to the server broadcasts a message which my activity receives and update the UI accordingly. Now everything is good up till this point but when I delete my activity from the background while my service is still running in the background what happens is that whenever the service logs the location on the server and broadcasts the message it crashes and a message is shown on the screen saying your application has been stopped.
I think that the android broadcast system is expecting my activity to be alive to receive the broadcast and when it doesn't find it then it crashes the service.
What I want is that if my activity is around it will receive the broadcast but if it is not then the broadcast should be ignored. It should not crash my service.
I am following proper steps by registering for the service in onResume() and unregistering in onPause(). Moreover I am registering the service dynamically rather than in the manifest.
you should use bindService(intent) not startservice(intent) for indefinite internal of time.so it would work till your activity is binded to your service when you finish activity then call onUnbind().
onDestroy()in activity call stop service.
check in manifest that your receiver is not registered there.
I was doing a stupid mistake there. I was passing the references of variables defined in my activity to the broadcast service. It worked fine when my activity is still alive but when my activity was killed the service ended up with null pointers which upon updating crashed the service.

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...

Share a thread between different activities

I'm about to develop an application for Android.
I need to continuously run an update thread that executes a task in a given interval. And this thread needs to be shared between activities.
I would also like to notify the active Activity when the thread executes a task.
In iOS I would execute a thread from the AppDelegate and then send notifications, but how do I achieve this with the Android SDK?
I'd say create a Service that does the work for you. When it starts or finishes (or at any point you want), you can send a custom broadcast intent to indicate all parties that your service has passed this point. See Intents.
If you want to start this Service periodically, also have a look at the AlarmManager. That allows you send a broadcast intent periodically - in this case the intent that starts the service.
Also note that it's usually wiser to to terminate a service via stopSelf() when it's work is done. Run it again via intent when needed. Keeping it alive all the time isn't a good idea when it comes to battery life.
Make a service and implement a thread with infinite loop and from there you can do your job....to update data in activity you can make a static method and you can call it from there with appropriate arguments....

Categories

Resources