I have a Runnable r that is triggered periodically once per minute by handler.postDelayed(60*1000). And I test my code on a real device.
However I notice, when the phone is charging (AC or USB) , it works well, but if the phone is disconnected, the Runnable r will only run once every 20min or even worse, several hours. Thanks for any help!
Below is the code:
private final Runnable listen_to_server = new Runnable(){
public void run(){
new Thread() {
public void run() {
try {
handler.sendMessage(handler.obtainMessage(PING_SERVER,"listen"));
synchronized (listen) {
listen.wait();
}
handler.postDelayed(listen_to_server, 50000);
}
catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
};
In the Handler:
handler=new Handler() {
#Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case PING_SERVER:
String type = (String) msg.obj;
add_log("ping server"); // print to screen and Log.d
...
...
}
}
}
Referring to this link i think the problem might be, as they said:
Android is not a real-time operating system. All postDelayed()
guarantees is that it will be at least the number of milliseconds
specified. Beyond that will be dependent primarily on what the main
application thread is doing (if you are tying it up, it cannot process
the Runnable), and secondarily on what else is going on the device
(services run with background priority and therefore get less CPU time
than does the foreground).
How to fix this? in this post the solution was the following:
You'll probably have better luck using the AlarmManager for such a
long delay. Handler is best for ticks and timeouts while your app is
in the foreground.
so try implement an AlarmManager looking at the doc.
Hope i helped :)
Related
I've a TextView where I want to set a message according to time ( hour of day). To achieve this I'm using-
Thread t2 = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(3600000);
handler.post(new Runnable() {
#Override
public void run() {
int hour=Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
update(hour);
}
});
}
} catch (InterruptedException e) {
}
}
};
t2.start();
where update(hour) is used to update the message.
This works fine, however, the updating is done depending on the launching time. For example, the message should update at time 20:00. But if the app is launched at 19:59, the updating takes place at 20:59.
If I use Thread.sleep(1000) it works just as expected. But I feel like wasting resource by running the thread every second just to look for a 1 hour event. Is there any better way to do this?
Surely you need to check the current time, get the minutes past the hour, then work out from there when the next hour 00 will come. Then, just sleep time for those minutes, then for all the hours after that sleep for the full hour.
Take a look at AlarmManager.
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.
What is happening in Android if I have IntentService defined as following:
public class BackgroundService extends IntentService {
public BackgroundService() {
super("BackgroundService");
}
#Override
protected void onHandleIntent(Intent workIntent) {
run();
}
private void run() {
try {
while(true)
{
//Some expensive Internet & SQL querying stuff
Thread.sleep(1000 * 60 * 60);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
How bad will it drain the battery?
I aim for rather fundamental answer (What will happen if I set the sleep to 1 day)?
You question to so close to this one. He also trying to do some work inside a loop and make the Thread sleep.
From the Geeks answer in the provided question, I can tell you that it depends on the //Some code line and what will you replace it with. You might replace it with an intensive code that use the internet, GPS, Flash, Camera and consume your battery for sure OR you might replace it with nothing and let the Thread sleep which allow the CPU to replace it with any other Thread that needs to perform anything.
I am making android application which sends signal from android app to arduino.
But i want to make arduino pin high and low for specific time period say one hour.
i.e user will specify the time period and length of time period..
How i can approach in android for this..
For Android you need to schedule your background task at regular interval as a separate process. You can use Syncadapter for your android application.
or Try this
final Handler handler = new Handler();
Runnable runable = new Runnable() {
#Override
public void run() {
try{
//do your Arduino code here
//also call the same runnable
handler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//also call the same Arduino code here
handler.postDelayed(this, 1000);
}
}
};
handler.postDelayed(runable, 1000);
Hope it helps !
I have to run a bit of code in the background every one second, the code will call a webservice which searches a database and returns a value to the application. My question is which method would be the most effective to do this? I have read up on Timers, Threads, AsyncTask and Services and each seem to have their pros and cons. Please can someone tell me which would be the best to use considering execution time and battery life.
Thanks
Update:
I decided to use Aysnc task to run my code in the background while using a TimeTask to trigger the AsyncTask at regular intervals. This way the operation is destroyed when I leave that particular activity
You should use the service to do the background operation but in your case you want to run code in 1 sec here is the example of service using handler it call in every 1 sec.
public class YourService extends Service {
private static final String TAG = "Your Service";
private final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onDestroy() {
super.onDestroy();
// Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
handler.removeCallbacks(sendUpdatesToUI);
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
/// Any thing you want to do put the code here like web service procees it will run in ever 1 second
handler.postDelayed(this, 1000); // 1 seconds
}
};
#Override
public void onStart(Intent intent, int startid) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);//1 second
Log.d(TAG, "onStart");
}
}
and service can't run every time android idle the service within 3 or 4 hr i suggested you to use the foreground service to use your process long running.
For operations like this I tend to use a Service component. for the task itself i use an AsyncTask which will wait a set time before it repeats itself (using a while loop).
You will have to create a new Thread so that the call don't lock up the device if the call takes longer than expected. The AsyncTask is an easy way to use multithreading, but it lacks the functionality of repeating tasks. I would say that you are best of either using a Timer or the newer ScheduledExecutorService.
If you chose to use the Timer you create a TimerTask that you can hand it. The ScheduledExecutorService takes a Runnable instead.
You might want to wrap the thread in a Service (The Service does not provide a new Thread), but this is not always necessary depending on your needs.
As suggested in comment, you can also use the Handler.postDelayed(). Although you still need to create a new thread and then call Looper.prepare() on it:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
(Code from Looper docs)
Also; calls to a webservice every second seems way too frequent, especially if the user is on a slow connection or there are data that needs to be transferred, try to reduce the calls as much as possible.
I think it's not only one solution, so it's up to you. You can try start thread with this run method:
private final int spleeptime = 1000;
public boolean running;
#Override
public void run() {
while (running) {
try {
int waited = 0;
while ((waited < spleeptime)) {
sleep(100);
waited += 100;
}
} catch (InterruptedException e) {
} finally {
// your code here
}
}
}
I have an android app that repeatedly collects fingerprints from the wifi-networks that are around (for scientific reasons, not to invade anybodies privacy).
Anyways, imagine I have a function that does this work and it's called scanWifi(). I initally wanted to start it like this:
ExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor();
mExecutor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
scanWifi();
}
}, 0, interval, TimeUnit.MILLISECONDS);
Sadly, this only works reliably when the phone is plugged in. If it's plugged out and lays there for a while, it doesn't run my scanWifi() function every minute. Sometimes there are gaps of several minutes between single calls to scanWifi().
I also tried doing the same thing using a Timer/TimerTask with similarly poor results.
The only thing that seems to work more or less reliable until now is to post it to a handler and call it repeatedly, like this:
Handler h = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
if (!mIsStopped) {
scanWifi();
h.postDelayed(this, mInterval);
}
}
};
h.post(r);
Why is that the case? Is the CPU sleeping and thus misses the scheduled execution? I hold a partial wakelock in my app.
I think what you're looking for is an AlarmManager. See, for example, this question: Android: How to use AlarmManager