How do you make a StopWatch in android using the chronometer? - java

I'm trying to make a stopwatch for android as part of a score board app the problem is I'm not sure how to use the chronometer to start, stop, then resume from the time it stopped at or reset to 0. The only problem is that I'm not sure how to use the setBase() and getBase() methods properly.
public class MainActivity extends Activity {
int homecount, awaycount, minutes, seconds;
TextView home, away;
Button stop, start, reset, addhome, subhome, addaway, subaway;
TextView time;
public boolean running;
Chronometer MyChronometer;
long startTime, stopTime;
running = false;
stopTime = 0;
MyChronometer = (Chronometer) findViewById(R.id.timer);
start.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((Chronometer) findViewById(R.id.timer)).start();
startTime=System.currentTimeMillis();
running = true;
}
});
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((Chronometer) findViewById(R.id.timer)).stop();
stopTime=System.currentTimeMillis();
running = false;
}
});
reset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});

You have the variable MyChronometer. Use that every time you want to start or stop.
Also, right after initialization you should run MyChronometer.setBase(SystemClock.elapsedRealtime());. For more details read the documentation: Chronometer and SystemClock.

Related

I am trying to create a Stopwatch app and am having problems adding a lap button and continue button that work

As the title suggests I am trying to create a Stopwatch app and am having problems adding a lap button and continue button that work. I have added the buttons to the layout.xml file but am having trouble with the java code that gets them to function.
I need to display the "stopped/paused" time when the lap button is clicked, the internal clock needs to keep running however and no longer be displayed, or the stopped/paused time needs to be shown in a new display whichever is easier to accomplish. When the lap timer is clicked subsequently it should display the current time (internal clock)
I need the continue button to then resume the paused/stopped time.
Could somebody help me with the code, I'm relatively inexperienced in java, so any help would be appreciated
here's the code of my main java file:
package com.hfad.stopwatch;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.TextView;
public class StopwatchActivity extends Activity implements View.OnClickListener {
Button Continue;
Button lapChrono;
Chronometer chrono;
long time =0;
//Number of seconds displayed on the stopwatch.
private int seconds = 0;
//Is the stopwatch running?
private boolean running;
private boolean wasRunning;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stopwatch);
Continue=(Button)findViewById(R.id.Continue_button);
lapChrono=(Button)findViewById(R.id.lap_button);
lapChrono.setOnClickListener(this);
Continue.setOnClickListener(this);
chrono=(Chronometer)findViewById(R.id.chronometer);
if (savedInstanceState != null) {
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
runTimer();
}
#Override
protected void onPause() {
super.onPause();
wasRunning = running;
running = false;
}
#Override
protected void onResume() {
super.onResume();
if (wasRunning) {
running = true;
}
}
public void onClick(View arg0) {
switch (arg0.getId()){
case R.id.Continue_button:
chrono.setBase(SystemClock.elapsedRealtime()+time);
chrono.setBase(time);
break;
case R.id.lap_button:
time = chrono.getBase()+SystemClock.elapsedRealtime();
break;
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("seconds", seconds);
savedInstanceState.putBoolean("running", running);
savedInstanceState.putBoolean("wasRunning", wasRunning);
}
//Start the stopwatch running when the Start button is clicked.
public void onClickStart(View view) {
running = true;
}
//Stop the stopwatch running when the Stop button is clicked.
public void onClickStop(View view) {
running = false;
}
//Reset the stopwatch when the Reset button is clicked.
public void onClickReset(View view) {
running = false;
seconds = 0;
}
//Sets the number of seconds on the timer.
private void runTimer() {
final TextView timeView = (TextView)findViewById(R.id.time_view);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds/3600;
int minutes = (seconds%3600)/60;
int secs = seconds%60;
String time = String.format("%d:%02d:%02d",
hours, minutes, secs);
timeView.setText(time);
if (running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
I am just having problems getting things to run smoothly as I'm not too fluent in my Java, apologies, that is why help is needed. The logic isn't quite there. The continue button doesn't function properly nor does the lap, I'm needing it to function as described above.
chrono object is not initialized and used in onClick(). Hence NPE occurs.
Try to initialise it in onCreate().

How can I tell MyCountDownTimer to quit when the activity is not the current activity?

The project i'm working on is an quiz with a timer on each question. for 30 seconds. I noticed that if you finish the test before the timer runs out, the timer doesn't stop running. So if you head on to another test, the notification that you haven't finished the test will popup and override the current activity. I tried using the cancel() method, but i'm sure I misplaced it.
Here is a snippet of the MyCountDownTimer Class
public MyCountDownTimer(TextView textCounter, long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.textCounter = textCounter;
}
#Override
public void onTick(long millisUntilFinished) {
textCounter.setText(String.valueOf(millisUntilFinished / 1000));
}
#Override
public void onFinish() {
Intent retryIntent = new Intent(textCounter.getContext(), Retry.class);
if (textCounter.getContext() instanceof Test1){
whichTest = 1;
retryIntent.putExtra("whichTest",whichTest);
}
textCounter.getContext().startActivity(retryIntent);
}
This is a snippet of the Activity that implements the method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_page);
textCounter = ((TextView)findViewById(R.id.textCounter));
myCountDownTimer = new MyCountDownTimer(textCounter, 29000, 1000);
myCountDownTimer.start();
textCounter.setText("");
myCountDownTimer.onTick(29000);
}#Override
public void onClick(View v) {
if (questionIndex == questions7.length){
myCountDownTimer.cancel();
Intent intent1 = new Intent(Test1.this, UsersAnswers1.class);
intent1.putExtra("usersAnswers1", usersAnswers1);
intent1.putExtra("isATOF1", isATOF1);
intent1.putExtra("score1S", score1S);
startActivity(intent1);
}
}
Override onStop method of your activity and use code like
#Override
protected void onStop() {
myCountDownTimer.cancel();
super.onStop();
}
Hence whenever your activity goes in background it will cancel any timer associated with current activity.

when restart CountDownTimer, it finish work

I want to stop CountDownTimer and to restart it, with time when it stopped. I have this code in class CountDownTimer
public class MyDownTimer extends CountDownTimer{
long mills;
public MyDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.mills=millisInFuture;
}
#Override
public void onFinish() {
GameScreen.showWindow("Time is over","Sorry, time is Over, you lose");
}
#Override
public void onTick(long millisUntilFinished) {
mills=millisUntilFinished/1000;
GameManager.time= millisUntilFinished/1000;
}
}
and Dialog class, he must to showing, when user click in button 'pause'.
Dialog code, as you can see, i start new CountDownTimer in this code
public static void showWindowPause(final MyDownTimer dTime){
final Dialog wdialog= new Dialog(context);
wdialog.setContentView(R.layout.dialog_window);
wdialog.setTitle("title");
TextView text=(TextView)wdialog.findViewById(R.id.txtFirstWord);
text.setText("mainText");
Button dialogButton=(Button)wdialog.findViewById(R.id.button1);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
wdialog.dismiss();
dTime.start();
}
});
wdialog.show();
}
and method, where I stoping CountDownTimer and show Dialog window.
long stime =dTime.mills;
dTime.cancel();
dTime=null;
dTime= new MyDownTimer(stime,1000);
GameScreen.showWindowPause(dTime);
when i click button in Dialog window, i see new Dialog, which created in method
MyDownTimer.onFinish()
But if I change line
long stime =dTime.mills;
on
long stime =5000;
CountDownTimer restarts,and all normal.
where i made mistake?
Your question is really confusing , but I THINK I found something that doesn't make sense.
public void onTick(long millisUntilFinished) {
mills=millisUntilFinished/1000;
GameManager.time= millisUntilFinished/1000;
}
I think it should be
mills=millisUntilFinished - 1000;
edit: If you are actually converting millseconds to seconds, then you'll need to do
long stime =dTime.mills*1000;

How to restore to exact activity after coming from Paused or Resumed state in android

I have two simple activities MainActivity and ThreadActivity. I call ThreadActivity from MainActivity.
The code ofMainActivity:
public class MainActivity extends Activity {
private Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn2);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ThreadActivity.class);
startActivity(intent);
}
});
}
}
And the code of ThreadActivity:
public class ThreadActivity extends Activity{
private Thread myThread=null;
Button btn;
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
void runThread(){
myThread = new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
Log.d("Thread", "I am running " + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
};
myThread.start();
}
}
When I start ThreadActivity I run a simple thread and change button text.
My Problem
When I loose focus from application, i.e when application becomes partially visible, and I come back I am redirected to ThreadActivity and the thread is still running.
When I leave application running and open a new application, and then come back, I am again redirected to ThreadActivity.
The problem is when I press back button, I am being redirected to first activity MainActivity. But instead when back button is being pressed I want my application to exit. In a few words MainActivity should not exist in the stack.
I tried setting android:noHistory="true" for MainActivity but I could not keep the behavior explained in bullet points working. I mean when I pause the application and restore it back, it redirected me to MainActivity instead of ThreadActivity.
Just call finish() when starting the ThreadActivity:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ThreadActivity.class);
startActivity(intent);
finish();
}
});
BUT there is a problem with your app. Use a Timer to set the text of the Button! By using a Thread like you do you are creating a memory leak and that is very bad. Try this:
private int i = 0;
private Timer timer;
private final TimerTask timerTask = new TimerTask() {
#Override
public void run() {
btn.post(new Runnable() {
#Override
public void run() {
btn.setText("#" + i++);
}
});
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer = new Timer();
timer.schedule(timerTask, 300, 300);
}
});
}
#Override
public void onPause() {
super.onPause();
if(timer != null) {
timer.cancel();
}
}
From your comments to other peoples' answers, it seems like you want the ThreadActivity to always be resumed instead of the MainActivity when your thread is running.
Do the thread in a Service - the service will mean your application's VM is likely to be kept alive longer. An app with no foreground activities can be killed off quite quickly (even if it has background threads running).
You need to persist that the thread is running, and the progress (if, in the real code that is applicable). Currently you could persist the value of i in your while loop.
Your application's default launcher activity (MainActivity) will launch when you click on it from your launcher. Check if the persisted value has been set, and act as though the user started the ThreadActivity in onCreate, if you finish() in onCreate, the user won't see any UI from the MainActivity
Depending on what you're actually trying to do, you might be able to resume the thread depending on the progress persisted - in this example, you could start from the persisted value of i (instead of 0).
What I had to is set android:noHistory="true" for MainActivity and in the ThreadActivity I had to add the solution mention by #NeTeInStEiN in this quesiotn
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}

Pass the name of button clicked to different class in Android

I am new to android (and not so hot with it, but trying to learn).
I am creating an application that has a number of various buttons that start countdown timers when they are clicked.
On the activity that has these buttons the following code is used to start the timer:
//Button 1 Start On Click
final CountDown buttonOneTimer = new CountDown(15000,1000);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonOneTimer.start();
}
});
//Button 2 Start On Click
final CountDown buttonTwoTimer = new CountDown(15000,1000);
buttonTwo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonTwoTimer.start();
}
});
my CountDown class looks like this:
public class CountDown extends CountDownTimer {
public CountDown (long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
System.out.println("Timer Completed.");
****NAMEOFTHEBUTTONCLICKED****.setText("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished) {
****NAMEOFTHEBUTTONCLICKED****.setText((millisUntilFinished/1000)+"");
System.out.println("Timer : " + (millisUntilFinished/1000));
}
}
I am trying to get the name of the button pressed into the class so I can set the text on the button to countdown.
I'm sure I am doing all sorts of things wrong or there may be better ways to do it - so if you see areas where I could improve - feel free to critique me!
I read over the tutorial here however it has an 'inner class' (I believe that is what it is called?) inside the current class. A friend of mine said that's very rarely done and to just create a separate class such as CountDown. If I do it the same way as in the tutorial I can get the timer to work (by hardcoding the buttons name where it says *NAMEOFTHEBUTTONCLICKED* above, which means it only works for that button) - but I still need to figure out how to pass that class the buttons name so I don't have to write a separate class for each timer.
Would that be done through Extras? I have had a hard time finding any more info to my specific issue. Any help is appreciated!!
Try passing off the button instance to the Timer:
public class CountDown extends CountDownTimer {
Button button;
public CountDown (long millisInFuture, long countDownInterval, Button button) {
super(millisInFuture, countDownInterval);
this.button = button;
}
#Override
public void onFinish() {
System.out.println("Timer Completed.");
button.setText("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished) {
button.setText((millisUntilFinished/1000)+"");
System.out.println("Timer : " + (millisUntilFinished/1000));
}
}
Then call like this:
//Button 1 Start On Click
final CountDown buttonOneTimer = new CountDown(15000,1000,buttonOne);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonOneTimer.start();
}
});

Categories

Resources