I'm making this app that tells how much longer till we reach a destination but whenever I try to use it it just black screens just crashes. I think it has something to do with the loop but I can't find anything online Can anyone help? Thanks in advance.................................................................................................................
package com.example.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.util.Calendar;
import java.util.TimeZone;
import java.time.*;
import java.math.*;
public class TimeTIll extends AppCompatActivity {
private static final String DateUtils = null;
TextView txt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time_till);
txt = (TextView) findViewById(R.id.TimeDipslay);
int i = 0;
while (i < 10) {
Program();
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public void Program() {
int totalMinutesSinceMidnight = 0;
long ms = 0;
long secondsM = 0;
long SecondsTillEstimate = 0;
long SecondsTillArrival1 = 0;
double MinutesTillArrival = 0;
double hoursTillArrival = 0;
double SecondsTillArrival = 0;
Calendar now = Calendar.getInstance();
Calendar midnight = Calendar.getInstance();
midnight.set(Calendar.HOUR_OF_DAY, 0);
midnight.set(Calendar.MINUTE, 0);
midnight.set(Calendar.SECOND, 0);
midnight.set(Calendar.MILLISECOND, 0);
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
now = Calendar.getInstance();
midnight = Calendar.getInstance();
ms = now.getTime().getTime() - midnight.getTime().getTime();
totalMinutesSinceMidnight = (int) (ms / 1000);
secondsM = totalMinutesSinceMidnight;
SecondsTillEstimate = (60 * 60 * 23);
SecondsTillArrival1 = SecondsTillEstimate - secondsM;
hoursTillArrival = Math.floor(SecondsTillArrival1 / 3600);
SecondsTillArrival1 -= (hoursTillArrival * 3600);
MinutesTillArrival = Math.floor(SecondsTillArrival1 / 60);
SecondsTillArrival1 -= (MinutesTillArrival * 60);
SecondsTillArrival = SecondsTillArrival1;
txt.setText((int) hoursTillArrival + " Hours " + (int) MinutesTillArrival + " Minutes " + (int) SecondsTillArrival + " Seconds Till Arrival In Floriada");
}
}
Please read about the activity life-cycle. You cannot call long-running tasks in onCreate and expect them to show anything other than an ANR crash (your onCreate method blocks the UI thread with all those sleep statements and generates an ANR crash before it even gets to the onStart and onResume stages where it actually shows the activity).
If you want the UI to change dynamically, you could use a handler to execute a method at a regular interval. For example, to update something at a regular interval (1000 ms here) you could do:
public class MainActivity extends AppCompatActivity {
private final Handler handler = new Handler();
private TextView txt;
private int count = 0;
private final int updateFreqMs = 1000; // call update every 1000 ms
#Override
protected void onPause() {
super.onPause();
handler.removeCallbacksAndMessages(null);
}
#Override
protected void onResume() {
super.onResume();
handler.postDelayed(new Runnable() {
#Override
public void run() {
updateTime();
handler.postDelayed(this, updateFreqMs);
}
}, updateFreqMs);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time_till);
txt = findViewById(R.id.TimeDipslay);
}
private void updateTime() {
// here you update the displayed value
// this will be called every second indefinitely
// do your math and generate a string to print, just showing
// a counter here to demonstrate
++count;
txt.setText("Count = " + count);
}
}
I think that the problem is that you are trying to make sleep the main thread of the application. In Android I knew that for security reasons this can't be done.
(Look this https://www.codementor.io/tips/0743378261/non-freezing-sleep-in-android-app for details )
Try this solution instead:
How to pause / sleep thread or process in Android?
You Shouldn`t use it inside main thread specially when you are doing operation inside it.
You may have to use some thing like that.
viewModelScope.launch(Dispatchers.IO) {
while (statues==true){
if (statue==true){
delay(500)
//ToDo
}
}
}
Related
I am developing one android application and on one screen i have Listview with countdown timer on each row. I am using List Adapter. I tried Google and other reference but not getting actual output. I have seconds returned from web-service, I am converting seconds to hh:mm:ss format and started countdown timer using CountdownTimer class. but when i am scrolling Listview it changes behavior, I know this is the common problem for android Listview but i want to display countdown timer on each row with complete moving time second by second.
Please help me friend, Thanks in advance.
meh from this thread here gave a good advice.
From within the CountDownTimer, don't update the textviews in the listview-item directly, but update some String in the data-objects from the adapter. Afterwards let another separate CountDownTimer call adapter.notifyDataSetChanged() to let the listitem-views update themselves. I call this one adapterNotifier in code.
The adapterNotifier alone should call adapter.notifyDataSetChanged() to avoid the additional overhead if every other single CountDownTimer would itself call adatper.notifyDataSetChanged().
In the getView()-method from the adapter, don't do anything fancy, only read the pre-computed strings from the data-object and update the textviews as usual.
The main drawback to this approach is, that you update the whole of every listitem, which could be overkill if you have e.g. network-loaded images in the listitems. I will try to optimize this further.
Here is some code
public Adapter(Context context, ListData dataList) {
super(context, dataList);
this.dataList = dataList;
initTimerData(dataList);
}
private void initTimerData(ListData dataList) {
long longestTimerInterval = 0;
for (final Data data : dataList) {
if (data.show_timer) {
if (data.end_time == null) {
data.show_timer = false;
continue;
}
long endTimeMillis = 0;
try {
endTimeMillis = dataDateTimeProcessor.parse(data.end_time).getTime();
} catch (ParseException e) {
Log.e(DataDetailFragment.class.getSimpleName(), "Error parsing data-time: ", e);
}
// TODO use the server-time for reliability
long nowTime = System.currentTimeMillis();
long timeInterval = endTimeMillis - nowTime;
// if the data is over or more than 24 hours away, don't display the timer
if (nowTime >= endTimeMillis ||
timeInterval > 24 * 3600 * 1000) {
data.show_timer = false;
continue;
}
// save the longest interval for an extra adapter-notifier timer
if (timeInterval > longestTimerInterval)
longestTimerInterval = timeInterval;
// this listener holds the references to the currently visible data-timerviews
DataCountDownTimerListener timerListener = new DataCountDownTimerListener() {
#Override
public void onTick(long millisUntilFinished) {
int seconds = (int) ((millisUntilFinished / 1000) % 60);
int minutes = (int) ((millisUntilFinished / (60000)) % 60);
int hours = (int) ((millisUntilFinished / (3600000)) % 24);
data.timerSeconds = String.format("%02d", seconds);
data.timerMinutes = String.format("%02d", minutes);
data.timerHours = String.format("%02d", hours);
}
#Override
public void onFinish() {
data.timerSeconds = "00";
data.timerMinutes = "00";
data.timerHours = "00";
}
};
if (data.endTimer != null) {
Utils.stopDataTimer(data);
}
data.endTimer = new DataCountDownTimer(timeInterval, 1000);
data.endTimer.setDataCountDownTimerListener(timerListener);
data.endTimer.start();
} else {
data.show_timer = false;
}
}
initAdapterNotifier(longestTimerInterval);
}
private void initAdapterNotifier(long longestTimerInterval) {
// no timers here, go away
if (longestTimerInterval == 0)
return;
adapterNotifier = new DataCountDownTimer(longestTimerInterval, 1000);
DataCountDownTimerListener adapterNotifierListener = new DataCountDownTimerListener() {
#Override
public void onTick(long millisUntilFinished) {
// TODO evaluate performance
// update the adapter-dataset for timer-refreshes
notifyDataSetChanged();
}
#Override
public void onFinish() {
// last timer finished, nothing to do here
}
};
adapterNotifier.setDataCountDownTimerListener(adapterNotifierListener );
adapterNotifier.start();
}
public void stopDataTimers() {
if (adapterNotifier != null)
adapterNotifier.cancel();
for (Data data : dataList) {
if (data.endTimer != null) {
Utils.stopDataTimer(data);
}
}
}
you can create a class that will handle your timer in each row. I mean a reusable class. you already created a class to make your timer then utilize it.In that class, you should be able to monitor your listview item so that the timer will continue to run. you can reference the id of that listitem.
hope it gives you some hint
The timer works fine for starting then reseting and leaving the view, but if I start the time then leave the view and return and just hit Reset the app crashes. I know that most people would not hit reset when the timer is not started, but for idiot proofing I need a fix for this any suggestions?
public void startTimer(View view) {
final Handler handler = new Handler();
Timer ourtimer = new Timer();
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
int sec = n % 60;
int min = n / 60;
TextView timer = (TextView) findViewById(R.id.androidtimer);
timer.setText("" + String.format("%02d", min) + ":"
+ String.format("%02d", sec));
// timer.setText(n + " Seconds");
n++;
}
});
}
};
ourtimer.schedule(timerTask, 0, 1000);
}
public void stopTimer(View view) {
timerTask.cancel();
TextView timer = (TextView) findViewById(R.id.androidtimer);
timer.setText("--:--");
timerTask = null;
n = 0;
}
I think your problem is that timerTask is null as long as you do not start the timer.
So a simple if clause might help. If that's not the problem please post the exception.
public void stopTimer(View view) {
if(timerTask != null) {
timerTask.cancel();
}
TextView timer = (TextView) findViewById(R.id.androidtimer);
timer.setText("--:--");
timerTask = null;
n = 0;
}
My intention is to create an timer which starts from 00:00:00 and hangs together with a recording function. This recording is done in a service so, the timer is also in the same service. If the app moves to the background, the recording and thus the timer keep on going and the app picks the time up at the onResume with a myService.getTime().
But I experience two strange things. The first is that my timer sometimes goed faster than a second, sometimes slower, sometimes jumps from for example 00:00:04 to 00:00:06 etc. There is no consitency in it. I use the code below, but there might be a better option to solve this? The second is that it is causing a lag on my button, although I am starting it in a service?
SERVICE
//////////TIMER FUNCTION START//////////
private void startTimerClick() {
if (stopped) {
startTime = System.currentTimeMillis() - elapsedTime;
} else {
startTime = System.currentTimeMillis();
}
mHandler.removeCallbacks(startTimer);
mHandler.postDelayed(startTimer, 0);
}
private void pauseTimerClick() {
mHandler.removeCallbacks(startTimer);
stopped = true;
}
private void stopTimerClick() {
mHandler.removeCallbacks(startTimer);
stopped = false;
}
private void startTimer() {
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;
}
}
//////////TIMER FUNCTION END////////////
public String getHours(){
return hours;
}
public String getMinutes(){
return minutes;
}
public String getSeconds(){
return seconds;
}
}
ACTIVITY(/FRAGMENT)
private void timerStart() {
handler = new Handler();
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
handler.post(new Runnable() {
#Override
public void run() {
timer.setText(myService.getHours()+":"+myService.getMinutes()+":"+myService.getSeconds());
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
}
You are using Threads both in your Service and in your Activity/Fragment code.
Using threads for time sensitive tasks in Android is a problem because Android is able to significantly delay threads.
I have been using a ScheduledThreadPoolExecutor for a similar task and it worked great.
You are then using it like this:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); // where 1 is the number of needed concurrent threads. 1 should last for your needs.
executor.scheduleWithFixedDelay(new TimerTask() {
// your recurringly executed code here
}, 0, 1, TimeUnit.SECONDS);
I am trying to make view of random text 3 times with time pausing between.
I just can't! It all run all together. I admit I don't know thread subject at all, I just need simple solution.
public void loading3() {
Random randomDouble = new Random();
temp = (double) randomDouble.nextInt(100);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
result.setText(temp + "%");
}
This is the code. I want to use it let's say 3-4 times in a row. How can i do it? I try inside loop or writing same methods in a row but it won't work because it doesn't wait for the first method to end before start the new one.
You should not sleep on the main thread. This can easily be done with a Handler or Timer. Here is an example with a Handler:
private int mCount = 0;
private Handler mHandler = new Handler();
private Runnable mUpdater = new Runnable() {
public void run() {
Random randomDouble = new Random();
temp = (double) randomDouble.nextInt(100);
result.setText(temp + "%");
mCount++;
if (mCount < 3)
mHandler.postDelayed(mUpdater, 1000);
}
}
public void loading3() {
mHandler.postDelayed(mUpdater, 1000);
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
public class MainActivity extends Activity {
private Button Start, Reset, Stop;
private EditText stop_watch, lblDate, lblTime;
public MainActivity() {
init();
}
private final UpdateClockThread ucThread = new UpdateClockThread();
private final StopwatchThread swThread = new StopwatchThread();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Start = (Button)findViewById(R.id.button1);
Stop = (Button)findViewById(R.id.button3);
Reset = (Button)findViewById(R.id.button2);
stop_watch = (EditText)findViewById(R.id.editText3);
lblTime = (EditText)findViewById(R.id.editText2);
lblDate = (EditText)findViewById(R.id.editText1);
Start.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
startactionPerformed();
}
});
Stop.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
stopactionPerformed();
}
});
Reset.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
resetactionPerformed();
}
});
}
public void init() {
swThread.setDaemon(true);
ucThread.setDaemon(true);
swThread.start();
ucThread.start();
}
/** Listens to the Start/Stop/Resume button. */
void startactionPerformed() {
swThread.go();
//init();
}
void stopactionPerformed() {
swThread.noGo();
}
void resetactionPerformed() {
swThread.reset();
}
/** A thread that updates the current date & time. */
private class UpdateClockThread extends Thread {
/** The actual work of the thread. */
public void run() {
while (true) {
lblTime.setText("ampm");
Calendar now = Calendar.getInstance();
String month = Integer.toString(now.get(Calendar.MONTH)+1);
String date = Integer.toString(now.get(Calendar.DAY_OF_MONTH));
String year = Integer.toString(now.get(Calendar.YEAR));
String hour = Integer.toString(now.get(Calendar.HOUR));
if (hour.equals("0")) hour = "12";
String minute = Integer.toString(now.get(Calendar.MINUTE));
if (minute.length() == 1) minute = "0" + minute;
String second = Integer.toString(now.get(Calendar.SECOND));
if (second.length() == 1) second = "0" + second;
String ampm = now.get(Calendar.AM_PM) == Calendar.AM ? "AM" : "PM";
lblDate.setText(month + "/" + date + "/" + year);
lblTime.setText(hour + ":" + minute + ":" + second + " " + ampm);
try {
sleep(500);
} catch (InterruptedException e) {}
}
}
}
/** A thread that keeps track of the stop watch & updates
* the display accordingly.
*/
class StopwatchThread extends Thread {
/** Whether or not stop watch is running. */
private boolean going = false;
/** Stores elapsed milliseconds of previous runs. */
private long prevElapsed = 0;
/** Stores beginning time of this run. */
private Date startDate = new Date();
/** Returns elapsed time in milliseconds.
*#return The elapsed time
*/
private long elapsedTime() {
return prevElapsed + (going ? new Date().getTime() - startDate.getTime() : 0);
}
/** Changes the number of elapsed milliseconds into a string.
*#param time Number of elapsed milliseconds
*#return The elapsed time as a string.
*/
private String msToString(long time) {
String ms, sec, min;
if (time % 10 >= 5) //round to nearest hundredth
time += 5;
ms = Long.toString(time % 1000);
while (ms.length() < 3)
ms = "0" + ms;
ms = ms.substring(0, ms.length() - 1);
time /= 1000;
sec = Long.toString(time % 60);
if (sec.length() == 1) sec = "0" + sec;
time /= 60;
min = Long.toString(time);
return min + ":" + sec + "." + ms;
}
/** Called when the stop watch is to go.
*/
public void go() {
startDate = new Date();
going = true;
}
/** Called when the stop watch is to stop.
*/
public void noGo() {
prevElapsed = elapsedTime();
going = false;
}
/** Resets the stop watch.
*/
public void reset() {
going = false;
prevElapsed = 0;
}
/** Adds a lap to the list.
*/
/** Main code of the thread.
*/
public void run() {
while (true) {
stop_watch.setText(msToString(elapsedTime()));
yield();
}
}
}
}
What is my app getting force close? There is some error with the thread. But i'm not able to figure it out?
Try make all interaction with UI from threads in runOnUiThread method of Activity http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
EDIT
private class UpdateClockThread extends Thread {
public void run() {
/* Do somthing expensive */
......
/* Update UI */
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
/* Do UI update */;
lblTime.setText("ampm");
......
}
});
}
}
You should run adb logcat on your developer machine. Usually if you get a force close a traceback is displayed in the log.
Your class StopwatchThread contains the line:
stop_watch.setText(msToString(elapsedTime()));
This will not work, and neither will the UI updates within UpdateClockThread. This is because you cannot modify the UI from a background thread. Your background thread should either:
send a message to a Handler that has been created on the UI thread, so that the Handler then makes the update to the UI, or
you can pass a runnable into runOnUiThread that performs the UI update.