Countdown Timer which shows on the UI with AsyncTask - android

I'm trying to implement a Countdown Timer which shows on the UI,
I thought this was a clean and elegant solution but Logcat throws
AndroidRuntime(3282): java.lang.RuntimeException: An error occured while executing doInBackground()
,
private class UpdateCountdownTask extends AsyncTask<Long, Long, Void> {
#Override
protected Void doInBackground(Long... millisUntilFinished) {
new CountDownTimer(millisUntilFinished[0], 1000) {
#Override
public void onTick(long millisUntilFinished) {
publishProgress(millisUntilFinished);
}
#Override
public void onFinish() {
((TextView) findViewById(R.id.answer)).setText(answer);
}
};
return null;
}
#Override
protected void onProgressUpdate(Long... millisUntilFinished) {
super.onProgressUpdate(millisUntilFinished);
((TextView) findViewById(R.id.timer)).setText(""
+ millisUntilFinished[0] / 1000);
}
}
Still don't fully understand threads. Can anyone tell me what I'm doing wrong?
Thanks.
UPDATE: Very Sorry. I am an absolut incompetent. I had forgotten to call the metod start() on the counter. :P
I finally went for implementing the countdown with the CountDownTimer by itself. Sill don't know if this actually runs on a separate thread or not but it works now.
CountDownTimer myCounter = new CountDownTimer(millisUntilFinished, 1000) {
#Override
public void onTick(long millisUntilFinished) {
((TextView) findViewById(R.id.timer)).setText(""
+ millisUntilFinished / 1000);
System.out.println("I am ticking");
}
#Override
public void onFinish() {
}
};
myCounter.start();

I think the problem is the onFinish() method inside CountDownTimer. Here you're modifiying the UI thread, and you cannot do this from a background thread. So you have to put ((TextView) findViewById(R.id.answer)).setText(answer); inside onPostExecute() method. I mean:
protected void onPostExecute(String result) {
super.onPostExecute(result);
((TextView) findViewById(R.id.answer)).setText(answer);
}
I hope this works.

You will not be able to connect the UI when doing somthing in background.In my opinion what you want is possible if you use a thread.This will make your work much more easier.A small piece of code is shown below.I hope this may help you.I am trying to set an image instead you can settext.Here i had done using a thread and a handler.Its impossible to connect the UI inside the thread.In assynctask When you are doing something in background you are compleatly inside the thread.Thats why you are getting a error here.Otherwinse you can do it in Postexecute()
Thread animator = new Thread() {
public void run() {
int i = 0;
try {
sleep(2000);
while (i < 4) {
sleep(50);
handler.sendMessage(handler.obtainMessage(i));
i++;
}
} catch (Exception e) {
}
}
};
animator.start();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0) {
animatedimage.setImageResource(R.drawable.sub1);
} else if (msg.what == 1) {
animatedimage.setImageResource(R.drawable.sub2);
} else if (msg.what == 2) {
animatedimage.setImageResource(R.drawable.sub3);
} else if (msg.what == 3) {
animatedimage.setImageResource(R.drawable.sub4);
}
}
};

Have you consider using Handler to update UI every second?
checkout http://developer.android.com/resources/articles/timed-ui-updates.html

Related

Running backgound thread every X seconds (Android Studio)

I have a code that plays 5 sounds with 1 second delay between the sounds and I want this part of code to be executed every 5 seconds (so it will run in a row so far as a boolean variable is true, and when it becomes false the tread run stopped - I have a button to both start and stop this executions). Everything works perfectly, but the issue is that I can't get rid of the 5 seconds delay in the first time I click the button, so when I first click, the sounds beggins only after 5 seconds. How can I make it start right away and only after the first time start taking the delays?
Here is the button onClick code:
public void clickHandlerStartTempo(final View view) {
if (!tempoOn) {
Toast toast = Toast.makeText(getApplicationContext(), "Start Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = true;
final Handler handler = new Handler();
final int delay = 5000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
if (tempoOn) {
runCode(view);
handler.postDelayed(this, delay);
}
}
}, delay);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "Stop Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = false;
}
}
And here is the runCode method:
public void runCode(View view) {
Runnable runnable = new Runnable() {
#Override
public void run() {
playSound(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 4; i++) {
if (tempoOn) {
playSound(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
return;
}
}
}
};
Thread thread = new Thread(runnable);
Log.i(TAG, "runCode: Thread id = " + thread.getId());
thread.start();
}
I'm new to android development and any help would be very much appreciated.
Thanks.
First you need to playsound without thread after that you will execute your reaming 5 second logic stop thread after 4 count.
public void onStartPress(){
playSound();
someMethod();
}
public void someMethod(){
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
playSound();
someMethod();
}
},1000);
}
Don't use actual Threads unless you really want to do something off the Ui thread. Most of the time you do want to keep things on the Ui thread.
For simple repeating tasks, you can easily repurpose the CountDownTimer class. Often with an (almost) infinite run time or Long.MAX_VALUE (292 million years). The fist onTick happens immediately after starting.
private CountDownTimer mTimer;
private void start() {
if (mTimer == null) {
mTimer = new CountDownTimer(Long.MAX_VALUE, 5000) {
#Override
public void onTick(long millisUntilFinished) {
// start a beeping countdown
new CountDownTimer(5000, 1000) {
private int state = 1;
#Override
public void onTick(long millisUntilFinished) {
playSound(state);
state = state + 1 % 2;
}
#Override
public void onFinish() {
playSound(0);
}
}.start();
}
#Override
public void onFinish() { /* ignore, never happens */ }
};
mTimer.start();
}
}
private void stop() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}

CountDownTimer in EditText lag in the last second

I would like to set an EditText with a timer thanks to CountDownTimer.
My EditText write second by second the number 3 and 2 but for the 1 there is a lag (it take 1,5 to 2 seconds).
Maybe I do it wrong.
This is my code :
CountDownTimer mCountDownTimer = new CountDownTimer(4000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
txt_timer.setText(String.valueOf(millisUntilFinished / 1000));
}
#Override
public void onFinish() {
txt_timer.setText("GO");
}
};
mCountDownTimer.start();
That is because the UI thread is doing too much work. Try running a new thread on the UI thread itself:
runOnUiThread(new Runnable() {
public void run()
{
//Insert your code
}
});
}
Let me know if you can;t get this to work!
The memory in the device cause the problem. I found a solution running a new thread.
I have to declare int i=4; before and use this code :
new Thread() {
public void run() {
while (i-- > 1) {
try {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
txt_timer.setText(String.valueOf(i));
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
txt_timer.setText("GO");
}
}.start();

execute a function within a timer

I ve got this function here:
public void stoprecording()
{
this.recorder.stop();
this.recorder.reset();
this.recorder.release();
}
which stops the recoridng. This is within the class Audio. I also got this function here:
public void recordtimer(final int timer)
{
/*First Part with timer*/
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
CountDownTimer countDowntimer = new CountDownTimer(timer, 100000)
{
public void onTick(long millisUntilFinished) {}
public void onFinish() {
this.stoprecording();
}
};countDowntimer.start();
}
});
thread.start();
this.stoprecording();
}
also within the class Audio. I canĀ“t execute this.stoprecording(); because the class CountDownTimer doesn t have this function. How can I execute this function?
Looking at your code it seems there is no need to call stoprecording() from this, since it does not belong to CountDownTimer class you have defined.
Just call it like
public void onFinish() {
stoprecording();
}
or if you want to definitely use this, follow the #gary111 suggestion thus doing
public void onFinish() {
YourClass.this.stoprecording();
}

Android Timer update UI between multiple tasks

I have tried multiple ways to have a single persistent timer update the ui in multiple activities, and nothing seems to work. I have tried an AsyncTask, a Handler, and a CountDownTimer. The code below does not execute the first Log.i statement.... Is there a better way to start the timer (which must be called from another class) in Main (which is the only persistent class)?
public static void MainLawTimer()
{
MainActivity.lawTimer = new CountDownTimer(MainActivity.timeLeft, 1000)
{
public void onTick(long millisUntilFinished)
{
Log.i("aaa","Timer running. Time left: "+MainActivity.timeLeft);
MainActivity.timeLeft--;
if(MainActivity.timeLeft<=0)
{
//do stuff
}
else
{
//call method in another class
}
}
public void onFinish()
{ }
}.start();
}
To clarify my problem:
When I run the code the Log.i("aaa","Timer running") statement is never shown in the log, and the CountDownTimer never seems to start. MainLawTimer is called from another class only (not within the same class.
For CountDownTimer
http://developer.android.com/reference/android/os/CountDownTimer.html
You can use a Handler
Handler m_handler;
Runnable m_handlerTask ;
int timeleft=100;
m_handler = new Handler();
#Override
public void run() {
if(timeleft>=0)
{
// do stuff
Log.i("timeleft",""+timeleft);
timeleft--;
}
else
{
m_handler.removeCallbacks(m_handlerTask); // cancel run
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
Timer
int timeleft=100;
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
Log.i("timeleft",""+timeleft);
//update ui
}
});
if(timeleft>==0)
{
timeleft--;
}
else
{
_t.cancel();
}
}
}, 1000, 1000 );
You can use a AsyncTask or a Timer or a CountDownTimer.
Thank you all for your help, I discovered the error in my code... timeLeft was in seconds rather then milliseconds. Since timeLeft was under 1000 (the wait period) the timer never started.

How to late thread run in android

In my code I have a thread. You can see the code of thread,
public class MainAsyncHome extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
return null;
}
#Override
protected void onPostExecute(String xml) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
I run this thread in my main activity onCreate method as following way
new MainAsyncHome().execute(null);
But I want to give time out for this thread. It means when main activity run I want late to run this thread. I know it can do using sleep method. But How I can late for running this thread just like that way.
I'm stuck with this problem.
pls give me answer. Thanks
Use Handler class, and define Runnable handleMyAsyncTask that will contain code executed after 3000 msec delay:
mHandler.postDelayed(MainAsyncHome, 1000*3); //Delay of three seconds
The answer is taken from here.
To put it in the code:
private final static int INTERVAL = 1000 * 3; //3 seconds
Handler m_handler;
Runnable MainAsyncHome = new Runnable()
{
#Override
public void run() {
doSomething();
m_handler.postDelayed(MainAsyncHome, INTERVAL);
}
}
void startRepeatingTask()
{
MainAsyncHome.run();
}
void stopRepeatingTask()
{
mHandler.removeCallback(MainAsyncHome);
}
Hope it works.
I normally use CountDownTimer, suppose a 3 seconds of delay:
CountDownTimer timer = new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//do things, start your Task
//remember we are still in the main thread!
}
}.start();
Get more info at:
http://developer.android.com/reference/android/os/CountDownTimer.html
Use a CountDownTimer like this.
Start your timer in onCreate.
CountDownTimer timer=new CountDownTimer(Delay,TimeIntervalToCallOnTick) {
#Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
//start your asynctask
}
};

Categories

Resources