I have a TimePicker in my app that can select the amount of time for playback of a song, im having issues with getting the time remaining to display properly with the CountDownTimerim using, everything is pretty much going on behind the scenes in milliseconds of course and i think im doing the conversion right but all i see on the screen is just completely wrong values.
When i just make a test CountDownTimer with 3600000(1hour) as first argument, everything works fine, but when i put timepicker to 0 and minute to 1 , like i want just 1 minute of playback , it displays 12 hours and what seems like random values in the minutes and seconds slots. tp.getCurrentHour(); returns zero when set to zero and tp.getCurrentMinute(); returns one as expected, seems like something is happening with this part, cant figure out what yet:
playtime = (hour * (60 * 60 * 1000)) + (min * (60 * 1000));
startime = SystemClock.elapsedRealtime();
Why is tv2.setText("totaltest "+startime+playtime); displaying a value of 6000046929803??? That is obviously wrong...
Here is the the rest of the code:
TimePicker tp =(TimePicker)findViewById(R.id.timePicker1);
public void onClick(View v) {
// TODO Auto-generated method stub
long hour = tp.getCurrentHour();
long min = tp.getCurrentMinute();
playtime = (hour * (60 * 60 * 1000)) + (min * (60 * 1000));
startime = SystemClock.elapsedRealtime();
tv2.setText("totaltest "+startime+playtime);
timer = new CountDownTimer(startime+playtime,1000){
#Override
public void onFinish() {
tv.setText("finished");
}
//#SuppressLint("ParserError")
#Override
public void onTick(long millisUntilFinished) {
String display = DateUtils.formatElapsedTime(millisUntilFinished/1000);
tv.setText(display);
}
}.start();
Try:
String display = DateUtils.formatElapsedTime(millisUntilFinished/1000);
That does the conversion for you.
and:
timer = new CountDownTimer(playtime,1000){
as CounterDownTimer is expecting the amount of milliseconds to run.
Related
Hey guys so i need help with my setTime method. Basically this is the question in my assignment:
Consider a class Time that represents a time of day. It has attributes for the
hour and minute. The hour value ranges from 0 to 23, where the range 0 to
11 represents a time before noon. The minute value ranges from 0 to 59.
a. Write a default constructor that initializes the time to 0 hours, 0 minutes.
b. Write a private method isValid(hour, minute) that returns true if the
given hour and minute values are in the appropriate range.
c. Write a method setTime(hour, minute) that sets the time if the given
values are valid.
I need help with c, in my code you can see that i have the set time method but when i run my programs and enter the time it returns this instead of the numbers in entered:
Please enter the hour
3
Please enter the minute
23
The time is time.Time#4d546e25 time.Time#620b66cc
BUILD SUCCESSFUL (total time: 3 seconds)
My code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package time;
/**
*
* #author 797286001
*/
public class Time {
/**
* #param args the command line arguments
*/
//default constructor
public static int hour;
public static int minute;
public Time(){
hour = 0;
minute = 0;
}
private static boolean isValid(int hour, int minute)
//returns true if given hour & minute values are in range
{
if((hour >= 0 && hour <= 23) && (minute >= 0 && minute <=11))
{
return true;
}
else
{
return false;
}
}
public void setTime(int hour, int minute)
//set time if given values are valid -
{
}
public static void main(String[] args) {
//
Time.hour = 0;
Time.hour = 0;
Time hour = new Time();
Time minute = new Time();
System.out.println("The time is " + hour + " " + minute);
}
}
setTime should not be reading anything from the keyboard; the parameters contain the values you need.
Time hour = new Time();
Time minute = new Time();
This creates two instances of your class named hour and minute. Then you try to print them out. The default toString() method prints out their location in memory.
Go ahead and create one instance of the class, then use that to call the methods you need to call. Also, your setTime method takes 2 parameters but doesn't use them.
OK, so i'm new to this and have just signed up however i need some help with explanations please..
I have a assignment which has asked me to convert a 24 hour clock into a 12 hour clock by making some adjustments. I am pretty sure I am almost there however I cannot get the boolean to switch when the hour changes using the timeTick method in the code. To be honest I believe the rest is fine but any help would be appreciated:
public class ClockDisplay
{
private NumberDisplay hours;
private NumberDisplay minutes;
private String displayString;
private boolean isAM;
/**
* Constructor for ClockDisplay objects. This constructor
* creates a new clock set at 00:00.
*/
public ClockDisplay()
{
hours = new NumberDisplay(12);
minutes = new NumberDisplay(60);
updateDisplay();
setMorn();
}
/**
* Constructor for ClockDisplay objects. This constructor
* creates a new clock set at the time specified by the
* parameters.
*/
public ClockDisplay(int hour, int minute)
{
hours = new NumberDisplay(12);
minutes = new NumberDisplay(60);
setTime(hour, minute);
setMorn();
}
/**
* This method should get called once every minute - it makes
* the clock display go one minute forward.
*/
public void timeTick()
{
minutes.increment();
if(minutes.getValue() == 0) { // it just rolled over!
hours.increment();
}
if (hours.getValue() == 12)
{
isAM = !isAM;
}
updateDisplay();
}
private void setMorn()
{
isAM = true;
}
private void setAft()
{
isAM = false;
}
/**
* Set the time of the display to the specified hour and
* minute.
*/
public void setTime(int hour, int minute)
{
hours.setValue(hour);
minutes.setValue(minute);
updateDisplay();
}
/**
* Return the current time of this display in the format HH:MM.
*/
public String getTime()
{
return displayString;
}
/**
* Update the internal string that represents the display.
*/
private void updateDisplay()
{
int hour = hours.getValue();
String daynight;
if (isAM = true)
{
daynight = "AM";
if (hour == 0)
{
hour = 12;
}
}
else
{
isAM = false;
daynight = "PM";
if (hour == 0)
{
hour = 12;
}
}
displayString = hour + ":" +
minutes.getDisplayValue() + daynight;
}
}
What We have
Add a boolean field isAM which will have the value true (it is morning) and false (it is afternoon).
We create two new methods; setMorning which sets isAM to be true and setAfternoon which sets isAM to be false.
Both constructors will initialise the time of day to be morning by default and so both invoke setMorning.
In timeTick we need to check whether the hours rolled over, meaning it either changed from am to pm or from pm to am. Note the use of: isAM = !isAM
In updateDisplay we need to create the suffix "am" or "pm" depending on whether isAM is true or false.
Your problem is almost certainly in the line that reads:
if (isAM = true)
This is actually setting isAM to true and the result of the expression is therefore also true so the else part will never be executed.
You probably meant:
if (isAM == true)
or - better still:
if (isAM)
OK, so i finally worked it out thanks to Dragondraikk who made me think. The issue was just as he suggested, well kind of. as I set the hours to 0 - 11 and tick over. I was not changing 0 into a 12 until the updateDisplay was run so it was actually a 0 and not a twelve:
public void timeTick()
{
minutes.increment()
if(minutes.getValue() == 0) { // it just rolled over!
hours.increment();
}
if (hours.getValue() == 0)
{
isAM = !isAM;
}
updateDisplay();
}
This fixed the problem and now it works :) thank you everyone for all your help.I am also aware that I can provide feedback in the form of a rating, if someone can tell me how I am more than happy to do so :)
I am making listview with timers, each with different deadline depending on the database(similar to auction)
Time now = new Time();
now.setToNow();
now.normalize(true);
nowMillis = now.toMillis(true);
.
.
String endtime = a.get(position).get(TAG_ENDTIME);
Integer timeSecond = Integer.parseInt(endtime.substring(17, 19));
Integer timeMinute = Integer.parseInt(endtime.substring(14, 16));
Integer timeHour = Integer.parseInt(endtime.substring(11, 13));
Integer timeDay = Integer.parseInt(endtime.substring(0, 2));
Integer timeMonth = Integer.parseInt(endtime.substring(3, 5)) - 1;
Integer timeYear = Integer.parseInt(endtime.substring(6, 10));
Time future = new Time();
future.set(timeSecond, timeMinute, timeHour, timeDay, timeMonth, timeYear);
future.normalize(true);
long futureMillis = future.toMillis(true);
long interval = futureMillis - nowMillis;
new CountDownTimer(interval,1000)
{
#Override
public void onTick(long millisUntilFinished)
{
Long interval = millisUntilFinished;
int days = (int) ((millisUntilFinished / 1000) / 86400);
int hours = (int) (((millisUntilFinished / 1000) - (days * 86400)) / 3600);
int minutes = (int) (((millisUntilFinished / 1000) - (days * 86400) - (hours * 3600)) / 60);
int seconds = (int) ((millisUntilFinished / 1000) % 60);
String countdown = String.format("%dd %dh %dm %ds", days, hours, minutes, seconds);
holder.duration.setText(countdown);
}
#Override
public void onFinish()
{
// TODO Auto-generated method stub
holder.duration.setText(TimeUp);
}
}.start();
That code works almost perfectly when there is only one instance.
However the problem arise when there is several instance, around 4-5 timer running at the same time
Several/all the countdown will start to flicker, be it seconds, minutes, hours, or days.
e.g. one of my timer flicker between 27d 11h 54m 50s and 0d 23h 47m 0s
Since this occur on both on emulator and on my device, it seems to be my code's flaw, but I don't have a clue what could cause this.
I tried to change
holder.duration.setText(countdown) into holder.duration.setText(millisUntilFinished)
and the the countdown flickers between the desired duration and a huge, random number,
Please help.
You should use one TimerTask and put all your UI updates into that single timer instead running multiple CountDownTimers for essentially the same job since you're already doing all the math to determine when "time is up" for any particular item, you might just run one TimerTask and once a second have it update everything. CountDownTimer is useful for a single implementation count down because it does some built-in math, etc. You're redoing all that math, so you might as well use one instance of a regular TimerTask.
The implementation of CountDownTimer relays on scheduled delays in Handler messaging. A single countdown instance is unlikely to result in any bizarre behavior, but if you have several going that all supposed to "tick" when the system clock hits each second (the time in millis ends in "000" - once a second, and all at the same time), then those handlers will all try to fire simultaneously and inevitably fail.
If the UI or other process will likely delay some of these messages, even to the point where it will "skip ticks" to catch up. Also, that means that the next message delay could be only milliseconds from the next tick (i.e. if it's supposed to check every 1000 millis, but is delayed an additional 1990 millis, then it will skip a tick and also schedule the next message for 10 millis into the future.
I want to create a function that will convert the days into milliseconds. The days format is stored as 0.2444, so how to convert this to milliseonds?
The best practice for this, in my opinion is:
TimeUnit.DAYS.toMillis(1); // 1 day to milliseconds.
TimeUnit.MINUTES.toMillis(23); // 23 minutes to milliseconds.
TimeUnit.HOURS.toMillis(4); // 4 hours to milliseconds.
TimeUnit.SECONDS.toMillis(96); // 96 seconds to milliseconds.
In addition to the other answers, there is also the TimeUnit class which allows you to convert one time duration to another. For example, to find out how many milliseconds make up one day:
TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS); //gives 86400000
Note that this method takes a long, so if you have a fraction of a day, you will have to multiply it by the number of milliseconds in one day.
Won't days * 24 * 60 * 60 * 1000 suffice?
24 hours = 86400 seconds = 86400000 milliseconds. Just multiply your number with 86400000.
Its important to mention that once in 4-5 years this method might give a 1 second error, becase of a leap-second (http://www.nist.gov/pml/div688/leapseconds.cfm), and the correct formula for that day would be
(24*60*60 + 1) * 1000
There is a question Are leap seconds catered for by Calendar? and the answer is no.
So, if You're designing super time-dependant software, be careful about this formula.
public static double toMilliSeconds(double day)
{
return day * 24 * 60 * 60 * 1000;
}
or as long:
public static long toMilliSeconds(double day)
{
return (long) (day * 24 * 60 * 60 * 1000);
}
You can use this utility class -
public class DateUtils
{
public static final long SECOND_IN_MILLIS = 1000;
public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
}
If you are working on Android framework then just import it (also named DateUtils) under package android.text.format
int day = 5;
long dayInMilliseconds = day * org.apache.commons.lang.time.DateUtils.MILLIS_PER_DAY
Below is a sample of the code I was trying, I need to run 1 task in 3 different times for X minutes every day and let's say I have 12,17,20 and it should run for 120 minutes and it is already 12:30:00 so if i open the application it should start the task and it should run for 90 minutes.
What am I doing wrong here and what do I have to change in order to do the above ?
// here I receive my config with the hours I need to run my task
String[] time = Config.SCHEDULE.split(",");
int runTimeLeft = Config.TIMELEFT;
for (String hour : time)
{
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour));
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
long start = calendar.getTimeInMillis() - System.currentTimeMillis();
ThreadPoolManager.getInstance().scheduleAtFixedRate(new Runnable()
{
public void run()
{
startMyTask();
}
}, start, 24 * 60 * 60 * 1000);
}
It's not exactly a Java problem...
You need to check if current time (in the calendar) minus current recieved time is more than 0 and less than 2 hours, and if so run the task for "2 hours minus this DIFFERENCE", else what you wrote.