are startService() Intents serialized? - android

a) if my code calls startService() twice, will the Intents be processeced in the order I called them, or might they get switched randomly?
b) will the first run through onStartCommand() complete before the second call starts, or might they run in parallel?
I have read the android services guide and the reference. While they clearly show how the IntentService worker threads are serialized, I've found little information on how the Intents are delivered and processed.

if my code calls startService() twice, will the Intents be processeced in the order I called them, or might they get switched randomly?
The behavior for Service in this regard is undocumented, last I checked. However, they should be called in the order they were issued, based on what seems to happen in practice.
will the first run through onStartCommand() complete before the second call starts, or might they run in parallel?
That is up to you. By default, onStartCommand() on a Service is called on the main application thread, and therefore only one command is processed at a time. If you choose to fork threads from onStartCommand() to process commands, those threads may run in parallel.
While they clearly show how the IntentService worker threads are serialized, I've found little information on how the Intents are delivered and processed.
IntentService maintains its own thread. You implement onHandleIntent() instead of (or possibly in addition to) onStartCommand(). Since there is only one thread, only one onHandleIntent() will be executed at a time.

Related

Is it possible to IntentServices to be called out of order?

I have 2 calls to startService made on the same thread, but apparently these calls are received out of order in my IntentService.
Our client says that the feature works on some devices and no on others, so I'm guessing this out of order could be the case.
I know that IntentService has a FIFO way to execute the Intents. So, once the intent arrives, the order is guaranteed. My question is that could be possible that one startService was delayed and the other goes first. Does anyone have any idea how startService works internally?
The code goes more or less like this
(... some logic...)
callService(param1)
(... more logic...)
callService(param2)

How long do Android worker threads last?

I have seen some postings on this subject, but none of them have satisfactory answers.
Assume that I start a worker thread from my main (one-and-only) Activity, in its onCreate() method. Then I call finish() to cause the Activity to terminate.
At that point, the task it belongs to gets destroyed (since there are no longer any Activity in it). The app (and the process running it) may continue to exist, however, in empty "skeleton" form, so that it can be restarted quickly if desired (although it would be highly susceptible to being killed by the system).
Assuming the above is correct -- when is the worker thread killed? Is it only killed when the system actively destroys the process?
In my case, my worker thread exists as a listener for a Bluetooth connection; when received, it will fire up the desired Activity again. In this situation there is no actively running component (Activity, Service, ContentProvider or BroadcastReceiver). It seems to me that this should work, except that something is killing my worker thread.
I am aware that I could do this (and with less pain) by using a background Service. However, I'm curious about why this isn't working.
Thanks,
Barry
when is the worker thread killed? Is it only killed when the system actively destroys the process?
-> the worker thread is skilled after all its code in run function executed. It still run even when your activity is destroyed.
In my case, my worker thread exists as a listener for a Bluetooth connection; when received, it will fire up the desired Activity again. In this situation there is no actively running component (Activity, Service, ContentProvider or BroadcastReceiver). It seems to me that this should work, except that something is killing my worker thread.
To make it works, You need to have a background service in this case and make a soft/weak reference to your service from your worker thread or more simple, using EventBus to start any component from your Service as:
EventBus.getDefault().post(new BlueToothEvent()); // call in your worker thread
// do something in your service
onBlueToothEventFired(BlueToothEvent e);
Android App lifecycle has a nice example that is very on topic:
A common example of a process life-cycle bug is a BroadcastReceiver
that starts a thread when it receives an Intent in its
BroadcastReceiver.onReceive() method, and then returns from the
function. Once it returns, the system considers the BroadcastReceiver
to be no longer active, and thus, its hosting process no longer needed
(unless other application components are active in it). So, the system
may kill the process at any time to reclaim memory, and in doing so,
it terminates the spawned thread running in the process.
In short, its really not very predictable if you thread would get a chance to run until termination or process will be killed beforehand, you should NOT definitely rely on any order/behavior.
Worth mentioning separately that its fairly easy to leak your activity along with thread even if you finish() it, but if its your last/only activity it does not change the picture
When you start a thread, it is independent of the parent that started it. In your case, it is your application activity. This means that until the Run method has been fully executed, your thread will live.
If you exit the application (and therefore call the activity's onStop method), the thread will still exist, and you will cause a memory leak. It will eventually get killed by the system if you run out of memory.
Since you mentioned that you created a listener to listen for a Bluetooth connection, your thread probably dies before it receives any event (It is impossible for me to know without any code snippet). It might also crash which would be ending the thread.
There is one main (also called UI) thread in Android. That is the only thread your app uses, unless it starts one explicitly via Thread.start(), AsyncTask.execute() etc. All Activities, Services, BroadcastReceivers, etc run all of their lifecycle methods on that main thread. Notice I included Services- a Service runs on the main thread unless it starts its own Thread (the exception to that is an IntentService, which does run on its own Thread).
A Thread you create continues until the Runnable its passed returns from its run function (or of course the process is terminated). This can live past the end of the Activity/Service it was created by. However such a Thread would still live in the original instance of the component, and would not be able to access variables of a new instance if one was restarted without a lot of special work (see Loader pattern).

BroadcastReceiver: goAsync() vs AsyncTask in onReceive()

I have a BroadcastReceiver (or, more specifically, an AppWidgetProvider) in which I need to do some network operations in the onReceive() method... not particularly long-running (should finish within 10s, and if not then I'm happy(*) to time them out).
At present I'm executing an AsyncTask from onReceive() so that the network operations don't block the UI thread, but I see that a BroadcastReceiver also provides a goAsync() method for apparently much the same purpose.
I'm struggling to find an explanation as to what exactly the differences are between using AsyncTask and goAsync() in this context... when would you use one, and when the other?
(*) I mentioned that my network operations and subsequent processing would typically finish within the 10s (**) that I understand you have before the BroadcastReceiver is killed (after returning from onReceive()). However, ideally it would be good to allow the operations to continue beyond the 10s in particularly challenging conditions (unreliable network, slow device). Is either of the above methods any better than the other in this respect? At least for goAsync(), the docs suggest that you should still wrap things up within the 10s. But for AsyncTask is it ever possible to spawn the AsyncTask and have the doInBackground() method run beyond the 10s... will it have an existence beyond the lifetime of the BroadcastReceiver if it is declared as a static inner class of the BroadcastReceiver?
(**) EDIT: the 10 second thing is in the docs for BroadcastReceiver.onReceive()... specifically:
When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed).
AsyncTask in receiver is a bad practice, try to avoid it because the system can kill your process and onReceive no guarantee its return.
goAsync() returns a PendingResult object,
the system considers the receiver as alive until you call the PendingResult.finish() on it.
goAsync:
if you call goAsync before the BroadcastReceiver::onReceive return, when a new broadcast comes after a while, android system will call the same receiver, just the same receiver instance where you call goAsync
AsyncTask:
if you call AsyncTask before the BroadcastReceiver::onReceive return, when a new broadcast comes after a while, the android system may call a new receiver even though the process is still running, you may not suppose the receiver is the same as the previous one where you call AsyncTask

Wait all threads finish in Service

I have a Service where I run a task inside a Thread. I call this Service many times and obviously it creates the corresponding number of Threads.
How am I going to know when no one Thread is running so I can call stopSelf() ?
The easiest thing to do is make your service subclass IntentService. This is a special kind of Service that will perform work in a background thread, and automatically stop the service when there is no more work to perform. There is a single thread per Service that you declare in your manifest. All you do is determine what sort of work you want to perform by implementing its onHandleIntent(), which is automatically run in that background thread for each Intent delivered to it.
You can keep track of the running threads in an array. When each thread completes it should remove itself from the array and call a method that checks if there are any running threads. That method just checks if the list of running threads is empty, and if so, calls stopSelf().
Or use IntentService if this suits your needs.

onStartCommand with intent action vs bound service

If the way I interact with service is single directional (that is only call service to do something without asking for result). What is the difference between these two approaches:
startService(intent) and onStartCommand do task depend on intent.getAction
bind the service and send message to the service using Messenger. So that service do task based on the message.
Here is one difference I can thought ( I am not sure):
For approach 1, we need to create the service every time we call startService, so the overloading is we need to create the service every time unless use START_STICKY.
There are several differences but the most significant is thread management.
IntentService
If you use an Intent service, onHandleIntent is called in a single daemon thread. Each new call to startService will appear as an in-order, queued call to onHandleIntent. The result is simple, well behaved, in-order execution of calls, on that daemon thread. Btw, the service will not stop itself until the queue is empty: no need to "recreate"
Bound Service in same App
There are, actually, two cases for a bound service. If it is running in your process, the service will run on the UI thread. If you need stuff run off the UI thread, you will have to build your own thread (probably a Looper) and, thus, talk to it with a Messenger. The result is more flexible (# of threads, queueing order, etc. is up to you) but very similar to the IntentService.
Bound Service in another App
If the Bound service belongs to a different application, your calls to it are run on one of several Binder threads. You don't need to manage those threads, they are supplied by the framework. They can, however, execute your calls out of order.

Categories

Resources