Timer not working properly in ListView - java

I have used ListView to create my order cards. In which I had run a continuous timer for each card using handler to check how much time has been spent. I have used code in adapter. But my problem is when there is more then one order then the timer time overlaps on each card. For example, if I have 3 cards then ist card will show time of 1,2,3 one by one at interval of one second and 2nd will show time of 2 n 3 and for 3rd timer is stop. Another problem is timer stops after a particular amount if time. Help me regarding this.
This is my piece of code of custom adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vv = LayoutInflater.from(mContext).inflate(R.layout.adapter_listview_newpage_card,null,false);
menuModels = new ArrayList<>();
// menuModels.clear();
order_time = (TextView) vv.findViewById(R.id.order_time);
// This is my handler of timer:
final Handler myHandler = new Handler(); //declare this line in class
myHandler.postDelayed( // called this line from createlaytout function first time
new Runnable() {
public void run() {
TimeZone tz = TimeZone.getTimeZone("Asia/Kolkata");
// Log.e("TAG", "timezone "+tz );
Calendar cd = Calendar.getInstance(tz);
int min0 = cd.get(Calendar.MINUTE);
int sec0 = cd.get(Calendar.SECOND);
int hour0 = cd.get(Calendar.HOUR_OF_DAY);
// int ampm0 = cd.get(Calendar.AM_PM);
int total = (hour0 * 60 * 60) + (min0 * 60) + sec0;
int finalTime = total - Integer.parseInt(data.getTimer_time());
int hoursnew = 0;
int seconds = finalTime;
int minutes = seconds / 60;
seconds = seconds % 60;
if (minutes > 59) {
hoursnew = minutes / 60;
minutes = minutes % 60;
}
// Log.e("TAG", "timer" + minutes + "-" + seconds + "$$" + data.getOrder_id());
order_time.setText(" " + data.getOrder_id() + "&" + String.format("%02d", hoursnew) + ":" + String.format("%02d", minutes) + ":" + String.format("%02d", seconds));
myHandler.postDelayed(this, 1000);
}
}, 0);
// Here order_time is textview where I add time.
}
Updated code
Hi, I was able to run timer in my code but the problem is that now i am having null pointer exception at adapter.setnotifydata change.
My code for adapter where I set time on textview
public class customadapetr_new extends BaseAdapter {
public customadapetr_new(ArrayList<DataModel> dataModels, Context context, NewPageActivity objNewPageActivity) {
this.dataSet=dataModels;
this.mContext=context;
this.objNewPageActivity = objNewPageActivity;
}
private void setTime(final int order_time, final TextView tv) {
TimeZone tz = TimeZone.getTimeZone("Asia/Kolkata");
// Log.e("TAG", "timezone "+tz );
Calendar cd = Calendar.getInstance(tz);
int min0 = cd.get(Calendar.MINUTE);
int sec0 = cd.get(Calendar.SECOND);
int hour0 = cd.get(Calendar.HOUR_OF_DAY);
// int ampm0 = cd.get(Calendar.AM_PM);
int total = (hour0 * 60 * 60) + (min0 * 60) + sec0;
int finalTime = total - order_time;
int hoursnew = 0;
int seconds = finalTime;
int minutes = seconds / 60;
seconds = seconds % 60;
if (minutes > 59) {
hoursnew = minutes / 60;
minutes = minutes % 60;
}
tv.setText(" " + String.format("%02d", hoursnew) + ":" + String.format("%02d", minutes));
}
}
And my code from where I have called handler
public class NewPageActivity extends Fragment{
private final Runnable timerRunnable = new Runnable() {
#Override
public void run() {
Log.e("TAG", "run:timer run run " );
adapter.notifyDataSetChanged();
timerHandler.postDelayed(this, 60000); //run every minute
}
};
}
I am getting error at adapter.notifyDataSetChanged() and attaching scrrenshot link of error i.e http://prntscr.com/dmxjr9

Related

Display days, hours... that have past since a date in Android (Chronometer)

I have made a Countdown to a future date (with remaining days, hours, minutes, seconds) using CountDownTimer and lots of code from this answer: https://stackoverflow.com/a/32773716/3984944
Now I want to do exactly the same but counting up from a past date. My TextView should refresh every second and show the elapsed time.
What I tried:
I tried manipulating the CountDownTimer so that it works in reverse order. Changing the interval to -1000 or adding 2000 milliseconds to the Countdown every second. Both didn't work.
Then I figured I should use the Chronometer class. The standard Chronometer only displays hours, minutes and seconds as far as I'm concerned. So no days. I then wrote the following code in the style of the CountDownTimer answer I found before that updates a TextView with the desired data:
final Chronometer ch = (Chronometer) findViewById(R.id.ch_chronometer);
final TextView tv = (TextView) findViewById(R.id.tv_show_stopwatch);
ch.setBase(endMillis); //endMillis is the date in Milliseconds
chCountdownSince.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
public void onChronometerTick(Chronometer cArg) {
long t = System.currentTimeMillis() - chCountdownSince.getBase();
long days = TimeUnit.MILLISECONDS.toDays(t);
t -= TimeUnit.DAYS.toMillis(days);
long hours = TimeUnit.MILLISECONDS.toHours(t);
t -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(t);
t -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(t);
String stopwatchDisplay = "Days: %d Hours: %d Minutes: %d Seconds: %d";
stopwatchDisplay = String.format(stopwatchDisplay, days, hours, minutes, seconds);
tv.setText(stopwatchDisplay);
}
});
I feel like this snipped makes absolute sense but upon execution it doesn't change my TextView at all. I feel like this is just not how Chronometer works but I don't know what I'm doing wrong.
Edit :
I think you forgot to start Chronometer completely.
Given that
The calls to onTick(long) are synchronized to this object so that one
call to onTick(long) won't ever occur before the previous callback is
complete.
Its unlikely that ticks are done on UI thread, but this is exactly where you need to set your text, try changing
tv.setText(stopwatchDisplay);
to
tv.post(new Runnable() {
public void run() {
tv.setText(stopwatchDisplay);
});
please use handler..
public void countDownStart() {
handler = new Handler();
runnable = new Runnable(){
#Override
public void run(){
handler.postDelayed(this,1000);
try {
FestCountdownTimer timer = new FestCountdownTimer(00, 00, 9, 3, 01, 2017);
new CountDownTimer(timer.getIntervalMillis(), 1000) {
#Override
public void onTick(long 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("%02dd %02dh %02dm %02ds", days,
hours, minutes, seconds);
txtTimerDay.setText("" + String.format("%02d", days));
txtTimerHour.setText("" + String.format("%02d", hours));
txtTimerMinute.setText(""
+ String.format("%02d", minutes));
txtTimerSecond.setText(""
+ String.format("%02d", seconds));
}
#Override
public void onFinish() {
textViewGone();
MainActivity.aSwitch.setChecked(false);
creditText.setText("Toggle On To Start");
}
}.start();
} catch (Exception e) {
e.printStackTrace(); }
}
};
handler.postDelayed(runnable, 1 * 1000);
}
Remember, 9 is Hours,3 is date,1 is Febraury Month..Month starts from 0th Index
FestCountdownTimer class
public class FestCountdownTimer {
private long intervalMillis;
public FestCountdownTimer(int second, int minute, int hour, int monthDay, int month, int year) {
Time futureTime = new Time();
// Set date to future time
futureTime.set(second, minute, hour, monthDay, month, year);
futureTime.normalize(true);
long futureMillis = futureTime.toMillis(true);
Time timeNow = new Time();
// Set date to current time
timeNow.setToNow();
timeNow.normalize(true);
long nowMillis = timeNow.toMillis(true);
// Subtract current milliseconds time from future milliseconds time to retrieve interval
intervalMillis = futureMillis - nowMillis;
}
public long getIntervalMillis() {
return intervalMillis;
}
}
Hope it helps.. :)

HH: MM in Range Bar

I use Ermodo Range Bar, and the fact that I need to display a minimum value and a maximum value in hours and minutes ... That is below:
public class FilterActivity extends Activity {
private RangeBar rangebar;
final int SMALLEST_HOUR_FRACTION = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.filter_layout);
final TextView mDepartMin = (TextView)findViewById(R.id.tvDepartMin);
final TextView mDepartMax = (TextView)findViewById(R.id.tvDepartMax);
rangebar = (RangeBar) findViewById(R.id.rangebar1);
rangebar.setTickCount(25 * SMALLEST_HOUR_FRACTION);
rangebar.setTickHeight(0);
rangebar.setThumbRadius(8);
rangebar.setConnectingLineWeight(3);
mDepartMin.setText("" + (rangebar.getLeftIndex() / SMALLEST_HOUR_FRACTION) + ":" + SMALLEST_HOUR_FRACTION * (rangebar.getLeftIndex() % SMALLEST_HOUR_FRACTION));
mDepartMax.setText("" + (rangebar.getRightIndex() / SMALLEST_HOUR_FRACTION) + ":" + SMALLEST_HOUR_FRACTION * (rangebar.getRightIndex() % SMALLEST_HOUR_FRACTION));
rangebar.setOnRangeBarChangeListener(new RangeBar.OnRangeBarChangeListener() {
#Override
public void onIndexChangeListener(RangeBar rangeBar, int leftThumbIndex, int rightThumbIndex) {
int minHour = leftThumbIndex / SMALLEST_HOUR_FRACTION;
int minMinute = SMALLEST_HOUR_FRACTION * (leftThumbIndex % SMALLEST_HOUR_FRACTION);
int maxHour = rightThumbIndex / SMALLEST_HOUR_FRACTION;
int maxMinute = SMALLEST_HOUR_FRACTION * (rightThumbIndex % SMALLEST_HOUR_FRACTION);
mDepartMin.setText(minHour + ":" + minMinute);
mDepartMax.setText(maxHour + ":" + maxMinute);
}
});
}
}
Now it looks like this:
I think date or calendar class may help, but how do I use them?
I need it to be displayed as HH:MM instead of H:M
Using DecimalFormat you can achieve.
DecimalFormat deciFormat= new DecimalFormat("00");
mDepartMin.setText(deciFormat.format(minHour) + ":" + deciFormat.format(minMinute));
OR Using Calendar
mDepartMin.setText(getFormattedDate(minHour,minMinute));
Call this below method
public static String getFormattedDate(int hour, int minute) {
Calendar cale = Calendar.getInstance();
cale.set(Calendar.HOUR_OF_DAY, hour);
cale.set(Calendar.MINUTE, minute);
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
return dateFormat.format(cale.getTime());
}

findViewById() not working when using a seperate class

Hi I am new to Android
I would like keep the following code seperatly from my MainActivity file. However, when I try to findViewById() inside the seperate class, I get the error
"cannot be resolved"
Now I know I cannot extend the MainActivity class as it will lead to stack overflow, but could someone tell me how to go about access a textview from this seperate file?
public class Counter {
private TextView tempTextView;
//Temporary TextView
private Button tempBtn;
public Handler mHandler = new Handler();
public long startTime;
public long elapsedTime;
public final int REFRESH_RATE = 100;
public String hours,minutes,seconds,milliseconds;
public long secs,mins,hrs,msecs;
public boolean stopped = false;
public Runnable startTimer = new Runnable() {
public void run() {
elapsedTime = System.currentTimeMillis() - startTime;
updateTimer(elapsedTime);
mHandler.postDelayed(this,REFRESH_RATE);
}
};
private void updateTimer (float time) {
secs = (long) (time / 1000);
mins = (long) ((time / 1000) / 60);
hrs = (long) (((time / 1000) / 60) / 60); /* Convert the seconds to String * and format to ensure it has * a leading zero when required */
secs = secs % 60;
seconds = String.valueOf(secs);
if (secs == 0) {
seconds = "00";
}
if (secs < 10 && secs > 0) {
seconds = "0" + seconds;
} /* Convert the minutes to String and format the String */
mins = mins % 60;
minutes = String.valueOf(mins);
if (mins == 0) {
minutes = "00";
}
if (
mins < 10 && mins > 0
) {
minutes = "0" + minutes;
} /* Convert the hours to String and format the String */
hours = String.valueOf(hrs);
if (hrs == 0) {
hours = "00";
}
if (hrs < 10 && hrs > 0) {
hours = "0" + hours;
}
/* Although we are not using milliseconds on the timer in this example * I included the code in the event that you wanted to include it on your own */
milliseconds = String.valueOf((long) time);
if (milliseconds.length() == 2) {
milliseconds = "0" + milliseconds;
}
if (milliseconds.length() <= 1) {
milliseconds = "00";
}
milliseconds = milliseconds.substring(milliseconds.length() - 3, milliseconds.length() - 2);
/* Setting the timer text to the elapsed time */
// ((TextView) findViewById(R.id.elapsed_value)).setText(hours + ":" + minutes + ":" + seconds);
// ((TextView)findViewById(R.id.timerMs)).setText("." + milliseconds); }
}
}
You need to inflate a view and call the mehod findViewById() from this view. To inflate a view, you need a Context (you can set it in a custom constructor)
View view;
LayoutInflater inflater = (LayoutInflater) yourContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.mylayout, null);
tempTextView = (TextView) view.findViewById(R.id.tv);
Because, findViewById() is method from Activity class. That's why you can not use it in any other Java class.
And second you can not update Android application UI from any worker thread.
So better to use AsyncTask and pass the TextView's references which you want to update after certain task.
Or use runOnMainUiThread() if you are going to update Application UI from other worker thread. But Be sure runOnUiThread() only works with Activity Context.
You could create a constructor for Counter that takes a reference to your TextView from your Activity.
public Counter(TextView tv) {
tempTextView = tv;
}
Then call findViewById() on your MainActivity as pass in the result when you're instantiating Counter.
You're already on the UI thread, no need for AsyncTask here...
You can have a constructor where you set an activity variable.
public Counter (MainActivity activity) {
mActivity = activity;
}
Then, you can call
mActivity.findViewById(...);
which will find the view in your MainActivity layout that you set in
setContentView(<layout>);

Converting date into text format

How do I convert date into its text format..for ex:if updated today..then instead of date it must show "Today",one day after it must show "Yesterday",and then after two days..it must display the date in general form(//_) on which it was updated..i tried using SimpleDateFormat..but not working..
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Date d= new Date();
//Convert Date object to string
String strDate = sdf.format(d);
System.out.println("Formated String is " + strDate);
d = sdf.parse("31-12-2009");
Plz help..
Thanks in advance..
Try this:
public class TimeUtils {
public final static long ONE_SECOND = 1000;
public final static long SECONDS = 60;
public final static long ONE_MINUTE = ONE_SECOND * 60;
public final static long MINUTES = 60;
public final static long ONE_HOUR = ONE_MINUTE * 60;
public final static long HOURS = 24;
public final static long ONE_DAY = ONE_HOUR * 24;
private TimeUtils() {
}
/**
* converts time (in milliseconds) to human-readable format
* "<w> days, <x> hours, <y> minutes and (z) seconds"
*/
public static String millisToLongDHMS(long duration) {
StringBuffer res = new StringBuffer();
long temp = 0;
if (duration >= ONE_SECOND) {
temp = duration / ONE_DAY;
if (temp > 0) {
duration -= temp * ONE_DAY;
res.append(temp).append(" day").append(temp > 1 ? "s" : "")
.append(duration >= ONE_MINUTE ? ", " : "");
}
temp = duration / ONE_HOUR;
if (temp > 0) {
duration -= temp * ONE_HOUR;
res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
.append(duration >= ONE_MINUTE ? ", " : "");
}
temp = duration / ONE_MINUTE;
if (temp > 0) {
duration -= temp * ONE_MINUTE;
res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
}
if (!res.toString().equals("") && duration >= ONE_SECOND) {
res.append(" and ");
}
temp = duration / ONE_SECOND;
if (temp > 0) {
res.append(temp).append(" second").append(temp > 1 ? "s" : "");
}
return res.toString();
} else {
return "0 second";
}
}
public static void main(String args[]) {
System.out.println(millisToLongDHMS(123));
System.out.println(millisToLongDHMS((5 * ONE_SECOND) + 123));
System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR));
System.out.println(millisToLongDHMS(ONE_DAY + 2 * ONE_SECOND));
System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
System.out.println(millisToLongDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
+ (2 * ONE_MINUTE) + ONE_SECOND));
System.out.println(millisToLongDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
+ ONE_MINUTE + (23 * ONE_SECOND) + 123));
System.out.println(millisToLongDHMS(42 * ONE_DAY));
/*
output :
0 second
5 seconds
1 day, 1 hour
1 day and 2 seconds
1 day, 1 hour, 2 minutes
4 days, 3 hours, 2 minutes and 1 second
5 days, 4 hours, 1 minute and 23 seconds
42 days
*/
}
}
Take a look at the PrettyTime library.
You can check this Comparision of dates
import java.text.SimpleDateFormat;
import java.util.Date;
public class App {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
public static long ms, s, m, h, d, w;
static {
ms = 1;
s = ms * 1000;
m = s * 60;
h = m * 60;
d = h * 24;
w = d * 7;
}
public App() {
Date now = new Date();
Date old = new Date();
try {
old = sdf.parse("12-11-2013");
} catch (Exception e) {
e.printStackTrace();
}
long diff = now.getTime() - old.getTime();
if (diff < this.d) {
System.out.println("Today");
}
else if (diff > this.d && diff < this.d*2) {
System.out.println("Yesterday");
}
System.out.println("Difference: " + msToHms(diff));
}
public String msToHms(long ms) {
int seconds = (int) (ms / this.s) % 60 ;
int minutes = (int) ((ms / this.m) % 60);
int hours = (int) ((ms / this.h) % 24);
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
public static void main(String[] args) {
new App();
}
}
Output
Yesterday
Difference: 07:11:22
You have to implement your own logic based on the time difference and use the corresponding date format.
Lets assume you are getting a date from a server.
Get the device's time and compare to your date.
For your requirements there will be two cases.
The difference between the two date is less then a day, then return "Today" string.
The difference between the two date is grater then a day then use the Simple Date format to format your date as you want.
For comparing dates please see this entry: datecompare

Java console code for StopWatch/Timer?

I have the required code for the stopwatch here. All i want is get rid of the Swing part here and display the same output in console. Can anybody help?
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.text.*;
public class ElapsedTime extends JFrame
{
JLabel time;
long startTime = System.currentTimeMillis();
ElapsedTime()
{
setSize(380,200);
setTitle("http://simpleandeasycodes.blogspot.com/");
setLocation(100,100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridBagLayout());
time = new JLabel("");
time.setFont(new Font("SansSerif",Font.BOLD, 36));
time.setForeground(Color.MAGENTA);
add(time);
//starting new Thread which will update time
new Thread(new Runnable()
{
public void run()
{ try
{
updateTime();
}
catch (Exception ie)
{ }
}
}).start();
}
public void updateTime()
{
try
{
while(true)
{
//geting Time in desire format
time.setText(getTimeElapsed());
//Thread sleeping for 1 sec
Thread.currentThread().sleep(1000);
}
}
catch (Exception e)
{
System.out.println("Exception in Thread Sleep : "+e);
}
}
public String getTimeElapsed()
{
long elapsedTime = System.currentTimeMillis() - startTime;
elapsedTime = elapsedTime / 1000;
String seconds = Integer.toString((int)(elapsedTime % 60));
String minutes = Integer.toString((int)((elapsedTime % 3600) / 60));
String hours = Integer.toString((int)(elapsedTime / 3600));
if (seconds.length() < 2)
seconds = "0" + seconds;
if (minutes.length() < 2)
minutes = "0" + minutes;
if (hours.length() < 2)
hours = "0" + hours;
return minutes+":"+seconds;
}
public static void main(String[] args)
{
JFrame obj = new ElapsedTime();
obj.setVisible(true);
}
}
The keys are:
a.) Finding which character to write to the console in order to remove the most recently-written character (\b, or \010 in ASCII)
b.) Realising that you need to remember how many characters you've written to the console the last time you updated it
c.) Remembering to use print instead of println
public class Test {
public static void main(String[] args) throws InterruptedException {
int charsWritten = 0;
long start = System.currentTimeMillis();
while (1 > 0) {
Thread.sleep(1000);
long elapsedTime = System.currentTimeMillis() - start;
elapsedTime = elapsedTime / 1000;
String seconds = Integer.toString((int) (elapsedTime % 60));
String minutes = Integer.toString((int) ((elapsedTime % 3600) / 60));
String hours = Integer.toString((int) (elapsedTime / 3600));
if (seconds.length() < 2) {
seconds = "0" + seconds;
}
if (minutes.length() < 2) {
minutes = "0" + minutes;
}
if (hours.length() < 2) {
hours = "0" + hours;
}
String writeThis = hours + ":" + minutes + ":" + seconds;
for (int i = 0; i < charsWritten; i++) {
System.out.print("\b");
}
System.out.print(writeThis);
charsWritten = writeThis.length();
}
}
}
Note: you could be more efficient by only clearing the console up to only the characters you are changing but I figure you're not going to get that much of a speed improvement.
Have a look at StopWatch from Apache Commons. It should fulfill your needs.
Here's something that i have figured out myself a little while ago:
public class DelayExample{
static int i,j;
public static void main(String[] args){
for (j= 0; j>=0; j++)
{
for (i = 0; i < 60; i++)
{
System.out.println(j+":" + i);
try
{
Thread.sleep(1000);
}catch (InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}
}
}
Now i want the clear screen code in Java now. Also i think i have to use System.out.print() instead.
So there a Swing-free solution:
public class ElapsedTime{
long startTime = System.currentTimeMillis();
public ElapsedTime() {
try {
while (true) {
//Clear Console
for (int i = 0; i < 25; i++)
System.out.println();
// geting Time in desire format
System.out.println(getTimeElapsed());
// Thread sleeping for 1 sec
Thread.currentThread().sleep(1000);
}
} catch (Exception e) {
System.out.println("Exception in Thread Sleep : " + e);
}
}
public String getTimeElapsed() {
long elapsedTime = System.currentTimeMillis() - startTime;
elapsedTime = elapsedTime / 1000;
String seconds = Integer.toString((int) (elapsedTime % 60));
String minutes = Integer.toString((int) ((elapsedTime % 3600) / 60));
String hours = Integer.toString((int) (elapsedTime / 3600));
if (seconds.length() < 2)
seconds = "0" + seconds;
if (minutes.length() < 2)
minutes = "0" + minutes;
if (hours.length() < 2)
hours = "0" + hours;
return minutes + ":" + seconds;
}
public static void main(String[] args) {
new ElapsedTime();
}
}
I'm afraid there is no method to clear the console because Java is platform independant. I just insert 25 empty Lines so the last time disappears.

Categories