Novice looking for some help~
I have a CountDownTimer with start, pause, and reset buttons. When the timer is running, I'd like to be able to hit the reset button to restart it from the original value (edittext.) Currently, the only way I am able to accomplish this is to hit "pause" then "reset."
To give an example of what I'm hoping to accomplish:
If timer is set to 10s,
10-9-8-reset-10-9-8-7-6-5-reset-10-9....
Thanks in advance!
I've looked through the forums and android dev site
EDIT: Original problem solved but another has arisen. Code below shows changes made. If I hit start-pause-start too quickly, one second is added to the original countdown time. For example: 15-14-pause-start-15-pause-start-16-pause-start-17-pause-start-18
private void pauseTimer(boolean actualPause) {
mCountdowntimer.cancel();
mTimerRunning = false;
if(actualPause)
updateWatchInterface();
}
private void resetTimer() {
if(mTimerRunning)
pauseTimer(false);
mTimeLeftInMillis = mStartTimeInMillis;
updateCountDownText();
updateWatchInterface();
}
I am not sure what your exact problem is, so I will mention a couple of approaches.
Option 1: If you don't have any problems remembering the 'start time' (that's what mStartTimeInMillis denotes, right?), then you can simply change the signature of the function pauseTimer as follows:
private void pauseTimer(boolean actualPause) {
mCountdowntimer.cancel();
mTimerRunning = false;
if(actualPause)
updateWatchInterface();
}
private void resetTimer() {
if(mTimerRunning)
pauseTimer(false);
mTimeLeftInMillis = mStartTimeInMillis;
updateCountDownText();
updateWatchInterface();
}
Also modify the top portion as:
public void onClick(android.view.View view) {
if (mTimerRunning) {
pauseTimer(true);
}
//...Other code
}
This will ensure that the watch interface is not updated to show the paused interface when you press the reset button, but the actual working would be as if you had pressed pause first and then reset. Also, we put a check to ensure that the pause timer is not called if it was actually pause followed by reset.
Option 2: If you can't get the reference to mStartTimeInMillis without calling pause first, you can use SharedPreferences, and save the start time every time you start the timer, thus allowing you access to the variable as follows:
//Put
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("time", *Your_value* );
editor.apply();
//Get
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String name = prefs.getString("time", "00:00");//"00:00" is the default value if the //entry doesn't exist.
I hope these will be helpful :)
Related
So my goal is to click a button, disable it and start a timer, once the timer is up enable the button. Simple right? You would do something like this.
button1.onClick {
button1.setEnabled(false);
new CountDownTimer(60000, 1000) { //Set Timer for 5 seconds
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
button1.setEnabled(true);
}
}.start()
}
However.. If the user closes the app while the timer is running the button will be enabled again, restarting the timer. so instead of having to wait for 60 seconds the user can just close the app and open it within 10 seconds.
So my question is, how do I disable the button for 60 seconds and keep it disabled even if the user closes and opens the app until 60 seconds has passed?
You have to persist that information within a data store that keeps it even when the app is switched off.
One way to do that would be to use https://developer.android.com/training/data-storage/shared-preferences
You have to get a timestamp when starting the timer, or compute the "end time" for the timer. You then save that information, and whenever the app starts up, you first check if your preferences contain such a time stamp. And if so, you check whether you are still in that "timed" window.
Thr key things to remember: you have to remove the persisted information when the timer is up, and: if somebody changes the system clock in the mean time, you got a problem, too. Dealing with that is possible, but requires more effort.
Try this with Handler.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
btn.setEnabled(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// This method will be executed once the timer is over
btn.setEnabled(true);
Log.d(TAG,"resend1");
}
},10000);// set time as per your requirement
}
});
I have made the beginning of what will be a pretty cool wear app, for now it is just a metronome that vibrates on the tempo the user selects.
My problem is that when you exit the app or when the screen goes into "ambient mode" the vibration keeps going, which is great, but when you open the app again it opens a new "instance" (or however you say that) of the app so the vibration tempo previously selected keeps vibrating and when you select a new one you basically have 2 tempos vibrating.
Maybe this has something to do with the fact that I use a new Thread for the timing and that Thread keeps running. Is there a way to prevent this? Thank you!
public void buttonTempoOnClick(final View v) {
Running = !Running;
Button button = (Button) v;
Thread Timer = new Thread(new Runnable() {
public void run() {
while (Running == true) {
vibrate(150);
try {
Thread.sleep(60000 / Tempo);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Timer.start();
(vibrate refers to a void I created in the class, which works.)
public void vibrate(int duration){
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(duration);
}
Edit: I already have a public boolean Running that is false by default, when the "start' button is pressed it toggles the boolean and starts a new threat with a while(Running == true) loop in it. Stopping the vibration by pressing the button one more time works like a charm.
Try setting a variable in the class managing the thread, like
boolean isTempoOn = true;
In your main activity, in the onResume() function, check if it's already running. If so, don't start again.
Perhaps posting the applicable portion of code will help.
I am currently working on a very simple UI for my Android App. My goal is to animate some (I don't know how many yet) buttons on startup and NEVER AGAIN.
So following the official docs, reading java doc and searching on stackoverflow aswell, I finally got it work. Here's what I do with a single test view.
Set the View and the Animation in the OnCreate() method.
private TextView test_text;
private Animation test_anim;
...
protected void onCreate(Bundle savedInstanceState) {
...
test_text = (TextView) findViewById(R.id.text);
test_anim = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.test_animation);
}
Start the Animation in the OnWindowFocusChanged() method.
#Override
public void onWindowFocusChanged(boolean hasFocus) {
test_text.startAnimation(test_anim);
}
This procedure works, the animation is executed when the activity starts, the only problem is that the onWindowFocusChanged() method is called everytime the activity changes status. So the text animates when the app is resumed, when the layout rotates and stuff like that.
So, repeating: My goal is to animate the text only ONCE when the app boots up and then stop forever.
If it helps, I already tried to put the Animation start in other methods like onStart() or onResume(), but the issue remains the same.
You can use SharePreferences, to check a boolean value. If is true or not exists means is first launch or you can animate app in onWindowFOcusChange() method. Set it to false to never aniamte again.
////////////////////////////
/// CONSTANTS
////////////////////////////
private static final String PREF_NAME = "pref_name";
public static final String IS_STARTUP = "is_startup";
////////////////////////////
/// FIELDS
////////////////////////////
private SharedPreferences settings;
#Override
public void onWindowFocusChanged(boolean hasFocus) {
settings = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
if (settings.getBoolean(IS_START_UP, true)) {
test_text.startAnimation(test_anim);
settings.edit().putBoolean(IS_START_UP, false).commit();
}
}
In case you want to aniamte again when app starts next time, you can set the pref IS_START_UP to true when exit the application.
if (!settings.getBoolean(IS_START_UP, false)) {
settings.edit().putBoolean(IS_START_UP, true).commit();
}
Use SharedPreference to store a boolean variable & make it to true immediately after first animation & check this each time before animation starts.
if(!isAnimatedAlready){
animate();
setIsAnimated(true);
}else{}
Simply you can add a boolean variable with initial value true and after first time you can change its value to false and inside onfocus you can add another condition
If(boolean){do the animation;
boolean=false;}
this will do want you want but if you want the animation to be once during the application life cycle you can use shared prefs or simply add a static Boolean variable in application class
I am using
<Chronometer android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/chrono"
android:visibility="gone" />
in my one activity now my question is can I make it global for all of my activities so that I can show its value to every activity in my android app?
If yes then how to do this please give example because I am new in android??
Here is my timer code
Chronometer stopWatch;
stopWatch.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener(){
#Override
public void onChronometerTick(Chronometer arg0) {
countUp = (SystemClock.elapsedRealtime() - arg0.getBase()) / 1000;
long min = countUp / 60;
long sec = countUp % 60;
String minStr = "";
String secStr="";
if(min < 10)
{
minStr = "0"+min;
}
else
{
minStr = ""+min;
}
if(sec<10)
{
secStr = "0"+sec;
}
else
{
secStr = ""+sec;
}
// String asText = (countUp / 60) + ":" + (countUp % 60);
String asText = minStr + ":" + secStr;
textGoesHere.setText(asText);
}
});
stopWatch.start();
Here is an idea. Create a separate layout for your Chronometer and <include /> it in all the layouts that require a Chronometer.
Now you can either use a Singleton pattern or SharedPreferences to store the attributes such as start time, current state (Paused, Running, Stopped, Reset) of your timer. Whenever you start a new activity get the state of the timer and show it on your Timer.
For instance if the current state is running then you may have to kick start a thread to update the timer or if the timer is stopped just get the start time and stop time from your SharedPreference or your Singleton class and show it on the timer.
For instance, consider the following scenario. For simplicity let's have 2 Activities, ActivityA and ActivityB.
Now here are some of the states for your timer, yours could be different.
Ready (00:00 - Your timer is ready to run)
Running (Timer is running)
Paused (Timer is paused and can be resumed)
Stopped (You have stopped the timer and it displays the elapsed time and the next possible state would be 1 i.e, ready.)
You would need several other parameters such as,
Timer start time (System.currentTimeInMillis() minus this time gets you elapsed)
Timer stop time (Used to calculate timer paused and stopped time)
Let's consider this case. You are starting a timer from ActivityA and want to retain the state on ActivityB. Here are the set of things you might want to do.
When you start your timer by any event - say click of a button, you have to save the start time in your SharedPreference.
Now you want to navigate to ActivityB, then you have to save the timer state to your SharedPreference in the onStop() method of your ActivityA.
Now after you start ActivityB, in the onResume() method get the start time from the SharedPreference, the System.currentTimeInMillis() minus the start time will give you the elapsed time. Next, you have to get the timer state from your SharedPreference.
If the state is running, then you have to start a thread to update the timer. If the timer is stopped, then it's enough to show the time elapsed on your timer.
This is the outline of the solution. You can learn about SharedPreferences from here.
Also, you need to be familiar with the Activity lifecycle, which you can learn from here.
No, you can't.
Activities have a life cycle in Android : they are created, started, display & do stuff, get stopped and destroyed. And all the views inside obey to this life cycle.
Don't fight against it, that's the way Android is and it's great like that, learn this life cycle.
The views of an activity don't exist outside of it. This would have no meaning. You should read on how to pass information from one activity to another.
Also, maybe your question is : how can all my activities have the same view in their layout, each one having its own instance of the view. In that case, use the include xml keyword.
yes you can do this but not by making it global. it is little tricky.
what you have to do is:
- make choronometer xml declarartion with tag in each Activity.
- make access of this chronometer in base class.
Just like an example: i required header in each of activity but i wanted to do coding only at one place. so what i do is:
/**
* Method to init Header components sets header bar title and header bar
* buttons. This method sets onClickListener to
*/
private void initHeader() throws InvalidHeaderTitleException {
try {
View headerView = findViewById(R.id.header_layout);
if (headerView != null) {
headerTextView = (TextView) headerView
.findViewById(R.id.layout_header_textview_header);
nextHeaderButton = (Button) headerView
.findViewById(R.id.layout_header_button_next);
prevHeaderButton = (Button) headerView
.findViewById(R.id.layout_header_button_previous);
if (headerTextView != null) {
String title = getHeaderText();
if (isValidString(title)) {
if (title.length() > IDryIceUIConstants.LENGTH_HEADER_TEXT)
title = title.substring(0,
IDryIceUIConstants.LENGTH_HEADER_TEXT)
+ IDryIceUIConstants.SUFFIX_HEADER_TEXT;
headerTextView.setText(title);
} else {
throw new InvalidHeaderTitleException(title);
}
}
if (nextHeaderButton != null) {
nextHeaderButton.setVisibility(getVisibility());
nextHeaderButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
headerNextButtonClicked();
}
});
}
if (prevHeaderButton != null) {
prevHeaderButton.setVisibility(getVisibility());
prevHeaderButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
headerPrevButtonClicked();
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
xml declaration in each Activity xml is
<include
android:id="#+id/header_layout"
android:layout_width="fill_parent"
android:layout_height="40dip"
layout="#layout/layout_header" />
I am new android developer. I want to ask a question. Here is what I need: When the user click Back Button it counts as double click?
#Override
public void onBackPressed() {
--> what to write here?
return;
}
}
You need to check an interval between to presses and determine whether you it can be counted as a double click or not:
private static final long DOUBLE_PRESS_INTERVAL = /* some value in ns. */;
private long lastPressTime;
#Override
public void onBackPressed() {
long pressTime = System.nanoTime();
if(pressTime - lastPressTime <= DOUBLE_PRESS_INTERVAL) {
// this is a double click event
}
lastPressTime = pressTime;
}
You should probably include the reasoning behind wanting this functionality in the question instead of a comment. It makes it a lot easier for us to point you in the right direction. There are a few ways to achieve what you want but I would not recommend the 'double back' method.
Instead, if you show the progress bar in a dialog or somewhere in the search activity, there is no activity between the search and the second activity. That way you do not need to do a double back.
Also, you could display the progress bar in the second activity until the work is done and then replace it with the actual content with another call to setContentView(View). Note that this would require threading though (otherwise the progress bar would never show).
Double Key Button
private static long back_pressed;
#Override
public void onBackPressed()
{
if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed();
else Toast.makeText(getBaseContext(), "Press once again to exit!", Toast.LENGTH_SHORT).show();
back_pressed = System.currentTimeMillis();
}