I need to perform a network operation in a BroadcastReceiver.
So far I achieve it by starting a new thread:
#Override
public void onReceive(Context context, Intent intent) {
new Thread(new Runnable() {
public void run() {
// network stuff...
}
}).start();
}
Is there any risk that the process will be killed before the thread is done?
Is it better to use an IntentService instead? Any other better approach?
Is there any risk that the process will be killed before the thread is done?
If this receiver is registered via the manifest, yes.
If this receiver is registered via registerReceiver(), the lifetime of your process will be determined by other running components.
Is it better to use an IntentService instead?
If that work will be over a few milliseconds, IMHO, yes, probably in concert with WakefulBroadcastReceiver.
Any other better approach?
There is a goAsync() option on BroadcastReceiver that gives you a window of time to do work in another thread before triggering an ANR. I avoid this, because it is poorly documented. For example, it does not directly address your question: what is the process importance while this background thread is doing its work? Does this keep the device awake long enough for our work to get done? And so on. I'll use an IntentService or some other form of Service, where I have better understanding of the contract.
It isn't the best idea. The life-cycle of a BroadcastReceiver lasts as long as it takes to finish calling onReceive(), after that it's destroyed. If you were to start running a new thread, there's a chance the BroadcastReceiver would be killed before the thread completes, which would wind up in some unexpected behaviour.
The better option would be to start a background service, like you said.
Here is some practical information from my tests:
The onResume lasts for 10 seconds.
The Thread itself lasts far longer. About 7 minutes on an idle device.
Filling about 450MB of RAM (on a 4GB device) will stop the thread and garbage collect everything.
Reliability is worse if the BroadcastRecevier is triggered while the device is in sleep-mode (by an AlarmManager). Most of the time it runs fine but sometimes it runs hours later when the phone get's unlocked and sometimes it doesn't run at all. (I used a wake lock too but I don't think it made much of a difference.)
This could be worth trying in some cases because from my experience the android specific threading solutions are not very reliable as well. Maybe for something like a widget button that fetches the latest weather forecast...
Related
I have programmed an app which uses a handler. Inside the handler there are some network operations.
The handler has an interval of min*1000*60 ms. I used the handler with min=5, so it should repeat after five minutes. But this is the result of my check:
First Handler:
16:20:22
16:25:23
17:01:52
17:13:07
17:20:19
17:25:55
Second Handler:
16:20:26
16:25:26
17:01:35
17:12:51
17:20:02
17:25:37
Third Handler:
16:24:58
16:31:59
17:12:43
17:19:54
17:25:30
All Handlers are running in separate Services. The screen is turned off.
Do you have any ideas or alternatives to a Handler in Android?
The code of the handlers is so simple:
handler.postDelayed(new Runnable() {
public void run() {
// network operations
}
}, interval);
First, assuming that you created your Handler via new Handler(), it will do its work on the main application thread. Do not do network I/O on the main application thread. It also is likely the source of your drift.
Second, most likely you do not need three services. Usually, you need one service. Three services simply makes your app more complicated for no added value to the user.
Third, your Handler will only work while the device is awake, and I do not know whether that is an acceptable limitation or not.
Fourth, using a Handler implies that your service(s) will be running indefinitely, and users do not like this. Only have your services be in memory when they are actively delivering value to the user.
A better way to implement this, therefore, is to use AlarmManager for your scheduled events. If you do not need the events to be processed while the device is asleep, the AlarmManager can directly pass control to your service. Ideally, that would be an IntentService, so that the service will give you a background thread automatically and so that the service will automatically shut itself down when the work is complete.
If you need the events to be processed even while the device is asleep, please give the user control over the event period, including an option of "do not do anything", as waking up the device every 5 minutes to do network I/O will be bad for the battery. Then, use a WakefulBroadcastReceiver or a WakefulIntentService to arrange to have your work be done while keeping the device awake.
Use SheduledThreadPoolExecutor instead of handler.
It has scheduleAtFixedRate function, which does exactly what you need. And no handlers at all)
What is the cons of using Thread instead of using Android Service in an App for long running task. What will happen if I don't use Android Service for long running task?
Service:
A service is a component which runs in the background, without direct interaction with the user. As the service has no user interface it is not bound to the lifecycle of an activity.
Services are used for repetitive and potential long running operations, like Internet downloads, checking for new data, data processing, updating content providers and the like.
It is possible to assign services the same priority as foreground activities. In this case it is required to have a visible notification active for the related service. It is frequently used for services which play videos or music.
Threads:
They are simple runnable threads. You can execute non UI stuff with these threads but you can't perform UI tasks in them (as UI is not thread safe). For dealing with UI in these threads, you will have to use Handlers, which is quite cumbersome for beginners to get a grip and understanding of them.
So depending on your needs and app you can choose the one best suits you.
A Service is an application component that can perform
long-running operations in the background and does not provide a user
interface. Another application component can start a service and it
will continue to run in the background even if the user switches to
another application. Additionally, a component can bind to a service
to interact with it and even perform interprocess communication
(IPC). For example, a service might handle network transactions, play
music, perform file I/O, or interact with a content provider, all
from the background.
On other hand, Threads are the cornerstone of any multitasking
operating system and can be thought of as mini-processes running
within a main process, the purpose of which is to enable at least the
appearance of parallel execution paths within applications.
They are to be used as per requirement and we cannot actually point out pros and cons of either of them as both of them are essential in different situations.
What will happen if I don't use Android Service for long running task?
You might get lucky and your code finishes. Then again, you might not get lucky, and your code gets killed at a random point in time.
Aside from the textbook descriptions of what an Android Service is and what a Thread is, the main difference between the two which is directly relevant to your question is how the OS threats them.
A thread is a way to execute code in the background, while a service is a way to make Android aware you are executing code in the background.
As far as the underlying Linux kernel is concerned, it knows only about threads, and cares about them only with regards to thread switching and prioritization. Whether there is a service has no impact on this.
However, as far as the Android device memory management and task prioritization goes, Android does not know or care about threads in your process. It only knows about services, and interacts with them on the main app process thread only.
Thus, for as long as you have a thread alive, the kernel will happily try to keep the process alive and allocate CPU time for that thread execution.
However, unless you have an activity, service, content provider, or a broadcast receiver alive, the Android memory manager might decide to kill your process to reclaim its resources for another higher priority process, no matter what threads might be working at this point.
Therefore, while you could go away with running stuff on a separate thread if the user is interacting with your activity, if you want to make sure the background task finishes successfully and is not interrupted at a random point, you need to wrap it in a service (preferably one that is bound by an activity, or is elevated to UI priority by showing a notification).
Note that having a service does not guarantee you that its code will be running in the background. Android will call the lifecycle methods (onStartCommand/onBind/onCreate/OnDestroy) on the main thread of the application process. Your code will have to start a thread to ensure true background execution.
Services are highly recommended and used in Android to do both foreground and background tasks. Instead of going into the definitions I would highly recommend you to look into IntentService class specifically in Android. Available from API Level 3 this class does most of the worker thread heavy lifting for your background task. This class handles asynchronous requests expressed as Intents. Clients send request using startService(Intent) calls. The service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work. Coolest thing you can use this along with an AlarmManager implementation to do say what you want to do every 10-15 mins and still not worry about threads and handler explicit implementation as you would have to if you use Service class.
Here is a short bit of code on how to implement it.
public class UpdateService extends IntentService {
public UpdateService() {
//constructor
}
#Override
public void onCreate() {
super.onCreate();
//Called by the system when the service is first created.
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStart(intent, startId);
return(START_REDELIVER_INTENT); //Intent Relidelivery
//You should not override this method for your
IntentService and remember onStart() for IntentService is
deprecated.
}
#Override
protected void onHandleIntent(Intent intent) {
//do your main background tasks here forget about threading doing anything
in here Android will do the heavylifting as required
}
#Override
public void onDestroy() {
super.onDestroy();
//finalize your objects GC etc here
//Called by the system to notify a Service that it is no longer
used and is being removed.
}
}
Services are best implementations for long running tasks that you don't need user input or ui updates right away. If you absolutely don't need to don't use threads and handlers since you might come across a lot of concurrency / deadlock etc issues.
Hope this helps.
Nothing will happen, I ran an algorithm in a async task about 90 hours. Worked fine.
Async Task: seperate a "heavy" task from the UI, for example a download
Service: seperate a task from the App, for example an alarm clock
I would like to create an Android application with real-time monitoring functions. One monitoring function is to audit the audio flow. The other function is to interact with a peripheral sensor. These monitoring functions can be triggered by others.
Besides, in order to save power consumption, the audio function will be running in a polling mode, i.e. sleep for a certain amount of time and wake for a certain amount of time.
I am considering how to design the Android application.
Whether to design the audio function as a Service or an Activity?
The problem is if it is designed as an Activity, the audio function will be off if screen turns off after a period of time.
How to design the polling function? Use an AlarmManager or a inner-thread with Timer?
My goal is to save the power consumption as much as possible. Thanks.
I would recommend following
a) Use a Service. Activity is short lived entity (it works only while it's on the screen)
b) Make the service foreground (read this: http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification). This will decrease the chance that system will kill your service
c) In the service, start a thread and do everything you need in the thread.
d) If you want execute periodically, just do Thread.sleep() in the thread (when Thread sleeps it doesn't consume CPU cycles).
I believe c) and d) is preferable to AlarmManager.
Here is piece from documentation (http://developer.android.com/reference/android/app/AlarmManager.html) : "Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler."
Since your application running it's better to have some permanently running thread and execute something on it. Generally speaking Handler, HandlerThread, MessageQueue are just convenience classes for more complex message handling and scheduling. It looks like your case is quite simple and usual Thread should be enough.
Concurring with Victor, you definitely want to use a Service, and pin it into memory by calling startForeground()
However I suggest you look into utilizing the built in system Handler ; place your functionality in a Runnable and call mhandler.postDelayed(myRunnable, <some point in future>) ; this will allow the android framework to make the most of power management.
That's a service.
And you may want some extra robustness: the service can be killed and NOT restarted later, even being a foreground service. That will stop your monitoring.
Start your service from the UI. If you want the service to survive device reboot, also start it from a BroadcastReceiver for android.intent.action.BOOT_COMPLETED.
Create a thread in the service as described in other answers here.
Additionally, use Alarm Manager to periodically start your service again. Multiple startService() calls are OK. If already running, the service will keep running. But if it's been forgotten by the system, say, after a series of low resource conditions, it will be restarted now.
Schedule those alarms responsibly: to be a good citizen, set the absolutely minimal frequency. After all, Android had some good reasons to kill the service.
With some services, even more steps may be needed, but in this case this approach seems to be sufficient.
Why is it suggested generally to pass a pending intent for an Intent Service when using alarm manager? The same thing can be done in the onreceive() function of the broadcast receiver called by the alarmmanager. What is the advantage with using a service(Intent Service)?
If everything that you need done can be completed in onReceive of a BroadcastReceiver, then you should use that, not an IntentService.
If you want to do anything after the BroadcastReceiver, then you should use the IntentService. For example, if you want your BroadcastReceiver to start a Service, and you want the service to gain a WakeLock, then you should be using an IntentService instead.
The reason is that AlarmManager only guarantees that the onReceive of a BroadcastReceiver will be run, even if you use RTC_WAKEUP. So, it is slightly possible that if you use the BroadcastReceiver/Service combination, then the CPU will fall asleep before the Service can acquire the WakeLock - this is, unless you acquire a WakeLock in the BroadcastReceiver and you acquire one in the service, perhaps via a static WakeLock. But this is... messy, I suppose.
Btw, I have never implemented an IntentService. I just use the BroadcastReceiver and Service combo and have never had a problem reported. All the information I provided are things I read from other SO posts (primarily from CommonsWare)
EDIT:
The 50ms time frame I read from something CommonsWare posted on StackOverflow, and CommonsWare seems to be a rather reliable source of knowledge for Android.
I looked it up and, The docs do say:
(there is a timeout of 10 seconds that the system allows before
considering the receiver to be blocked and a candidate to be killed).
And they also say:
If this BroadcastReceiver was launched through a tag, then the object is no
longer alive after returning from this function.
You should not do anything that takes close to 10 seconds, just to be safe.
If you do anything that has to wait for a response, the BroadcastReceiver will die because the onReceive will likely finish running before you get the response back.
Though, I suppose the reason for the 50ms time frame is so you don't risk causing an ANR or any lag. Because if you use a Service, then you can start a new Thread, and it will not block. You would not be able to start a new Thread in a BroadcastReceiver because the code after the thread would continue to run, the BroadcastReceiver would die, and then the Thread would die, too.
I need to run a background service in Android mobile which runs 24*7, And on Start & On mobile low battery and Hit a webservice every 1hr. Can you please suggest me any approach. I tried reading few articles but did not get any idea. I know here I need to paste some code after trying something. But I did not get any clue. Please let me know how to approach?
You will probably need to use the method startForeground(int id, Notification notification) to prevent the system from killing your Service as stated here:
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
Then you would need some kind of scheduled task to run every hour. Something like a ScheduledThreadPoolExecutor is ideal for this purpose, using the method scheduleAtFixedRate (Runnable command, long initialDelay, long period, TimeUnit unit).
The task that needs to be done each hour must be implemented as a Runnable and submitted to your ScheduledThreadPoolExecutor:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1 );
executor.scheduleAtFixedRate( new MyRunnableTask(), 0, 1, TimeUnit.HOURS );
The Runnable task should be something like:
private class MyRunnableTask implements Runnable {
public void run() {
//Do what needs to be done.
}
I need to run a background service in Android mobile which runs 24*7
Please don't. For starters, it is not possible.
Users complain loudly and often about services that "run 24*7", because the services are tying up system resources (e.g., RAM) for no value. As a result, between third-party task killers and Force Stop options in Settings, users get rid of such services. When they do, particularly on Android 3.1+, your application will not run again, ever until the user manually launches an activity of yours from the launcher.
Android itself will get rid of such services on its own, because too many developers are too sloppy with their service management.
And on Start & On mobile low battery and Hit a webservice every 1hr.
Based on this list, you do not need "a background service in Android mobile which runs 24*7". You need to do work:
when the device starts up
when the device's battery is low
every hour
You can find out when the device starts up by the ACTION_BOOT_COMPLETED broadcast Intent. You can find out when the device's battery is low via the ACTION_BATTERY_LOW broadcast Intent. You can find out when time elapses via AlarmManager, where you establish your own alarm schedule (e.g., every hour).
All three of these triggers should call startService() on an IntentService. The IntentService will allow you to "Hit a Webservice" via its built-in background thread. And, the IntentService goes away when that work is complete, so you are not taking up memory all of the time.
And, if you want to wake up the device out of sleep mode for the every-hour condition, you will probably need to use something like my WakefulIntentService, as otherwise the device may fall back asleep while you are trying to "Hit a Webservice".
This way, your service is only running and taking up resources while it is actively delivering value to the user. It is not running and taking up resources when it is simply waiting for some other event to occur (e.g., the next 59 minutes).