android - start an activity onTouch - java

In my app I have a countdown which counts from five to one. At the moment, the counter starts as soon as the activity is started. What I want is to stay at 5 seconds and wait to count down until the screen is touched. So the countdown timer should be started which a touch event.
public class MainActivity extends Activity implements OnGestureListener {
private static final String FORMAT = "%02d:%02d";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
new CountDownTimer(5000, 10) {
public void onTick(long millisUntilFinished) {
text.setText("" + String.format("%02d:%03d",
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)),
TimeUnit.MILLISECONDS.toMillis(millisUntilFinished) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished))
));
if (animationRunning) {
cancel();
}
}
public void onFinish() {
text.setText("done!");
}
}.start();
}
#Override
public boolean onTouchEvent(MotionEvent touchevent) {
}
}

Place your count down timer inside onTouch like below
public class MainActivity extends Activity implements OnGestureListener {
private static final String FORMAT = "%02d:%02d";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
}
#Override
public boolean onTouchEvent(MotionEvent touchevent) {
new CountDownTimer(5000, 10) {
public void onTick(long millisUntilFinished) {
text.setText("" + String.format("%02d:%03d",
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)),
TimeUnit.MILLISECONDS.toMillis(millisUntilFinished) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished))
));
if (animationRunning) {
cancel();
}
}
public void onFinish() {
text.setText("done!");
}
}.start();
}
}

Move this section of code to your onTouchEvent, because it's on activity create that is why its starting when your activity starts
new CountDownTimer(5000, 10) {
public void onTick(long millisUntilFinished) {
text.setText("" + String.format("%02d:%03d",
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)),
TimeUnit.MILLISECONDS.toMillis(millisUntilFinished) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished))
));
if (animationRunning) {
cancel();
}
}
public void onFinish() {
text.setText("done!");
}
}.start();
you should be fine

Related

I am trying to display a CountDownTimer on screen and I get "Only one looper can be created per thread" in my logcat

I'm a beginner in Android programming. I'm trying to display a timer for an upgrade in my game to show how long the upgrade will be activated for. In my collision flag I call Looper.prepare and start my thread class as the logcat suggested I do. How would I get this to run on one looper?
Here is the snippet that starts the thread.
BigGapUpgrade.java
public boolean playerCollectUpgrade(Player player){
if(Rect.intersects(rectangle, player.getRectangle())){
Looper.prepare();
bigGapUpgradeHandler.start();
}
return Rect.intersects(rectangle, player.getRectangle());
}
And here is my thread class
BigGapUpgradeHandler.java
public class BigGapUpgradeHandler extends Thread {
TimerTask scanTask;
Timer timer = new Timer();
#Override
public void run() {
Looper.prepare();
scanTask = new TimerTask() {
public void run() {
}
};
timer.schedule(scanTask, 0, 4000);
CountDownTimer countDownTimer = new CountDownTimer(4000, 100) {
#Override
public void onTick(long l) {
Log.i(TAG, "onTick: ");
}
#Override
public void onFinish() {
timer.cancel();
Log.i(TAG, "onFinish: ");
}
}.start();
Looper.loop();
}
}
After running it I get this error
W/System.err: java.lang.RuntimeException: Only one Looper may be created per thread
--Edit
Here is the solution I came up with.
-- Solution
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
CountDownTimer countDownTimer = new CountDownTimer(5000,100) {
#Override
public void onTick(long millisUntilFinished) {
millis = millisUntilFinished/100;
}
#Override
public void onFinish() {
}
}.start();
}
});
OK, So what you can do is just use a TimerTask. That creates it's own background thread for you do stuff:
// This TimerTask Updates the UI so it needs a reference to the Activity.
static class PowerUpTimerTask extends TimerTask
{
WeakReference<AppCompatActivity> mActivity;
long mInterval;
long mPeriod;
public PowerUpTimerTask(AppCompatActivity activity, long period, long interval)
{
mActivity = new WeakReference<>(activity);
mInterval = interval;
mPeriod = period;
}
#Override
public void run()
{
AppCompatActivity activity = mActivity.get();
if (activity != null)
{
final TextView timerTextView = activity.findViewById(R.id.timerTextView);
mPeriod -= mInterval;
if (mPeriod > 0)
{
// Set time remaining
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
timerTextView.setText(String.valueOf(mPeriod));
}
});
}
else
{
// Out of time...clear the Text and stop the timer task.
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
timerTextView.setText("");
}
});
Log.d(TAG, "Timer done. Canceling.");
cancel();
}
}
else
{
// Cancel this timer task since we don't have a reference to
// the Activity any more.
Log.d(TAG, "Lost reference to Activity. Canceling.");
cancel();
}
}
}
Then you can start your Timer task like so:
...
// Will count down from 10 by 1s.
mPowerUpTimerTask = new PowerUpTimerTask(this, powerUpTime, 1);
// Schedule for every second.
Timer t = new Timer();
t.scheduleAtFixedRate(mPowerUpTimerTask, 1000, 1000);
...
Here is a link to this running sample:
https://github.com/didiergarcia/TimerTaskExample
I think you have to use LocalBroadcastManager for the timing to continuously in loop. Please check below code for for that :-
private void startTimer() {
countDownTimer = new CountDownTimer(Constant.getInstance().ANSWER_TIME_IN_SECOND * 1000, 1000) {
public void onTick(long millisUntilFinished) {
remaininTimeInMillies = millisUntilFinished;
tvTimer.setText(getTime(Integer.parseInt(String.valueOf(millisUntilFinished))));
}
public void onFinish() {
Intent intent = new Intent(Constant.getInstance().TIMER_RECEIVER);
LocalBroadcastManager.getInstance(PatientDetailActivity.this).sendBroadcast(intent);
}
};
countDownTimer.start();
}
private String getTime(int milliSec) {
int minut = 0, second = 0;
minut = milliSec / 60000;
second = (milliSec - (minut * 60000)) / 1000;
String strMinute = "", strSecond = "";
if (minut < 10) {
strMinute = "0" + String.valueOf(minut);
} else {
strMinute = String.valueOf(minut);
}
if (second < 10) {
strSecond = "0" + String.valueOf(second);
} else {
strSecond = String.valueOf(second);
}
return strMinute + ":" + strSecond;
}
#Override
protected void onResume() {
LocalBroadcastManager.getInstance(this).registerReceiver(timerBroadcast, new IntentFilter(Constant.getInstance().TIMER_RECEIVER));
super.onResume();
}
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(timerBroadcast);
super.onDestroy();
}
Thanks and Hope that will help you

Timer Issue on Android Studio

I am having a problem with the Timer in my quiz Game. Essentially it's a multiple choice game and the player is timed on each question. I have the timer starting when the application starts and the player sees the first question. My issue is that if the player answers the question correctly or Incorrectly the timers starts giving random values, even though I reset the timer to 30 seconds on the onclick method. How do I get the timer to start at 30 seconds and countdown normally.
public class MainActivity extends AppCompatActivity {
//Views
TextView questionTextView;
TextView mscoreTextView;
TextView mtimerTextView;
Button mchoice1;
Button mchoice2;
Button mchoice3;
Button mchoice4;
//Constructors
private questions Question = new questions();
private Answers cAnswers = new Answers();
private choices Choices = new choices();
//Variables
private int questionNumber = 0;
private int mScore = 0;
private String correctAnswer;
public void onClick(View view) {
Button answer1 = (Button) view;
if(answer1.getText() == correctAnswer) {
mScore = mScore + 1;
Toast.makeText(getApplicationContext(), "CORRECT!!", Toast.LENGTH_SHORT).show();
mtimerTextView.setText("30s");
runTimer();
} else {
Toast.makeText(getApplicationContext(), "WRONG!!", Toast.LENGTH_SHORT).show();
mtimerTextView.setText("30s");
runTimer();
}
updateScore(mScore);
updateUI();
}
private void updateScore(int points) {
mscoreTextView.setText("" + points + "/" + Question.getLength());
}
public void runTimer() {
new CountDownTimer(30100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
String tick = String.valueOf(millisUntilFinished/1000 + "s");
mtimerTextView.setText(tick);
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "TIME RAN OUT!!", Toast.LENGTH_LONG).show();
mtimerTextView.setText("0s");
updateUI();
}
}.start();
}
private void updateUI () {
if (questionNumber < Question.getLength()) {
questionTextView.setText(Question.getQuestion(questionNumber));
mchoice1.setText(Choices.getChoices(questionNumber, 1));
mchoice2.setText(Choices.getChoices(questionNumber, 2));
mchoice3.setText(Choices.getChoices(questionNumber, 3));
mchoice4.setText(Choices.getChoices(questionNumber, 4));
correctAnswer = cAnswers.getAnswer(questionNumber);
questionNumber ++;
} else {
Toast.makeText(getApplicationContext(), "This is the last question", Toast.LENGTH_LONG).show();
//Intent intent = new Intent(MainActivity.this, HighScoreActivity.class);
//intent.putExtra("Score", mScore);
//startActivity(intent);
}
runTimer();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionTextView = (TextView) findViewById(R.id.questionTextView);
mchoice1 = (Button) findViewById(R.id.choice1);
mchoice2 = (Button) findViewById(R.id.choice2);
mchoice3 = (Button) findViewById(R.id.choice3);
mchoice4 = (Button) findViewById(R.id.choice4);
mtimerTextView = (TextView) findViewById(R.id.timerTextView);
mscoreTextView = (TextView) findViewById(R.id.scoreTextView);
updateScore(mScore);
updateUI();
}
}
The thing is, you never really cancel a timer you've launched. Along with this, for every time you need a timer - you create a new one, which is not essential. The following must solve your problem:
You need to store CountDownTimer in a class field:
private CountDownTimer timer;
Then you can create it once on the start of app:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
timer = createTimer();
...
}
CreateTimer function:
public void createTimer() {
timer = new CountDownTimer(30100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
...
}
#Override
public void onFinish() {
...
}
}
}
So when you need to run timer you just call:
timer.start();
And when user gives an answer, you need to cancel timer first, then start it again:
public void onClick(View view) {
...
timer.cancel();
timer.start();
...
}
Also: you have some duplicated code in your OnClick() method. Regardless of user's answer correctness you need to run timer and set a value to mtimerTextView, so basically you want to do it outside of if-else construction.
You have to define a variable inside a CountDownTimer class.
public void runTimer() {
new CountDownTimer(30100, 1000) {
private int time = 30;
#Override
public void onTick(long millisUntilFinished) {
mtimerTextView.setText(time--+"s");
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "TIME RAN OUT!!", Toast.LENGTH_LONG).show();
mtimerTextView.setText("0s");
updateUI();
}
}.start();
}
Cancelable Timer
If you want your Timer cancelable you have to define it as a global variable.
private CountDownTimer timer; // global variable
start the timer by calling the below runTimer() method.
public void runTimer() {
timer = new CountDownTimer(30100, 1000) {
private int time = 30;
#Override
public void onTick(long millisUntilFinished) {
mtimerTextView.setText(time--+"s");
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "TIME RAN OUT!!", Toast.LENGTH_LONG).show();
mtimerTextView.setText("0s");
updateUI();
}
}.start();
}
You can cancel the timer by calling the below method.
public void stopTimer(){
if(timer != null){
timer.cancel();
}
}
Hope this will help

Repeat specific action X number of times in Android

So I want certain action to be performed X number of times, depends on how many times user wants it. User selection will be selected from a TextView string which is set up with this code:
homeScreenPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dodajInterval();
homeScreenMinus.setEnabled(counter > 0);
}
});
homeScreenMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
oduzmiInterval();
homeScreenMinus.setEnabled(counter > 0);
}
});
}
private void oduzmiInterval() {
counter--;
brojIntervala.setText(Integer.toString(counter));
}
private void dodajInterval() {
counter++;
brojIntervala.setText(Integer.toString(counter));
}
Those are basicly two buttons that increment or decrement value of TextView.
The action I want to perform X times is this:
public void homeScreenStart(View view) {
linearniLayoutSetup.setVisibility(View.GONE);
new CountDownTimer(seekBarTimerDelay.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
countDownTimerTrci();
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_trci));
}
}.start();
}
private void countDownTimerTrci() {
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
new CountDownTimer(seekBarIntervaliVisokogIntenziteta.getProgress() * 1000 + 100, 1000){
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
imageViewTimerSlika.setImageResource(R.drawable.ic_timer_niski_intenzitet);
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_hodaj));
countDownTimerHodaj();
}
}.start();
}
private void countDownTimerHodaj(){
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
new CountDownTimer(seekBarIntervaliNiskogIntenziteta.getProgress() * 1000 + 100, 1000){
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
karticaTimera.setBackgroundColor(getResources().getColor(R.color.colorAccent));
textViewTimerTrciHodajBlaBla.setText("Done!");
}
}.start();
}
So it is combination of 3 seekbars, or timers, one running after another and then they should run as many times as user selects.
The problem is, I have no idea how to set this up, and I need that first block of code in timers to run just once, and those 2 methods below it to run X times.
How can I do it?
Unless I am missing something couldn't you just wrap your code in the action in a loop that references the current counter? You may need to block input so that the user can not modify the counter (unless you want them to) after execution has begun but that should be it.
public void homeScreenStart(View view) {
linearniLayoutSetup.setVisibility(View.GONE);
CountDownTimer firstCountDown = new CountDownTimer(seekBarTimerDelay.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
countDownTimerTrci();
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_trci));
}
}
CountDownTimer secondCountDown = new CountDownTimer(seekBarIntervaliVisokogIntenziteta.getProgress() * 1000 + 100, 1000){
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
imageViewTimerSlika.setImageResource(R.drawable.ic_timer_niski_intenzitet);
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_hodaj));
countDownTimerHodaj();
}
}
CountDownTimer thirdCountDown = new CountDownTimer(seekBarIntervaliVisokogIntenziteta.getProgress() * 1000 + 100, 1000){
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
imageViewTimerSlika.setImageResource(R.drawable.ic_timer_niski_intenzitet);
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_hodaj));
countDownTimerHodaj();
}
}
for (int i = 0; i < counter; i++) {
firstCountDown.start();
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
secondCountDown.start();
thirdCountDown.start();
}
}
Should work for you

Continue countdown timer after pause

I have a countdown timer, I have a button that pause it, but I need that when you click on button, continue to countdown. I search but couldn't a function related this. How can do it? This is my code, I only managed to restart it, but not continue:
private TextView cuentaRegresiva;
private Button btnEmpezar;
private CountDownTimer countDownTimer;
private boolean timerHasStarted = false;
private long startTime = 30 * 1000;
private final long interval = 1 * 1000;
private long restante;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
btnEmpezar.setOnClickListener(iniciar);
}
OnClickListener iniciar=new OnClickListener() {
#Override
public void onClick(View arg0) {
if (!timerHasStarted && !pausado) {
countDownTimer.start();
timerHasStarted = true;
btnEmpezar.setText("Pause");
pausado=false;
}
else if(timerHasStarted && !pausado){
countDownTimer.cancel();
timerHasStarted = false;
btnEmpezar.setText("Restart");
pausado=true;
}
else if(!timerHasStarted && pausado){
countDownTimer2.start();
timerHasStarted = true;
btnEmpezar.setText("Pause");
pausado=false;
}
}
};
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
cuentaRegresiva.setText("Tiempo!");
}
#Override
public void onTick(long millisUntilFinished) {
cuentaRegresiva.setText("" + millisUntilFinished / 1000);
}
}
public class MyCountDownTimer2 extends CountDownTimer {
public MyCountDownTimer2(long restante, long interval) {
super(restante, interval);
}
#Override
public void onFinish() {
cuentaRegresiva.setText("Tiempo!");
}
#Override
public void onTick(long millisUntilFinished) {
cuentaRegresiva.setText("" + millisUntilFinished / 1000);
}
}
I thought about taking millisUntilFinished to a variable, but didn't work. Anyway I guess the way is close to that.
You can try saving the seconds until finish, and then you can start the new countdown timer with that seconds.
// -----------------------
Cuando presionas el boton de pausa, guarda los segundos que le faltan al timer para que termine. Entonces, cuando volves a apretar play, creas un nuevo CountDownTimer con esos segundos que te faltaban.
UPDATE
I did an example:
public class MainActivity extends Activity {
private static final int TIMER_TIME = 10000; // in millis
private Button btnCountdown;
private TextView tvTimeUntilFinish;
private boolean mIsPaused = true;
private long mMillisUntilFinish;
private CountDownTimer mTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMillisUntilFinish = TIMER_TIME;
btnCountdown = (Button) findViewById(R.id.btnCountdown);
tvTimeUntilFinish = (TextView) findViewById(R.id.tvTimeUntilFinish);
btnCountdown.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (mIsPaused) {
btnCountdown.setText("Pause");
initTimer();
} else {
btnCountdown.setText("Play");
cancelTimer();
}
mIsPaused = !mIsPaused;
}
});
}
private void cancelTimer() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}
private void initTimer() {
mTimer = new CountDownTimer(mMillisUntilFinish, 1000) {
public void onTick(long millisUntilFinished) {
tvTimeUntilFinish.setText("seconds remaining: " + millisUntilFinished / 1000);
mMillisUntilFinish = millisUntilFinished;
}
public void onFinish() {
}
}.start();
}
}

restart or refresh a timer when button is clicked in android [duplicate]

This question already has an answer here:
Restart Countdown Timer with new time android
(1 answer)
Closed 8 years ago.
how to restart a timer in every button click? here given a sample code for timer setting
new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
//getSelectedAlphabet.setText(selectedIndex.getText());
}
public void onFinish() {
//mTextField.setText("done!");
getSelectedAlphabet.setVisibility(View.INVISIBLE);
Log.d("Counter", "Finished....");
}
}.start();
Try this
CountDownTimer cdt;
cdt = new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
//getSelectedAlphabet.setText(selectedIndex.getText());
}
public void onFinish() {
//mTextField.setText("done!");
getSelectedAlphabet.setVisibility(View.INVISIBLE);
Log.d("Counter", "Finished....");
}
}.start();
// to restart
cdt.cancel(); // to cancel
cdt.start(); //to start
final CountDownTimer remainingTimeCounter = new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Log.d("Counter", "Finished....");
}
}.start();
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
remainingTimeCounter.cancel();
remainingTimeCounter.start();
}
});
final CounterClass timer = new CounterClass(180000,1000);
button.setOnclickListener(new OnClickListener() {
#Override
public void onClick(View view) {
timer.start();
}
};
CounterClass-
public class CounterClass extends CountDownTimer {
public CounterClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
System.out.println("finished");
}
#Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
String hms = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS
.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
.toMinutes(millis)));
System.out.println(hms);
}
}

Categories