Hey i recently got into android and made my first app which was meant to start a run down timer of 60 seconds when the user pressed start button. The application sets the content view fine and displays 60 but when i click the start button it displays 59 successfully and then the app crashes.Here's the code(it has only one activity)
public class test1activity extends Activity
{
Thread countdown;
long f, pa, jee;
TextView ytvp;
String s;
TextView uyti;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ytvp = (TextView) findViewById(R.id.textView2);
uyti = (TextView) findViewById(R.id.tv2);
countdown = new Thread() {
public void run() {
jee = (System.currentTimeMillis()) / 1000;
while ((((System.currentTimeMillis()) / 1000) - jee) < 60)
{
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
f = ((System.currentTimeMillis()) / 1000) - jee;
pa = 60 - f;
s = String.valueOf(pa);
ytvp.setText(s);
}
}
}
};
}
public void whenclickstart(View view) {
countdown.start();
}
You cannot set UI elements from inside another thread(Non UI thread). So you cannot use this below line.
ytvp.setText(s);
Try something like this, you dont need threading for what you are trying to do
new CountDownTimer(60000, 1000) {
public void onTick(long millisUntilFinished) {
ytvp.setText("" + millisUntilFinished/1000);
}
public void onFinish() {
ytvp.setText(""+0);
}
}.start();
If you do not want to use countdowntimer replace setText with
runOnUiThread(new Runnable() {
public void run() {
ytvp.setText(s);
}
});
Related
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;
}
}
I have implemented one counter and onFinish() of first counter,I started second counter but the first counter not able to finish.Text "Bye Guyz" remain for some time so how to finish the text.
Please help me.
Thanks in advance.!!!
Code :-
counter= new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
if (count == 0) {
tv.setText("First counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Guyz");
}
}
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
else if(flag) {
counter1 = new CountDownTimer(9000, 1000) {
public void onTick(long millisUntilFinished) {
flag = false;
tv.setText("Second counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Girls");
count = 0;
}
public void onFinish() {
tv2.setVisibility(View.VISIBLE);
tv2.setText("Bye Girls");
count = 0;
}
}.start();
Did you "debug" the code to be sure the code is arriving to counter1 = new CountDownTimer(9000, 1000)?
Are you sure when the first counter arrives to onFinish() the flag variable is true?
Why do you call counter.cancel() in onFinish() when obviously the counter is already over?
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
If you say your tv2 displays "Bye Guyz" it means that your flag is set to false, so the "else if" part is not being executed. onFinish() is only executed once, so you need to make sure the flag is set for true to start the second counter.
Also you shouldn't cancel your counter in onFinish() because it's already finished.
Here is my alternative is as follows
Create the custom Counterextending Thread
class Counter extends Thread {
private long timeOne, timeTwo;
private OnCounterFinishedListener mCounterFinishedListener;
private Thread t;
Activity activity = null;
Counter(Context context){
t = new Thread(this);
activity = (Activity)context;
}
#Override
public void run() {
try {
sleep(timeOne);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.firstCounterFinished();
}
});
sleep(timeTwo);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.secondCounterFinished();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void setTimes(long timeOne, long timeTwo){
this.timeOne = timeOne;
this.timeTwo = timeTwo;
}
public void start(OnCounterFinishedListener listener){
mCounterFinishedListener = listener;
t.start();
}
interface OnCounterFinishedListener{
void firstCounterFinished();
void secondCounterFinished();
}
}
Then inside your main thread you can start this counter as
final Counter counter = new Counter(this);
counter.setTimes(5000, 5000);
counter.start(new Counter.OnCounterFinishedListener() {
#Override
public void firstCounterFinished() {
// Update your first TextView
}
#Override
public void secondCounterFinished() {
// Update your second TextView
}
});
i am trying to implement a countdown timer that starts from the number that the user inputs in the EditText. When i am running my program with the emulator, i realise that something goes wrong inside the countdown timer block since it does not enter inside this block.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText countDownTxt = (EditText) findViewById(R.id.editText2);
final EditText intervalTxt = (EditText) findViewById(R.id.editText1);
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
int interval = Integer.parseInt(intervalTxt.getText().toString());
Log.d("buttonpressed", "interval countdown equals " + interval);
new CountDownTimer(Integer.parseInt(intervalTxt.getText().toString()), 1000) {
public void onTick(final long millisUntilFinished) {
Log.d("counttimer1", "enter");
runOnUiThread(new Runnable() {
#Override
public void run() {
countDownTxt.setText("" + millisUntilFinished / 1000);
}
});
countDownTxt.setText(""+ millisUntilFinished / 1000);
}
public void onFinish() {
countDownTxt.setText("done!");
}
}.start();
}
}
);
Any suggestions on solving this problemt ?
try using this
long timeVal = Long.parseLong(intervalTxt.getText().toString());
new CountDownTimer(timeVal, 1000) {
}
If you want the entered number by user present seconds, you should have like:
int time = Integer.parseInt(intervalTxt.getText().toString()) * 1000;
new CountDownTimer(time, 1000) {
...
I want to show timer, with every second. After 20 seconds I want that activity to call itself.
But when I don't display the timer it waits for 20 seconds as I wish to do but as soon as I implement code to display timer it just starts and suddenly stops suddenly.
Here is my code. Please help me out.
public class MainActivity extends Activity {
public int time=20;
Button end;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread timerdisp = new Thread(){
TextView tv = (TextView) findViewById(R.id.timer);
public void run(){
try{
sleep(1000); // sleep for 1 seconds
tv.setText(String.valueOf(time));
time-=1;
if(time==0){
startActivity(new Intent(MainActivity.this,MainActivity.class));
}
run();
}
catch (InterruptedException e){
e.printStackTrace();
}
}
};
timerdisp.start();
);
}
Android provides a better facility of CountDownTimer, may be you should use that. As it provides many inbuilt methods and runs on background thread by default.
You can use onFinish() method to execute your call to the activity.
Here is an example of the same.
Try Below Code:
private long ms=0;
private long splashTime=2000;
private boolean splashActive = true;
private boolean paused=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Hides the titlebar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
Thread mythread = new Thread() {
public void run() {
try {
while (splashActive && ms < splashTime) {
if(!paused)
ms=ms+100;
sleep(100);
}
} catch(Exception e) {}
finally {
Intent intent = new Intent(Splash.this, Home.class);
startActivity(intent);
}
}
};
mythread.start();
}
and you can try this also
public class MainActivity extends Activity {
private CountDownTimer countDownTimer;
public TextView text;
private final long startTime = 20 * 1000;
private final long interval = 1 * 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.textView1);
countDownTimer = new MyCountDownTimer(startTime, interval);
text.setText(String.valueOf(startTime / 1000));
countDownTimer.start();
}
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
Intent intent = new Intent();
intent.setClass(getApplicationContext(),xxxx.class);
startActivity(intent);
}
#Override
public void onTick(long millisUntilFinished) {
text.setText("" + millisUntilFinished / 1000);
}
}
}
Use runOnUiThread
This acts as a normal Thread and will not allow your UI to sleep.
and the system will not hang.
or you can also use AsyncTask. I will prefer you using AsyncTask.
Use below code to call the function for every 20 seconds.
private Timer timer;
TimerTask refresher;
timer = new Timer();
refresher = new TimerTask() {
public void run() {
// your code to call every 20 seconds.
};
};
// first event immediately, following after 20 seconds each
timer.scheduleAtFixedRate(refresher, 0,1000*20);
Use below lines to show the time :
package com.example.test;
public class MainActivity extends Activity {
private Long startTime;
public native String getLastShotName();
public native String colorNormal();
public native String flipImage();
public native String forceInvertColor();
public native String getLastTitle();
public native String myMethod();
boolean mbFlip = false;
private Timer timer;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TimerTask refresher;
startTime = System.currentTimeMillis();
handler.removeCallbacks(updateTimer);
handler.postDelayed(updateTimer, 1000);
}
#Override
protected void onResume() {
super.onResume();
handler.postDelayed(updateTimer, 1000);
}
private Runnable updateTimer = new Runnable() {
public void run() {
final TextView time = (TextView) findViewById(R.id.textView1);
Long spentTime = System.currentTimeMillis() - startTime;
Long minius = (spentTime/1000)/60;
Long seconds = (spentTime/1000) % 60;
time.setText(minius+":"+seconds);
handler.postDelayed(this, 1000);
}
};
}
I want to do countdown timer with pause and restart.Now i am displaying countdown timer By implenting ontick() and onfinish().please help me out.HEre is th code for countdown timer
final CountDownTimer Counter1 = new CountDownTimer(timervalue1 , 1000)
{
public void onTick(long millisUntilFinished)
{
System.out.println("onTick method!"(String.valueOf(millisUntilFinished/1000)));long s1=millisUntilFinished;
}
public void onFinish()
{
System.out.println("Finished!");
}
}
in onTick method..save the milliseconds left
long s1=millisUntilFinished;
when you want to pause the timer use..
Counter.cancel();
when you want to resume create a new countdowntimer with left milliseconds..
timervalue=s1
counter= new Counter1();
counter.start();
See this link
I would add something to the onTick handler to save the progress of the timer in your class (number of milliseconds left).
In the onPause() method for the activity call cancel() on the timer.
In the onResume() method for the activity create a new timer with the saved number of milliseconds left.
Refer the below links
LINK
LINK
My first answer on stackOverFlow, hope it should help :) ...
This is how I solved the problem, control timer from Fragment, Bottomsheet, Service, Dialog as per your requirement, keep a static boolean variable to control.
declare in your Activity:
long presetTime, runningTime;
Handler mHandler =new Handler();
Runnable countDownRunnable;
Toast toastObj;
public static boolean shouldTimerRun = true;
TextView counterTv;
In onCreate:
presetTime =60000L;
runningTime= presetTime;
//setting up Timer
countDownRunnable=new Runnable() {
#Override
public void run() {
if (shouldTimerRun) //if false, it runs but skips counting
{
counterTv.setText(simplifyTimeInMillis(runningTime));
if (runningTime==0) {
deployToast("Task Completed"); //show toast on task completion
}
runningTime -= 1000;
presetTime = runningTime; //to resume the timer from last position
}
mHandler.postDelayed(countDownRunnable,1000); //simulating on-tick
}
};
mHandler.post(countDownRunnable); // Start our CountdownTimer
Now, whenever you want to pause the timer change the value of shouldTimerRun false and to resume make it true.
#Override
public void onResume() {
super.onResume();
shouldTimerRun=true;
}
#Override
public void onPause() {
super.onPause();
shouldTimerRun=false;
deployToast("Timer is paused !!");
}
Helping methods: (can be skipped)
public static String simplifyTimeInMillis(long time) {
String result="";
long difference = time;
long secondsInMilli = 1000;
long minutesInMilli = secondsInMilli * 60;
long hoursInMilli = minutesInMilli * 60;
if (difference<1000){
return "0";
}
if (difference>=3600000) {
result = result + String.valueOf(difference / hoursInMilli) + "hr ";
difference = difference % hoursInMilli;
}
if (difference>=60000) {
result = result + String.valueOf(difference / minutesInMilli) + "m ";
difference = difference % minutesInMilli;
}
if (difference>=1000){
result = result + String.valueOf(difference / secondsInMilli) + "s";
}
return result;
}
public void deployToast(String msg){
if (toastObj!=null)
toastObj.cancel();
toastObj = Toast.makeText(mContext,msg,Toast.LENGTH_SHORT);
toastObj.show();
}
I'm using two private vars in this case:
private long startPauseTime;
private long pauseTime = 0L;
public void pause() {
startPauseTime = System.currentTimeMillis();
}
public void resumen(){
pauseTime += System.currentTimeMillis() - startPauseTime;
}
I am afraid that it is not possible to pause or stop CountDownTimer and pausing or stopping in onTick has no effect whatsoever user TimerTask instead.
Set up the TimerTask
class UpdateTimeTask extends TimerTask {
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timeLabel.setText(String.format("%d:%02d", minutes, seconds));
}
}
if(startTime == 0L) {
startTime = evt.getWhen();
timer = new Timer();
timer.schedule(new UpdateTimeTask(), 100, 200);
}
You can add event listener's like this..
private Handler mHandler = new Handler();
...
OnClickListener mStartListener = new OnClickListener() {
public void onClick(View v) {
if (mStartTime == 0L) {
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
};
OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
};
For more refer to Android Documentation.
//This timer will show min:sec format and can be paused and resumed
public class YourClass extends Activity{
TextView timer;
CountDownTimer ct;
long c = 150000; // 2min:30sec Timer
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.YourXmlLayout);
timer = (TextView)findViewById(R.id.Yourtimer)
startTimer(); // it will start the timer
}
public void startTimer(){
ct = new CountDownTimer(c,1000) {
#Override
public void onTick(long millisUntilFinished) {
// Code to show the timer in min:sec form
// Here timer is a TextView so
timer.setText(""+String.format("%02d:%02d",millisUntilFinished/60000,(millisUntilFinished/1000)%60));
c = millisUntilFinished; // it will store millisLeft
}
#Override
public void onFinish() {
//your code here
}
};
ct.start();
}
/*===========================================================
*after creating this you can pause this by typing ct.cancel()
*and resume by typing startTimer()*/
public class MainActivity extends AppCompatActivity {
TextView textView;
CountDownTimer ctimer;
boolean runCountDown;
private long leftTime;
private static final long MILL_IN_FUTURE = 6000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text_view);
textView.setText("Click to start");
textView.setOnClickListener(this::clickStartAndPauseAndResume);
leftTime = MILL_IN_FUTURE;
}
public void clickStartAndPauseAndResume(View view) {
if (!runCountDown) {
long time = (leftTime == 0 || leftTime == MILL_IN_FUTURE) ? MILL_IN_FUTURE : leftTime;
ctimer = new CountDownTimer(time, 1) {
#Override
public void onTick(long l) {
leftTime = l;
textView.setText(l + "ms");
}
#Override
public void onFinish() {
textView.setText("Done");
leftTime = 0;
runCountDown = false;
textView.postDelayed(new Runnable() {
#Override
public void run() {
textView.setText("Click to start");
}
}, 1000);
}
}.start();
runCountDown = true;
} else {
ctimer.cancel();
textView.setText(textView.getText() + "\n Click to resume");
runCountDown = false;
}
}
}
A nice and simple way to create a Pause/Resume for your CountDownTimer is to create a separate method for your timer start, pause and resume as follows:
public void timerStart(long timeLengthMilli) {
timer = new CountDownTimer(timeLengthMilli, 1000) {
#Override
public void onTick(long milliTillFinish) {
milliLeft=milliTillFinish;
min = (milliTillFinish/(1000*60));
sec = ((milliTillFinish/1000)-min*60);
clock.setText(Long.toString(min)+":"+Long.toString(sec));
Log.i("Tick", "Tock");
}
The timerStart has a long parameter as it will be reused by the resume() method below. Remember to store your milliTillFinished (above as milliLeft) so that you may send it through in your resume() method. Pause and resume methods below respectively:
public void timerPause() {
timer.cancel();
}
private void timerResume() {
Log.i("min", Long.toString(min));
Log.i("Sec", Long.toString(sec));
timerStart(milliLeft);
}
Here is the code for the button FYI:
startPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(startPause.getText().equals("Start")){
Log.i("Started", startPause.getText().toString());
startPause.setText("Pause");
timerStart(15*1000);
} else if (startPause.getText().equals("Pause")){
Log.i("Paused", startPause.getText().toString());
startPause.setText("Resume");
timerPause();
} else if (startPause.getText().equals("Resume")){
startPause.setText("Pause");
timerResume();
}