How to make a simple timer without new class in Android? - java

I'm developing a Service for Android, that must run in background, executing a function each 100 seconds. That's the source code (example)
package com.example
import ....
public class Servizio extends Service {
public IBinder onBind(Intent intent) {
}
public void onCreate() {
}
public void onDestroy() {
//here put the code that stop the timer cycle
}
public void onStart(Intent intent, int startid) {
//i want to begin here the timercycle that each 100 s call myCycle()
}
public void myCycle() {
//code that i can't move on other class!!!
}
}
How I can do that? Now the service execute myCycle() just one time, beacause I put a calling in onStart().

Use a Timer with a TimerTask. To execute your method every 100 seconds, you can use the following in your onStart method. Be aware that this method creates a new thread.
new Timer().schedule(new TimerTask() {
#Override
public void run() {
myCycle();
}
}, 0, 100000);
Alternatively, use an android.os.Handler as described in this article: Updating the UI from a Timer. It is better than a Timer because it runs in the main thread, avoiding the overhead of a second thread.
private Handler handler = new Handler();
Runnable task = new Runnable() {
#Override
public void run() {
myCycle();
handler.postDelayed(this, 100000);
}
};
handler.removeCallbacks(task);
handler.post(task);

I usually do this, if I understood correctly you wanted the myCycle to execute every 100 secs.
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
myCycle();
}
}, 0,100000);

When I had this issue, where I call out to a webservice on a periodic basis this was my solution:
public class MyService extends Service {
private Handler mHandler = new Handler();
public static final int ONE_MINUTE = 60000;
private Runnable periodicTask = new Runnable() {
public void run() {
mHandler.postDelayed(periodicTask, 100 * ONE_MINUTE);
token = retrieveToken();
callWebService(token);
}
};
I call the postDelayed early so that the delay from the webservice call doesn't cause the timing to shift.
The two functions are actually in the MyService class.
UPDATE:
You can pass a Runnable to postDelayed as shown here:
http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable, long)
public final boolean postDelayed (Runnable r, long delayMillis)
Since: API Level 1 Causes the Runnable r to be added to the message
queue, to be run after the specified amount of time elapses. The
runnable will be run on the thread to which this handler is attached.
Also, my code won't compile due to missing functions, this is shown as an example of what the OP can do.

Related

Android thread error - Can't create handler inside thread that has not called Looper.prepare()

I am trying to get a timer to run in a separate thread.
I have the following declaration before my onCreate function:
TimerTask scanTask;
Timer t = new Timer();
Then the following code within onCreate:
Runnable runnable = new Runnable() {
#Override
public void run() {
scanTask = new TimerTask() {
#Override
public void run() {
System.out.println("timer test");
}
};
t.schedule(scanTask, 0, 5000);
CountDownTimer waitTimer;
waitTimer = new CountDownTimer(20000,300) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
t.cancel();
System.out.println("Timer stopped");
}
}.start();
}
};
Thread periodic_scan = new Thread(runnable);
periodic_scan.start();
However, when I run the app, it crashes and gives me the error:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I'm not sure I completely understand why this error is occurring. Is it something to do with the UI thread? Also, I'm not sure whether the way I've tried to implement this is correct. This is my first time trying to deal with threads in Android.
you can use HandlerThread like
HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start();
Handler threadHandler = new Handler(handlerThread.getLooper(),new Callback() {
public boolean handleMessage(Message msg) {
return true;
}
});
I ended up changing the code a bit and decided to use a Thread class:
class TimerThread extends Thread {
TimerTask scanTask;
Timer t = new Timer();
#Override
public void run() {
Looper.prepare();
scanTask = new TimerTask() {
public void run() {
System.out.println("timer test");
}
};
t.schedule(scanTask, 0, 5000);
CountDownTimer waitTimer;
waitTimer = new CountDownTimer(20000,300) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
t.cancel();
System.out.println("Timer stopped");
}
}.start();
Looper.loop();
}
}
In onCreate I used the following:
new TimerThread().start();
The program now works without any errors, however the only problem now is that there is a noticeable 2-3 second lag when the program loads up before the UI renders to the screen.
I'm not sure why this is happening if the timer function I am using is running on a separate thread, unless I've missed something here...
If you create a handler (or any class you call creates a handler) it needs to be in a Thread that has a Looper on it, and has called Looper.prepare(). Either TimerTask or CountDownTimer is doing that. How to fix it depends on where you want the events to be posted to. If you want them on the UI thread, you'll have to create the handler on the UI thread. If you want them on this thread, then you need to call Looper.prepare and Looper.loop at some point.
The UI thread already has a looper (the framework starts it for you) so its always ok to make handlers there.

Issue calling a custom view method from runnable

I am using a handler to call runnable after a delay of 5 seconds. this then calls a method in a custom view. the problem im having is that the method is being called but the delay is far greater than 5 seconds.
code is as follows.
final Handler h = new Handler();
h.postDelayed(new Runnable()
{
#Override
public void run()
{
buttonArray.get(1).activate();
}
}, 5000);
and the code in the custom view that is being called
public void activate()
{
active = true;
this.animate().alpha(0.4f).setDuration(150);
}
Thanks

Error in derived TimerTask class: `Can't create handler inside thread that has not called Looper.prepare()`

I want to cyclically update an Android Layout. For this purpose I wrote a short class derived from TimerTask.
Unfortunately my code causes an exception and I do not really know, what the problem might be. :(
So maybe anybody could help.
Thanks
Chris
Here's my code:
In the main activity I've got:
private MyLayoutClass m_MyLayout;
...
public void onCreate(Bundle savedInstanceState)
{
...
m_MyLayout = new AdLayout(this);
Timer caretaker = new Timer();
caretaker.schedule(new MyReloadTimerTask(m_MyLayout), 1000, 5000);
...
}
This is my derived TimerTask class:
public class MyReloadTimerTask extends TimerTask
{
private MyLayoutClass m_MyLayout;
public MyReloadTimerTask(MyLayoutClass aLayout)
{
m_MyLayout = aLayout;
}
#Override
public void run()
{
m_MyLayout.doReload();
}
}
The doReload() cannot be executed, I get an exception with this message: Can't create handler inside thread that has not called Looper.prepare()
Timertask runs on a different thread. So you cannot not update/access ui from a background thread.
Probably m_MyLayout.doReload() is updating ui. Use a Handler or runOnUiThread
runOnUiThread(new Runnable() {
#Override
public void run() {
m_MyLayout.doReload()
}
});
Using Handler
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 1000);
// repeat some task every 1 second
}
};
m_handlerTask.run();
To cancel the run
m_handler.removeCallbacks(m_handlerTask);

Can't create handler inside threads that has not called looper?

I want to send a notification after 5 seconds.
I found this code example to do something after 5 seconds, but I just can set a Log.e().
The Notification method is also working. But if I want to call the method setNotification(), I get a RuntimeError after 5 seconds:
Can't create Handler inside Thread that has not called looper.prepare().
I found very much help, but nothing works. So I hope you can help me.
public class Reminder {
Timer timer;
public Reminder(int seconds) {
timer = new Timer();
timer.schedule(new RemindTask(), seconds * 1000);
}
}
class RemindTask extends TimerTask {
public void run() {
todo_list rem = new todo_list();
rem.setNotification("Todo!", false, 1);
}
}
public class todo_list extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
new Reminder(5);
}
public void setNotification(String text, boolean ongoing, int id) {}
}
You need to call rem.setNotification from a thread which will keep running always. One way is to use runonuithread
runonUithread(new Runnable(){
run(){
rem.setNotification("Todo!",false,1);
}
});
You'll get this error when you execute some code that shouldn't be done in another thread than the UI thread. So simple get an activity object and call runOnUiThread(Runnable action) {} on it. Place that code that generates the error in the Runnable.
I hope this helps.

Why is my countdown timer in Android so slow?

I'm trying to make a countdown timer in android for use in a small android app. The app will countdown from some number of seconds to 0, upon which it will do some action. I'm using the coundowntimer supplied by android.os.countdowntimer. Here is my code:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.quizlayout);
new CountDownTimer(30000, 1000) {
TextView tx = (TextView) findViewById(R.id.textView2);
public void onTick(long millisUntilFinished) {
tx.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
tx.setText("done!");
}
}.start();
}
However, this countdown timer is really slow. It takes like 3 real-time seconds for the timer to countdown by one second. I wonder what's going on? The code I have above is more or less copied straight from google (CountDownTimer)
Can anyone help me as per why my timer is so slow, and offer a way to speed it up a bit?
(EDIT): I am running this on an emulator, the intel atom x86. I am emulating an android 2.3.3 environment.
According to Android documentation for countdown timer
The calls to onTick(long) are synchronized to this object so that one call to onTick(long) won't ever occur before the previous callback is complete. This is only relevant when the implementation of onTick(long) takes an amount of time to execute that is significant compared to the countdown interval.
Take a look at this example for countdown timer
Countdown timer example
Alternately you can spawn a new thread and just get that thread to sleep for the interval you want and take actions when it wakes or vice versa.
You can also timertask
use a handler that will post the same runnable . this will remove the need for extra threads :
Handler handler=new Handler();
handler.postRunnable(... , 1000) ;
in the runnable , call the postRunnable again for the same handler (and add a condition for when to stop) .
CountDownTimer is not efficient regardless to ui updating performances. For a flawless ui update, it is better to create a custom countdown. I did my own so here it is. It is flawless on my app.
public abstract class CountDown {
int totalTime = 0;
int tickTime = 0;
Thread thread;
boolean canceled = false;
public CountDown(int totalTime,int tickTime){
this.totalTime = totalTime;
this.tickTime = tickTime;
}
public abstract void onTick();
public abstract void onFinish();
public void start(){
thread = new Thread(new Runnable() {
#Override
public void run() {
// Do in thread
canceled = false;
for (int elapsedTime = 0; elapsedTime < totalTime; elapsedTime += tickTime) {
if(!canceled){
onTick();
try {
thread.sleep(tickTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
if(!canceled){
onFinish();
}
}
});
thread.start();
}
public void cancel(){
canceled = true;
}
}
Remember that every time you have to update your ui, call a runOnUiThread, or else you will have an exception, you are not in a handler and not on ui thread.
Here is how to use it in your code, it is identical to CountDownTimer, so you could just rename lines in your code :
CountDown cDown = new CountDown(10000, 20) {
public void onTick() {
// Do something
}
public void onFinish() {
runOnUiThread(new Runnable() {
#Override
public void run() {
myButton.setImageDrawable(drawable);
}
});
}
};

Categories

Resources