We have an app who should process a task every 10 seconds. This should be more or less exact, which means that a difference of 1 or 2 seconds is OK, but not gaps of 20 seconds or more.
This should work regardless if the app is open, in foreground or in background.
We implement this via AlarmManager, but it is not working properly. If the smartphone is not plugged in and it is running in background, there are gaps in the execution.
With Android 4.3., we have gaps (about 30 seconds) from time to time, with Android 5.x we have fewer gaps, but gaps about 5 or 10 minutes long!
I think there must be a way to implement this, an alarm clock is also possible and is exact.
More about the app: It works in a service and a broadcast receiver is implemented. This means the service is restarted if I wipe away the app or restart the handy. This works correctly. The only problem is the 10 second task.
Any hints? How is an alarm clock implemented? Which calls, API?
I tried different ways until now without success.
Thanks
Hans
public void callAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
PerformBackgroundTask performBackgroundTask = new PerformBackgroundTask();
// PerformBackgroundTask this class is the class that extends AsynchTask
performBackgroundTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000); //execute in every 10000 ms
}
You can do it with handler and runnable, which I think is preferred by Android..
public class ActivityMain extends Activity
{
private Handler mainHandler = new Handler();
private Runnable backgroundTask = new Runnable() {
#Override
public void run() {
//do your background task
mainHandler.postDelayed(this, 10000);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainHandler.postDelayed(backgroundTask, 10000);
}
}
Use of "AlarmManager" with "broadcast Receiver" and "service". These 3 component will make your requirement fulfill.
Using Alarm Manager to generate a Broadcast Receiver, and from BroadcastReceiver start a Service where you can put your desired code of logic to get your task done in every 10 Seconds.
Related
I have a Service that shows a toast every 10s, but I'd expect Doze to slow it to every 15 minutes when it's in the background as the app is not whitelisted. Here's my service:
#Override
public void onCreate() {
super.onCreate();
if (mTimer != null)
mTimer = null;
// Create new Timer
mTimer = new Timer();
// Required to Schedule DisplayToastTimerTask for repeated execution with an interval of `2 min`
mTimer.scheduleAtFixedRate(new DisplayToastTimerTask(), TIMER_DELAY, TIMER_INTERVAL);
}
...
private class DisplayToastTimerTask extends TimerTask {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Hello world", Toast.LENGTH_SHORT).show();
}
});
}
}
What I'm getting in the emulator is that the toast is shown every 10s even when I'm at the home screen. Doesn't Doze restrict all non-whitelisted background services/apps to 15 min waking time?
Doze occurs only when the screen is off, and has been for some minimum amount of time. It has nothing to do with just backgrounding.
In addition, Timers or Threads set by the service wouldn't automatically be canceled, as 1)the OS doesn't know about them and 2)There's no way to know if its safe to do so, or if doing so would cause deadlock or other errors. They may be delayed to the Doze allowed rate of execution, but would not be stopped.
I need to repeat a task every 1 hour in the background (I am sending some info to my server).
I tried to use a service with a post delay handler calling it self.
handler = new Handler();
runable = new Runnable() {
#Override
public void run() {
try{
//sending info to server....
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//also call the same runnable
handler.postDelayed(this, 1000*60*60);
}
}
};
handler.postDelayed(runable, 1000*60*60);
This did not work, in small time interval of 1 minutes it worked fine, when i changed it to 5 minutes it worked for about 5 repetitions and then the timing got wrong and after an hour the service shut down.
i want to try to use a AlarmManager but in the documentation
it says "As of Android 4.4 (API Level 19), all repeating alarms are inexact"
does anybody know how inexact it is? is it seconds? ,minutes?
can i rely on this to work on time?
does anybody have any other suggestions for repeating tasks in a service?
Thanks
You can use this This Code is for repeated calling on oncreate method or anyother thing
public void callAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
onCreate();
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 1000); //execute in every 1000 ms
}
I would like to periodically check for updates doing network call every 30 sec and update listview accordingly, only if my screen is in foreground (thus not from service). What I am doing for that is -
private void refreshPeriodically()
{
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new callToMyAsyncTask().execute(context);
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 30*1000); //execute in every 30 sec
}
but, that hangs my list while scrolling.
What should I do for that?
You shouldn't use handler. When you call handler.post() it will run on UI thread so your list will freeze. Start a new callToMyAsyncTask in run method in TimerTask without using handler and you can call timer.cancel() when your activity is not in foreground.
Also I think you should use scheduleAtFixedRate instead of schedule.
However I think you may have some problems without service. When you cancel timer it will not cancel current callToMyAsyncTask and when it call onPostExecute activity is no longer available. But I don't know it will crash or not.
I have this method
public void GetSMS(){
//in this method I read SMS in my app inbox,
//If have new SMS create notification
}
for this I think create timer tick method and every 5 sec call GetSMS()
How can I create a correct method for that ?
Here is an example of Timer and Timer Task. Hope this helps.
final Handler handler = new Handler();
Timer timer = new Timer(false);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
// Do whatever you want
}
});
}
};
timer.schedule(timerTask, 1000); // 1000 = 1 second.
Maybe with a timer and a timertask?
See javadocs:
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
Yet receiving broadcasts is probably a more solid solution.
See: Android - SMS Broadcast receiver
Use Timer.scheduleAtFixedRate() as follow:
final Handler handler = new Handler();
Timer timer = new Timer(false);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
GetSMS();
}
});
}
};
timer.scheduleAtFixedRate(timerTask, 5000, 5000); // every 5 seconds.
I saw it by accident.. This is not the right way to do it..
You don't need to check if there is a sms that received. Android provide broadcast receiver to get notified when sms is income.
Here you go, you have the link here.. Copy paste and it will work great
http://androidexample.com/Incomming_SMS_Broadcast_Receiver_-_Android_Example/index.php?view=article_discription&aid=62&aaid=87
Hope that this make sense
Although the above timer methods are the correct way to use timers of the sort you are after, I quite like this little hack:
new CountDownTimer(Long.MAX_VALUE, 5000)
{
public void onTick(long millisUntilFinished)
{
// do something every 5 seconds...
}
public void onFinish()
{
// finish off when we're all dead !
}
}.start();
Long.MAX_VALUE has, according the Java docs, a (signed) value of 2^63-1, which is around 292471 millennia ! So starting up one of these countdown timers effectively lasts forever relatively speaking. Of course this depends on your interval time. If you want a timer every 1 second the timer would "only" last 58494 millenia, but we don't need to worry about that in the grander scheme of things.
how to run the async task at specific time? (I want to run it every 2 mins)
I tried using post delayed but it's not working?
tvData.postDelayed(new Runnable(){
#Override
public void run() {
readWebpage();
}}, 100);
In the above code readwebpage is function which calls the async task for me..
Right now below is the method which I am using
public void onCreate(Bundle savedInstanceState) {
readwebapage();
}
public void readWebpage() {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute("http://www.google.com");
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response1 = "";
response1=read();
//read is my another function which does the real work
response1=read();
super.onPostExecute(response1);
return response1;
}
protected void onPostExecute(String result) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
TextView tvData = (TextView) findViewById(R.id.TextView01);
tvData.setText(result);
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "http://www.google.com" });
}
}
This is what I my code is and it works perfectly fine but the big problem I drains my battery?
You can use handler if you want to initiate something every X seconds. Handler is good because you don't need extra thread to keep tracking when firing the event. Here is a short snippet:
private final static int INTERVAL = 1000 * 60 * 2; //2 minutes
Handler mHandler = new Handler();
Runnable mHandlerTask = new Runnable()
{
#Override
public void run() {
doSomething();
mHandler.postDelayed(mHandlerTask, INTERVAL);
}
};
void startRepeatingTask()
{
mHandlerTask.run();
}
void stopRepeatingTask()
{
mHandler.removeCallbacks(mHandlerTask);
}
Note that doSomething should not take long (something like update position of audio playback in UI). If it can potentially take some time (like downloading or uploading to the web), then you should use ScheduledExecutorService's scheduleWithFixedDelay function instead.
Use Handler and PostDelayed:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
readWebpage();
handler.postDelayed(this, 120000); //now is every 2 minutes
}
}, 120000); //Every 120000 ms (2 minutes)
you can use TimerTask instead of AsyncTask.
ex:
Timer myTimer = new Timer("MyTimer", true);
myTimer.scheduleAtFixedRate(new MyTask(), ASAP, TWO_MINUTES);
private class MyTask extends TimerTask {
public void run(){
readWebPage();
}
}
When phone goes to sleep mode, to save battery, and it is quite possible to happen within 2 mins interval, Handler.postDelayed() may miss scheduled time. For such activities you should use AlarmManager, get a lock with PowerManager to prevent going to sleep back while you're running the AsyncTask.
See my post with code sample here
Also you may want to read Scheduling Repeating Alarms
I suggest to go with Handler#postDelayed(Runnable). Keep in mind that this method will work only when your app is running (may be in background) but if user closes it manually or simply Android runs out of memory it'll stop working and won't be restarted again later - for that you need to use services.
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2 * 60 * 1000); // every 2 minutes
/* your code here */
}
}, 2 * 60 * 1000); // first run after 2 minutes
This code will wait 2 minutes, execute your code, and then keep doing that every 2 minutes. But if you want it to run instantly for the first time - and then start the wait-do loop, instead use:
final Handler handler = new Handler();
/* your code here */
new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2 * 60 * 1000); // every 2 minutes
/* and also here - your code */
}
}.run();
or, if your code is longer than just one method (readWebsite() in this case), and you don't want that to be duplicated:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2 * 60 * 1000); // every 2 minutes
/* your longer code here */
}
}, 0); // first run instantly
(^ this one is just like the first example but has a 0ms delay before first run instead of 2 minutes)
(This answer is based on #Devashish Mamgain's one but I added too much details for an edit so I had to add a new one)
Try extending the Thread class, set a sleep time of 2000 millis and place your call into the run method. That should do it.
Execute multiple messages(Runnables) then he should use the Looper class which is responsible for creating a queue in the thread. For example, while writing an application that downloads files from the internet, we can use Looper class to put files to be downloaded in the queue. This will help you to perform async task in android...
HandlerThread hThread = new HandlerThread("HandlerThread");
hThread.start();
Handler handler = new Handler(hThread.getLooper());
final Handler handler1 = new Handler(hThread.getLooper());
final long oneMinuteMs = 60 * 1000;
Runnable eachMinute = new Runnable() {
#Override
public void run() {
Log.d(TAG, "Each minute task executing");
handler1.postDelayed(this, oneMinuteMs);
sendPostRequest();
}
};
// sendPostRequest();
// Schedule the first execution
handler1.postDelayed(eachMinute, oneMinuteMs);
You can use Time with Handler and TimerTask
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask backtask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
//To task in this. Can do network operation Also
Log.d("check","Check Run" );
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(backtask , 0, 20000); //execute in every 20000 ms*/
You can check logcat to verify whether is running or not using 'check' tag name
You could run a loop within the AsyncTask that sleeps for two seconds between doing the tasks. Something like this:
protected Result doInBackground (Params... params) {
while (!interrupted) {
doWork();
Thread.sleep(2000);
}
}