I've searched everywhere for an answer to this dilemma. A CountDownTimer(bsCountDownTimer) will not start when it should. When I click the button, it is supposed to begin the onTick(), correct? However, only after I navigate to a different activity and navigate backwards using the UP button, or exit the app or destroy it and restart it does the onTick() start updating the text and sending information to LogCat like it is told to do.
My best guess is that this problem is exclusive to either the CDT sub-class, onBsButtonClick(), onCreate(), or possible onResume()/onPause().
Here is some of the source code.
public class HomeActivity extends Activity {
#SuppressLint("NewApi") #Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
if(bsTimeStamp!=0){bsIsRunning=true;}
if(bsTimeStamp==0){bsIsRunning=false;}
lastFed=(TextView)findViewById(R.id.lastFedTextView);
feedAt=(TextView)findViewById(R.id.feedAtTextView);
daysText = (EditText)findViewById(R.id.editTextDays);
hoursText = (EditText)findViewById(R.id.editTextHours);
minutesText = (EditText)findViewById(R.id.editTextMinutes);
daysText.setText("");
hoursText.setText("");
minutesText.setText("");
// get timeStamp and boolean from onFeedButtonClick() START
final SharedPreferences prefs = this.getPreferences(Context.MODE_PRIVATE);
feedClickTimeStamp = prefs.getLong("savedOnFeedClick", placeholder);
bsTimeStamp = prefs.getLong("savedOnBsClick", bsProgress);
bsPlaceholder = prefs.getLong("saved placeholder", bsPlaceholder);
bsIsRunning = prefs.getBoolean("bs is running", bsIsRunning);
progressbs = Long.toString(bsProgress);
placeholderbs = Long.toString(bsPlaceholder);
timestampbs = Long.toString(bsTimeStamp);
timestamp = Long.toString(feedClickTimeStamp);
LAST_FED = prefs.getString("lastFed", LAST_FED);
FEED_AT = prefs.getString("feedAt", FEED_AT);
feedAt.setText("Feed at: " + FEED_AT);
lastFed.setText("Last fed at: " + LAST_FED);
// get timeStamp and boolean from onFeedButtonClick() END
DateTime date = new DateTime();
long currentTime = date.getMillis();
Long bsDiffInMillis;
if(bsIsRunning=false) {
bsDiffInMillis = 0L;
}
else {
bsDiffInMillis = currentTime - bsTimeStamp;
bsPlaceholder -= bsDiffInMillis;
}
Integer bsDiffInt = Integer.valueOf(bsDiffInMillis.intValue());
int roundedDiff = (bsDiffInt + 500) / 1000 * 1000;
j += roundedDiff - 2000;
// BS PROGRESS BAR START
bsProgressBar = (ProgressBar)findViewById(R.id.bsProgressBar);
bsProgressBar.setProgress(j);
Long bsPlaceholderLong = bsPlaceholder;
final Integer setMax = Integer.valueOf(bsPlaceholderLong.intValue());
bsProgressBar.setMax(setMax);
setProgressBarVisibility(true);
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB){
bsProgressBar.setRotation(180);
} else{
// FIND A WAY TO ROTATE PROGRESSBAR BEFORE API 11 (3.0)
}
timeDisplayBs=(TextView)findViewById(R.id.bs_countdown); ((TextView)findViewById(R.id.bs_countdown)).setText(convertMillisForCrafting(bsPlaceholder-ji));
millisInFuture = bsPlaceholder;
bsCountDownTimer = new CDT(millisInFuture, countDownInterval);
// START BS BUTTON LISTENER //
final Button startBsBtn = (Button) findViewById(R.id.bsButton);
startBsBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBsButtonClick(view);
} //close onClick
}); //close onClickListener
// END BS BUTTON LISTENER //
if (savedInstanceState != null) {} else {}
}// onCreate END
#Override
protected void onPause() {
super.onPause();
bsCountDownTimer.cancel();
}
#SuppressLint("NewApi") #Override
protected void onResume() {
super.onResume();
SharedPreferences prefs = this.getPreferences(Context.MODE_PRIVATE);
bsIsRunning = prefs.getBoolean("bs is running", bsIsRunning);
if(feedClickTimeStamp>0){
mountCountDownTimer.start();
}
if(bsIsRunning==true) {
bsCountDownTimer.start();
bsIsRunning=true;
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("bs is running", bsIsRunning).commit();
}
if(bsIsRunning==false){
bsIsRunning=false;
String progressBarTitleBs = "blacksmithing research";
timeDisplayBs = (TextView)findViewById(R.id.bs_countdown);
timeDisplayBs.setText(progressBarTitleBs.toUpperCase(preferredLocale));
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("bs is running", bsIsRunning).commit();
}
}
public class CDT extends CountDownTimer {
public CDT(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
millisInFuture = prefs.getLong("saved placeholder", bsPlaceholder);
timeDisplayBs=(TextView)findViewById(R.id.bs_countdown);
}
#Override
public void onTick(long millisInFuture) {
Log.v("bsTimer", "Tick of Progress " + ji + " " + millisInFuture);
ji+=1;
j+=1000;
bsProgressBar.setProgress(j);
timeDisplayBs.setText(convertMillisForCrafting(millisInFuture-ji));
}
#Override
public void onFinish() {
bsCountDownTimer.cancel();
j=0;
ji=0;
bsPlaceholder = 0;
bsTimeStamp = 0;
bsProgressBar.setProgress(0);
String progressBarTitleBs = "blacksmithing research";
timeDisplayBs = (TextView)findViewById(R.id.bs_countdown);
timeDisplayBs.setText(progressBarTitleBs.toUpperCase(preferredLocale));
}
}
public void onBsButtonClick(View view) {
final SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
bsTimeStamp = prefs.getLong("savedOnBsClick", bsProgress);
bsPlaceholder = prefs.getLong("saved placeholder", bsPlaceholder);
bsIsRunning = prefs.getBoolean("bs is running", bsIsRunning);
EditText daysText = (EditText)findViewById(R.id.editTextDays);
EditText hoursText = (EditText)findViewById(R.id.editTextHours);
EditText minutesText = (EditText)findViewById(R.id.editTextMinutes);
int daysPh;
int hoursPh;
int minutesPh;
String daysStr = daysText.getText().toString();
String hoursStr = hoursText.getText().toString();
String minutesStr = minutesText.getText().toString();
if (daysStr.matches("") && hoursStr.matches("") && minutesStr.matches("")) {
Toast.makeText(this, "You did not enter DAYS, HOURS, or MINUTES.", Toast.LENGTH_LONG).show();
return;
}
if(bsIsRunning==false){
bsPlaceholder = 0;
bsTimeStamp = 0;
bsIsRunning=true;
j=0;
bsProgressBar.setProgress(0);
Long bsPlaceholderLong = bsPlaceholder;
final Integer setMax = Integer.valueOf(bsPlaceholderLong.intValue());
bsProgressBar.setMax(setMax);
if(daysText.getText().toString().equals("")){
daysText.setText("0");
}
if(hoursText.getText().toString().equals("")){
hoursText.setText("0");
}
if(minutesText.getText().toString().equals("")){
minutesText.setText("0");
}
daysPh = Integer.parseInt(daysText.getText().toString());
hoursPh = Integer.parseInt(hoursText.getText().toString());
minutesPh = Integer.parseInt(minutesText.getText().toString());
daysText.setText("");
hoursText.setText("");
minutesText.setText("");
SharedPreferences.Editor editor = prefs.edit();
bsPlaceholder = getMillisForCrafting(daysPh, hoursPh, minutesPh);
millisInFuture = bsPlaceholder; //VITAL
DateTime dt = new DateTime();
bsProgress = dt.getMillis();
editor.putBoolean("bs is running", bsIsRunning).commit();
editor.putLong("savedOnBsClick", bsProgress).commit();
editor.putLong("saved placeholder", bsPlaceholder).commit();
bsCountDownTimer.start();
} //close if bsIsRunning==false
else if(bsIsRunning==true){
view.invalidate();
new AlertDialog.Builder(HomeActivity.this)
.setTitle("New Blacksmithing Research Timer? (erases current)")
.setMessage("Are you sure you want to start a new timer? \n(Current timer will be erased.)")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
bsPlaceholder = 0;
bsTimeStamp = 0;
bsCountDownTimer.cancel();
bsIsRunning=true;
j=0;
bsProgressBar.setProgress(0);
String progressBarTitleBs = "blacksmithing research";
timeDisplayBs = (TextView)findViewById(R.id.bs_countdown);
timeDisplayBs.setText(progressBarTitleBs.toUpperCase(preferredLocale));
EditText daysText = (EditText)findViewById(R.id.editTextDays);
EditText hoursText = (EditText)findViewById(R.id.editTextHours);
EditText minutesText = (EditText)findViewById(R.id.editTextMinutes);
if(daysText.getText().toString().equals("")){
daysText.setText("0");
}
if(hoursText.getText().toString().equals("")){
hoursText.setText("0");
}
if(minutesText.getText().toString().equals("")){
minutesText.setText("0");
}
int daysPh = Integer.parseInt(daysText.getText().toString());
int hoursPh = Integer.parseInt(hoursText.getText().toString());
int minutesPh = Integer.parseInt(minutesText.getText().toString());
SharedPreferences.Editor editor = prefs.edit();
bsPlaceholder = getMillisForCrafting(daysPh, hoursPh, minutesPh);
DateTime dt = new DateTime();
bsProgress = dt.getMillis();
editor.putBoolean("bs is running", bsIsRunning).commit();
editor.putLong("savedOnBsClick", bsProgress).commit();
editor.putLong("saved placeholder", bsPlaceholder).commit();
Long bsPlaceholderLong = bsPlaceholder;
final Integer setMax = Integer.valueOf(bsPlaceholderLong.intValue());
bsProgressBar.setMax(setMax);
daysText.setText("");
hoursText.setText("");
minutesText.setText("");
bsCountDownTimer.start();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}return;
}
public static Long getMillisForCrafting(int daysPh, int hoursPh, int minutesPh) {
Locale.getDefault();
DateTime bs = new DateTime();
daysPulled = daysPh;
hoursPulled = hoursPh;
minutesPulled = minutesPh;
final long nowInMillis = bs.getMillis();
long days = daysPulled * 86400000;
long hours = hoursPulled * 3600000;
long minutes = minutesPulled * 60000;
long millisToAddToNow = days + hours + minutes;
long futureDateInMillis = millisToAddToNow + nowInMillis;
long millisFromDate = futureDateInMillis - nowInMillis;
return millisFromDate;
}
public void onBsResetButtonClick(View view) {
final SharedPreferences prefs = this.getPreferences(Context.MODE_PRIVATE);
bsTimeStamp = prefs.getLong("savedOnBsClick", bsProgress);
new AlertDialog.Builder(this)
.setTitle("Reset Timer?")
.setMessage("Reset Blacksmithing Research timer? \n(Current timer will be erased.)")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
j=0;
bsProgressBar.setProgress(0);
bsCountDownTimer.cancel();
bsIsRunning=false;
String progressBarTitleBs = "blacksmithing research";
timeDisplayBs = (TextView)findViewById(R.id.bs_countdown);
timeDisplayBs.setText(progressBarTitleBs.toUpperCase(preferredLocale));
bsPlaceholder = 0;
bsTimeStamp = 0;
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("bs is running", bsIsRunning).commit();
editor.putLong("savedOnBsClick", 0).commit();
editor.putLong("saved placeholder", 0).commit();
// CLEAR INPUT EDITTEXT AREAS
EditText daysText = (EditText)findViewById(R.id.editTextDays);
EditText hoursText = (EditText)findViewById(R.id.editTextHours);
EditText minutesText = (EditText)findViewById(R.id.editTextMinutes);
daysText.setText("");
hoursText.setText("");
minutesText.setText("");
// CLEAR INPUT EDITTEXT AREAS
}})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
#SuppressLint("DefaultLocale")
public static String convertMillis(long milliseconds){
long seconds, minutes, hours;
seconds = milliseconds / 1000;
minutes = seconds / 60;
seconds = seconds % 60;
hours = minutes / 60;
minutes = minutes % 60;
Locale.getDefault();
String time = String.format("%02d:%02d:%02d", hours, minutes, seconds);
return(time);
}
#SuppressLint("DefaultLocale")
public static String convertMillisForCrafting(long milliseconds){
long seconds, minutes, hours, days;
seconds = milliseconds / 1000;
minutes = seconds / 60;
seconds = seconds % 60;
hours = minutes / 60;
days = hours / 24;
hours = hours % 24;
minutes = minutes % 60;
Locale.getDefault();
String timeBs = String.format("%02d days %02d hours %02d minutes %02d seconds", days, hours, minutes, seconds);
return(timeBs);
}
#Override
protected void onDestroy() {
super.onDestroy(); // Always call the superclass
mProgressBar.destroyDrawingCache();
mountCountDownTimer.cancel();
// bsProgressBar.destroyDrawingCache();
// bsCountDownTimer.cancel();
// android.os.Debug.stopMethodTracing(); // Stop method tracing that the activity started during onCreate()
}
}
I got it!
The countDownTimer wouldn't start because the variable from onBsButtonClick() (bsPlaceholder) wasn't being passed into onCreate() correctly.
Here's what I did:
Declared a global variable
static long timeInput;
Created a sub-class that extends CountDownTimer:
public class bsTimer extends CountDownTimer {
public bsTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisInFuture) {
Log.v("bsTimer", "Tick of Progress " + ji + " " + millisInFuture);
ji+=1;
j+=1000;
bsProgressBar.setProgress(j);
((TextView)findViewById(R.id.bs_countdown)).setText(convertMillisForCrafting(millisInFuture-ji));
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
}
Instantiated the countdown timer in onCreate();
bsCountDownTimer = new bsTimer(timeInput, 1000);
Then just made a new timer and started it in the onBsButtonClick() method!
bsCountDownTimer = new bsTimer(timeInput, 1000).start();
Related
I am an absolute beginner and was trying to code a Count-up-timer app that will run in the background, in other words when the app is closed from overview or when the back button is pressed, the timer will still appear to continue on the corrected time the next time the app is opened. I tried to do this by using SharedPreferences.
An error that I run into is that when I launch the emulator, the timer does not start at 00:00:00 as it should, however, it starts at random times. Here is a screenshot
public class MainActivity extends AppCompatActivity {
TextView timerText;
TextView dayText;
Button startStopButton;
Timer timer;
TimerTask timertask;
Double time = 0.0;
Double mEndTime = 0.0;
Double startingSysTime = 0.0;
Double timeGap = 0.0;
public static final String SHARED_PREFS ="sharedPrefs";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timerText = (TextView) findViewById(R.id.timerText);
startStopButton = (Button) findViewById(R.id.startStopButton);
dayText = (TextView) findViewById(R.id.dayText);
timer = new Timer();
SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
time = Double.longBitsToDouble(prefs.getLong("mTimeValue", Double.doubleToLongBits(0.0)));
mEndTime = Double.longBitsToDouble(prefs.getLong("onDestr_SysTime", Double.doubleToLongBits(0.0)));
if(mEndTime==0.0){
startingSysTime = 0.0;
}else{
startingSysTime = (double) (System.currentTimeMillis());
}
timeGap = startingSysTime - mEndTime;
time += timeGap;
startTimer();
}
#Override
protected void onStop() {
super.onStop();
Log.i("TIMEGAP", "onStop called");
SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong("mTimeValue", Double.doubleToRawLongBits(time)); //saves the time value
editor.putLong("onDestr_SysTime", Double.doubleToRawLongBits(System.currentTimeMillis())); //saves the CurrentSystemTime when onStop is invoked
editor.apply();
}
private void startTimer() {
timertask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
time++;
timerText.setText(getTimerText());
dayText.setText(getDayText());
}
});
}
};
timer.scheduleAtFixedRate(timertask, 0, 1000);
}
private String getDayText() {
int rounded = (int) Math.round(time);
int days = (rounded / 86400);
return formatDay(days);
}
private String formatDay(int days) {
String pluralDays;
if (days == 1) {
pluralDays = " Day";
} else {
pluralDays = " Days";
}
return days + pluralDays;
}
private String getTimerText() {
int rounded = (int) Math.round(time);
int seconds = ((rounded % 86400) % 3600) % 60;
int minutes = ((rounded % 86400) % 3600) / 60;
int hours = ((rounded % 86400) / 3600);
return formatTime(seconds, minutes, hours);
}
private String formatTime(int seconds, int minutes, int hours) {
return String.format("%02d", hours) + " : " + String.format("%02d", minutes) + " : " + String.format("%02d", seconds);
}
EDIT: Problem fixed, I simply had to convert timeGap to seconds by dividing it by 1000
timeGap = (startingSysTime - mEndTime)/1000;
Try this way
Handler.postDelayed(new Runnable{
//Todo write your code here
handler.postdelayed(this,1000);
},1000);
Start where you need
long starttime;
start time = System.currentTimeMilisecond();
End where you need
long currtime = System.currentTimeMilisecond() - startime;
}
According to your question try to convert this millisecond in your format which you need. Store long value in shared preference if you want to manage this on app close also
I'm creating a timer app that utilizes a thread. When I exit the app using the home button the timer is running fine. Usually, when the time is up a dialog is launched that asks the user for some input. This works completely fine if the app is in its onResume() state, however when the app is in its onStop() state the dialog will not launch and an error is thrown.
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
How can I make it so that when the time is up and the app is NOT in the foreground the dialog is still launched. My initial thought was to save the time remaining in the bundle, but the time remaining is changing for every single tick. Then I thought about storing a boolean in the bundle mTimeRunning. However, when the time is up this value must also change. So now I'm drawing a blank. What can I possibly do so that the dialog is launched when the app is not in the foreground?
TimerActivity.java
public class TimerActivity extends AppCompatActivity implements TimeDialogFragment.sendMinutes,
TimeFinishDialogFragment.sendResponse, BreakFinishDialogFragment.userResponse {
// Variable to log activity state
private static final String TAG = "TimerActivity";
private static final boolean DEBUG = true;
// ^^ Variable used to log acitivty state
private Handler mHandler;
private Runnable mRunnable;
//private static final long START_TIME_MILLISECONDS = 600000;
// Below start time is for development purposes only
private static long mStartTime = 10000;
private long mTimeRemaining = mStartTime;
private boolean mTimeRunning;
private boolean mBreakTime = false;
private ProgressBar mTimeBar;
private TextView mTime;
private Button mStartPause;
private Button mSetTime;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
if(DEBUG) Log.d(TAG, "+ onCreate() +");
mHandler = new Handler();
mTimeBar = findViewById(R.id.time_bar);
mTime = findViewById(R.id.text_view_time);
mStartPause = findViewById(R.id.button_start_pause);
mSetTime = findViewById(R.id.button_set_time);
updateCountDownText();
mTimeBar.setMax((int) mTimeRemaining);
mSetTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//FragmentManager manager = getSupportFragmentManager();
DialogFragment setTime = new TimeDialogFragment();
setTime.show(getFragmentManager(),"SET_TIME_DIALOG");
}
});
mStartPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mTimeRunning){
//pauseTimer();
mTimeRunning = false;
mStartPause.setText("Start");
mHandler.removeCallbacks(mRunnable);
}else{
//startTimer();
timer();
}
}
});
}
// Using a handler + anon runnable
private void timer(){
mRunnable = new Runnable() {
#Override
public void run() {
mTimeRunning = true;
mStartPause.setText("Pause");
mTimeRemaining = mTimeRemaining - 1000;
updateCountDownText();
mTimeBar.incrementProgressBy(1000);
if(mTimeRemaining > 0) {
mHandler.postDelayed(this, 1000);
}else{
// if breaktime is false
if(!mBreakTime) {
DialogFragment dialog = new TimeFinishDialogFragment();
dialog.show(getFragmentManager(),"TIME_FINISH_DIALOG");
mTimeRunning = false;
}else{
// launch break time up dialog.
mBreakTime = false;
DialogFragment dialog = new BreakFinishDialogFragment();
dialog.show(getFragmentManager(), "BREAK_FINSIH_DIALOG");
}
}
}
};
mHandler.postDelayed(mRunnable,1000);
}
public void updateCountDownText(){
int min = (int) (mTimeRemaining / 1000) / 60;
int sec = (int) (mTimeRemaining / 1000) % 60;
String formattedString = String.format(Locale.getDefault(), "%02d:%02d", min, sec);
mTime.setText(formattedString);
}
public void setCountDownText(long time){
int min = (int) (time / 1000) / 60;
int sec = (int) (time / 1000) % 60;
String formattedString = String.format(Locale.getDefault(), "%02d:%02d", min, sec);
mTime.setText(formattedString);
}
#Override
public void userTime(int minutes) {
TimerActivity.mStartTime = (minutes * 60) * 1000;
mTimeRemaining = TimerActivity.mStartTime;
mTimeBar.setMax((int) mTimeRemaining);
setCountDownText(mTimeRemaining);
}
#Override
public void sendResponse(int val) {
if(val == -1){
mTimeRemaining = TimerActivity.mStartTime;
mTimeBar.setMax((int) mTimeRemaining);
updateCountDownText();
mTimeBar.setProgress(0);
mStartPause.setText("Start");
}else if(val == 1) {
mBreakTime = true;
mTimeRemaining = 15000;
mTimeBar.setMax((int) mTimeRemaining);
setCountDownText(mTimeRemaining);
mTimeBar.setProgress(0);
mStartPause.setVisibility(View.INVISIBLE);
timer();
}else {
mTimeRemaining = TimerActivity.mStartTime;
mTimeBar.setMax((int) mTimeRemaining);
updateCountDownText();
mTimeBar.setProgress(0);
timer();
}
}
#Override
public void userResponse(int val) {
if(val < 0) {
// user clicked cance
mTimeRemaining = TimerActivity.mStartTime;
mTimeBar.setMax((int) mTimeRemaining);
updateCountDownText();
mTimeBar.setProgress(0);
mStartPause.setText("Start");
}else {
mTimeRemaining = TimerActivity.mStartTime;
mTimeBar.setMax((int) mTimeRemaining);
updateCountDownText();
mTimeBar.setProgress(0);
timer();
}
mStartPause.setVisibility(View.VISIBLE);
}
TimeFinishedDialog.java
public class TimeFinishDialogFragment extends DialogFragment implements View.OnClickListener{
private Button mCancel;
private Button mSkip;
private Button mStartBreak;
private sendResponse mResponse;
interface sendResponse{
void sendResponse(int val);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//return super.onCreateDialog(savedInstanceState);
View view = LayoutInflater.from(getActivity()).inflate(R.layout.time_finish_dialog_fragment, null, false);
mCancel = view.findViewById(R.id.button_cancel);
mSkip = view.findViewById(R.id.button_skip);
mStartBreak = view.findViewById(R.id.button_start_break);
mCancel.setOnClickListener(this);
mSkip.setOnClickListener(this);
mStartBreak.setOnClickListener(this);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view)
.setTitle("Start Break?");
AlertDialog dialog = builder.create();
dialog.setContentView(view);
return dialog;
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.button_cancel:
mResponse.sendResponse(-1);
getDialog().dismiss();
break;
case R.id.button_skip:
mResponse.sendResponse(0);
getDialog().dismiss();
break;
case R.id.button_start_break:
mResponse.sendResponse(1);
getDialog().dismiss();
break;
default:
break;
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
mResponse = (sendResponse) getActivity();
}catch (ClassCastException e){
System.out.println("Error: " + e);
}
}
}
when the time is up and the app is NOT in the foreground the dialog is still launched
You should not be doing this since this will interrupt the user from doing other work which they might be doing at that time and this can be irritating.
What can I possibly do so that the dialog is launched when the app is not in the foreground?
You can show the dialog only the user is actively using your application or you can fall back to show a notification when the user is not using the app.
And if you desperately want to show a dialog, you can try a dialog themed activity
My app checks if there is a file with a date.
If there is a date, it calculates the difference between today and that (future) date and initializes a timer counting down the seconds until that date in the way X days Y hours Z minutes S seconds.
If there is no file, then the user can select a date with a button. The program will store the date in the file and set the countdown.
There is a Delete Button to delete the date and choose another. This delete button should cancel the timer so it stops counting.
The timer does not stop when I cancel it. My timer is ticking but the difference is 2 seconds instead of one. It shows 40 38 36... instead of 40 39 38...
And lastly, it's storing the picked date twice instead of once.
The DatePicker code is from here.
public class NextVisit extends Activity implements DatePickerFragment.TheListener{
protected Vibrator vibrate;
protected int SECONDS_IN_A_DAY = 24 * 60 * 60;
protected String filePath = "";
protected SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
final long[] pattern = {0, 1000, 500, 1000, 500, 1000, 500, 1000 };
CountDownTimer timer = null;
String dateString = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next_visit);
final TextView label = (TextView) findViewById(R.id.label);
final TextView countdown = (TextView) findViewById(R.id.time_visit);
final Button bDate = (Button) findViewById(R.id.date_button);
final Button bDelete = (Button) findViewById(R.id.delete_button);
File dir = new File(getFilesDir(), "loveApp");
if(!dir.exists())
dir.mkdirs();
final File f = new File(getFilesDir()+"/loveApp"+"/love_date.txt");
filePath = f.getAbsolutePath();
vibrate = (Vibrator) getSystemService(VIBRATOR_SERVICE);
bDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(f.exists()){
f.delete();
System.out.println("File deleted successfully");
bDate.setVisibility(View.VISIBLE);
label.setText(R.string.next_visit1);
timer.cancel();
countdown.setText("");
System.out.println("I cancelled the timer");
bDelete.setVisibility(View.INVISIBLE);
bDate.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
DialogFragment picker = new DatePickerFragment();
bDelete.setVisibility(View.VISIBLE);
bDate.setVisibility(View.INVISIBLE);
picker.show(getFragmentManager(), "datePicker");
}
});
}
}
});
if(f.exists()){
System.out.println("File exists");
bDate.setVisibility(View.INVISIBLE);
label.setText(getString(R.string.label));
try{
BufferedReader br = new BufferedReader(new FileReader(f));
dateString = br.readLine();
br.close();
System.out.println("Date: "+dateString);
Date finalDate = formatter.parse(dateString);
setCountdown(finalDate);
}catch(Exception e){
e.printStackTrace();
label.setText("ERROR");
}
}else{
System.out.println("File DOES NOT EXIST");
bDelete.setVisibility(View.INVISIBLE); //Removing the delete date button
bDate.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
DialogFragment picker = new DatePickerFragment();
bDelete.setVisibility(View.VISIBLE);
bDate.setVisibility(View.INVISIBLE);
picker.show(getFragmentManager(), "datePicker");
}
});
}
}
public void setCountdown(Date finishDate){
long end = finishDate.getTime();
final TextView countdown = (TextView) findViewById(R.id.time_visit);
timer = new CountDownTimer(end, 1000){
#Override
public void onTick(long millisUntilFinished) {
long now = Calendar.getInstance(Locale.GERMANY).getTimeInMillis()+1000;
long diff = millisUntilFinished - now;
long diffSec = diff / 1000;
long days = diffSec / SECONDS_IN_A_DAY;
long secondsDay = diffSec % SECONDS_IN_A_DAY;
long seconds = secondsDay % 60;
long minutes = (secondsDay / 60) % 60;
long hours = (secondsDay / 3600);
countdown.setText(days+ " days, "+ hours + "hours, "+minutes + "m, "+seconds + "s remaining!");
}
#Override
public void onFinish() {
countdown.setText("done!");
vibrate.vibrate(pattern,-1);
}
}.start();
}
#Override
public void returnDate(String date) {
dateString = date;
TextView label = (TextView) findViewById(R.id.label);
label.setText(R.string.label);
BufferedWriter bw;
try {
bw = new BufferedWriter(new FileWriter(new File(filePath)));
bw.write(dateString);
bw.close();
System.out.println("Saved the file, date is: "+ dateString);
Date finishDate = formatter.parse(date);
setCountdown(finishDate);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I think problem in this string long now = Calendar.getInstance(Locale.GERMANY).getTimeInMillis()+1000; you need put it outside of countdowntimer code.
final long now = Calendar.getInstance(Locale.GERMANY).getTimeInMillis()+1000;
timer = new CountDownTimer(end, 1000){
#Override
public void onTick(long millisUntilFinished) {
long diff = millisUntilFinished - now;
long diffSec = diff / 1000;
...
};
I have a TimePicker that is generated within a AlertDialog so do not know what your ID. How to get the value set by the user? I want to send you a notification to him every day at this time (I already have a prompt notification).
And then: what they suggest?`
/** Private members of the class */
private TextView MostraTime;
private Button Time;
private int DayHour;
private int DayMinute;
Intent VoltaMenu;
/**
* This integer will uniquely define the dialog to be used for displaying
* time picker.
*/
static final int TIME_DIALOG_ID = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notify);
/** Capture our View elements */
MostraTime = (TextView) findViewById(R.id.MostraTempo);
Time = (Button) findViewById(R.id.TempoAlerta);
/** Listener for click event of the button */
Time.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showDialog(TIME_DIALOG_ID);
}
});
/** Get the current time */
final Calendar cal = Calendar.getInstance();
DayHour = cal.get(Calendar.HOUR_OF_DAY);
DayMinute = cal.get(Calendar.MINUTE);
/** Display the current time in the TextView */
updateDisplay();
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case TIME_DIALOG_ID:
return new TimePickerDialog(this, mTimeSetListener, DayHour,
DayMinute, false);
}
return null;
}
/** Callback received when the user "picks" a time in the dialog */
private TimePickerDialog.OnTimeSetListener mTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
DayHour = hourOfDay;
DayMinute = minute;
updateDisplay();
displayToast();
}
};
/** Updates the time in the TextView */
private void updateDisplay() {
MostraTime.setText(new StringBuilder().append(pad(DayHour)).append(":")
.append(pad(DayMinute)));
}
/** Displays a notification when the time is updated */
private void displayToast() {
VoltaMenu = new Intent(MenuNotificacao.this, Prefs.class);
startActivity(VoltaMenu);
Toast.makeText(
this,
new StringBuilder().append(
getResources().getString(R.string.horario) + " ")
.append(MostraTime.getText()), Toast.LENGTH_SHORT)
.show();
}
/** Add padding to numbers less than ten */
private static String pad(int c) {
if (c >= 10)
return String.valueOf(c);
else
return "0" + String.valueOf(c);
}
}
`
try this link to get value from timepicker..link is
http://androidexample.com/Time_Picker_With_AM_PM_Values_-_Android_Example/index.php?view=article_discription&aid=86&aaid=109
/********* display current time on screen Start ********/
final Calendar c = Calendar.getInstance();
// Current Hour
hour = c.get(Calendar.HOUR_OF_DAY);
// Current Minute
minute = c.get(Calendar.MINUTE);
// set current time into output textview
updateTime(hour, minute);
/********* display current time on screen End ********/
// Add Button Click Listener
addButtonClickListener();
}
public void addButtonClickListener() {
btnClick = (Button) findViewById(R.id.btnClick);
btnClick.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showDialog(TIME_DIALOG_ID);
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case TIME_DIALOG_ID:
// set time picker as current time
return new TimePickerDialog(this, timePickerListener, hour, minute,
false);
}
return null;
}
private TimePickerDialog.OnTimeSetListener timePickerListener = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minutes) {
// TODO Auto-generated method stub
hour = hourOfDay;
minute = minutes;
updateTime(hour,minute);
}
};
private static String utilTime(int value) {
if (value < 10)
return "0" + String.valueOf(value);
else
return String.valueOf(value);
}
// Used to convert 24hr format to 12hr format with AM/PM values
private void updateTime(int hours, int mins) {
String timeSet = "";
if (hours > 12) {
hours -= 12;
timeSet = "PM";
} else if (hours == 0) {
hours += 12;
timeSet = "AM";
} else if (hours == 12)
timeSet = "PM";
else
timeSet = "AM";
String minutes = "";
if (mins < 10)
minutes = "0" + mins;
else
minutes = String.valueOf(mins);
// Append in a StringBuilder
String aTime = new StringBuilder().append(hours).append(':')
.append(minutes).append(" ").append(timeSet).toString();
output.setText(aTime);
}
I make it like this
public void alertDialog(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = LayoutInflater.from(this);
View alerdialogV = inflater.inflate(R.layout.alert_layout, null);
builder.setView(alerdialogV);
builder.setTitle("1st aletdialog");
final TextView timeset = (TextView) alerdialogV.findViewById(R.id.timepicker);
final TextView timeset1 = (TextView) alerdialogV.findViewById(R.id.timepicker2);
timeset.setOnClickListener(getL(timeset));
timeset1.setOnClickListener(getL(timeset1));
builder.show();
here is method
#NonNull
private View.OnClickListener getL(final TextView t) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
final Calendar c = Calendar.getInstance();
int hour = c.getTime().getHours();
int minut = c.getTime().getMinutes();
MyTimePicker tpd = new MyTimePicker(ctx, new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
t.setText(hourOfDay + ":" + minute);
}
}, hour,minut, is24HrView);
tpd.show();
}
};
}
and this is mycustom Timepicker
public class MyTimePicker extends TimePickerDialog {
private final static int TIME_PICKER_INTERVAL = 5;
private TimePicker timePicker;
private final OnTimeSetListener callback;
public MyTimePicker(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) {
super(context, TimePickerDialog.THEME_HOLO_DARK, callBack, hourOfDay, minute / TIME_PICKER_INTERVAL, is24HourView);
this.callback = callBack;
}
#Override
public void onClick(DialogInterface dialog, int which) {
if (callback != null && timePicker != null) {
timePicker.clearFocus();
callback.onTimeSet(timePicker, timePicker.getCurrentHour(),
timePicker.getCurrentMinute() * TIME_PICKER_INTERVAL);
}
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
try {
Class<?> classForid = Class.forName("com.android.internal.R$id");
Field timePickerField = classForid.getField("timePicker");
this.timePicker = (TimePicker) findViewById(timePickerField
.getInt(null));
Field field = classForid.getField("minute");
NumberPicker mMinuteSpinner = (NumberPicker) timePicker
.findViewById(field.getInt(null));
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1);
List<String> displayedValues = new ArrayList<String>();
for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
displayedValues.add(String.format("%02d", i));
}
mMinuteSpinner.setDisplayedValues(displayedValues
.toArray(new String[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
I wrote a timer code. the clear function doesn't clear the time value (when I press clear only the text changes, but the time value continues form stop point) here is the code, any suggestions to activate the clear button?:
public class MainActivity extends Activity {
private Button startButton;
private Button stopButton;
private Button clearButton;
private TextView timeValue;
private long timeStart = 0L;
private Handler timeHandler = new Handler();
long timeInMilisec = 0L;
long timeMemo = 0L;
long timeUpdate = 0L;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timeValue = (TextView) findViewById(R.id.timeValue);
startButton = (Button) findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
timeStart = SystemClock.uptimeMillis();
timeHandler.postDelayed(updateTimerThread, 0);
}
});
stopButton = (Button) findViewById(R.id.stopButton);
stopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
timeMemo += timeInMilisec;
timeHandler.removeCallbacks(updateTimerThread);
}
});
clearButton = (Button) findViewById(R.id.clearButton);
clearButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
case R.id.clearButton:
timeValue.setText("00:00:00");
int secs = 0;
int mins = 0;
secs = 0;
int milliseconds = 0;
timeInMilisec = SystemClock.uptimeMillis() - timeStart;
timeUpdate = timeMemo + timeInMilisec;
timeValue.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));
timeHandler.removeCallbacksAndMessages(updateTimerThread);
timeValue.setText("00:00:00");
break;
}
}
});
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
timeInMilisec = SystemClock.uptimeMillis() - timeStart;
timeUpdate = timeMemo + timeInMilisec;
int secs = (int) (timeUpdate / 1000);
int mins = secs / 60;
secs = secs % 60;
int milliseconds = (int) (timeUpdate % 1000);
timeValue.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));
timeHandler.postDelayed(this, 0);
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
You should reset the timeMemo variable.
clearButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
case R.id.clearButton:
// Clear the timestart and timeMemo
timeMemo = 0L;
timeValue.setText("00:00:00");
int secs = 0;
int mins = 0;
secs = 0;
int milliseconds = 0;
timeInMilisec = SystemClock.uptimeMillis() - timeStart;
timeUpdate = timeMemo + timeInMilisec;
timeValue.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));
timeHandler.removeCallbacksAndMessages(updateTimerThread);
timeValue.setText("00:00:00");
timeHandler.removeCallbacks(updateTimerThread);
break;
}
}
});
In the ClearButton onClick you are not reseting the value of the "timerstart" and "timeMemo" variables. That is why only the text is being updated but the timer is not being reset.