I get notification with socket.io to start a countdown timer in my android app. I use a Handler to send data from the socket.io callbacks to the UI thread. Handler messages work perfect. But starting the countdown timer from the handler doesn't work (onTick() function won't called). If I start it with the UI element, everything is ok. What is the best way to do it, when the countdown timer is operated not from the UI thread?
mHandler = new Handler(){
public void handleMessage(Message inputMessage) {
mBattle = (Battle) inputMessage.obj;
switch (inputMessage.what) {
case NO_BATTLE:
System.out.println("got message NO_BATTLE");
break;
//.................
case START_BATTLE:
startCountdownTimer(mBattle.getCountdown());
System.out.println("got message START_BATTLE");
break;
}
}
and the countdown timer function:
private void startProgressBar(final int time){
if (time != 0) {
new CountDownTimer(time, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.v("Log_tag", "Tick of Progress " + i + " " +
+ millisUntilFinished);
i++;
}
#Override
public void onFinish() {
i=0;
}
}.start();
}
Did you print out the value of time when it's not working? If time < SystemClock.elapsedRealtime() + 1000, then onFinish will be called without calling the onTick.
Related
I want to implement a timer in my application if user click clock in button timer should start from device time and the timer should run when giving pause timer should pause when user click stop timer should stop, Please help me.
for example, now time is 13:20:10 user click means timer should run on this time not from 00, normal timer code I have, but based on the current time it should run.
you can try this. call start()/stop() when you want to start/stop timer. if you want to update UI (Main)Thread use runOnUiThread(https://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)) or handler for update UI Thread
import java.util.Calendar;
int hou=0;
int min=0;
int sec=0;
boolean stopTimer=false;
private void initTimer()
{
Date currentTime = Calendar.getInstance().getTime();
hou=currentTime.getHours();
min=currentTime.getMinutes();
sec=currentTime.getSeconds();
Log.e("Initial Timer ","hou"+hou+ " min"+min+" sec"+sec);
startTimerThread();
}
private void startTimerThread()
{
new Thread()
{
public void run()
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
updateTimer();
}
}.start();
}
private void updateTimer()
{
if(!stopTimer)
{
sec=(((++sec)%60)==0)?0:sec;
min=(sec==0)?(((++min)%60==0)?0:min):min;
hou=(min==0)?((++hou)):hou;
/*hou%=12;*/
Log.e("Update Timer ","hou"+hou+ " min"+min+" sec"+sec);
startTimerThread();
}
}
public void start()
{
initTimer();
}
public void stop()
{
stopTimer=false;
}
you can try this using by using countdowntimer like this :
CountDownTimer timer = new CountDownTimer(1000000000, 1000) {
public void onTick(long millisUntilFinished) {
Calendar c = Calendar.getInstance();
Log.v(TAG , "CountDownTimer : " + c.get(Calendar.HOUR)+":"+c.get(Calendar.MINUTE)+":"+c.get(Calendar.SECOND));
}
public void onFinish() {
}
};
timer.start();
on pause you can cancel it like this:
timer.cancel();
i have take three button, first start button click on device time show in textview and it update as per device time. when click on paused button stop time update. and when click on restart time device time when start to stop.
mBtnStartTime?.setOnClickListener {
val someHandler = Handler(mainLooper)
someHandler.postDelayed(object : Runnable {
override fun run() {
mTvTime?.text = SimpleDateFormat("HH:mm:ss", Locale.US).format(Date())
someHandler.postDelayed(this, 1000)
}
}, 10)
mBtnPaused?.setOnClickListener {
someHandler.removeCallbacksAndMessages(null)
}
mBtnRestart?.setOnClickListener {
someHandler.postDelayed(object : Runnable {
override fun run() {
mTvTime?.text = SimpleDateFormat("HH:mm:ss", Locale.US).format(Date())
someHandler.postDelayed(this, 1000)
}
}, 10)
}
what I'm trying to do:
My app connects with a Bluetooth accelerometer and gets acceleration data every 50ms. I want to check for these with a Runnable. And this worked fine. However, for the complete app I added two CountDownTimers:
1) introTimer(), which runs in an AlertDialog and counts down from 3. OnFinish() calls (i) my Runnable, that deals with new acceleration data and (ii) a second timer called
2) mainTimer(), which counts down from 20 and refreshes a TextView on the UI.
My problem is, that my Runnable is only executed once when it is first called. Why is that? Apparently I have not yet understood the threading principles behind this. My next step (probably going to be complicated) is to refresh ImageViews every 50ms (or maybe less often, but still with a relatively high frequency) on the UI, depending on the accelerometer data.
I have thought about deleting the Runnable and putting my calculations in the CountDownTimer, but this might be difficult or inaccurate with the timing/frequency/periods. What do you think?
Here are the code parts. If you think other parts are relevant, I can post them as well:
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
View promptView = layoutInflater.inflate(R.layout.intro_timer_prompt, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final TextView introTimer = (TextView) promptView.findViewById(R.id.introTimer);
builder.setView(promptView);
AlertDialog alertD = builder.create();
alertD.show();
introTimer(introTimer, alertD);
}
private void introTimer(final TextView introTimer, final AlertDialog alertD) {
new CountDownTimer(4*1000, 1000) {
public void onTick(long millisUntilFinished) {
introTimer.setText( ""+ (millisUntilFinished / 1000));
}
public void onFinish() {
alertD.cancel();
// mainTimer();
clearArrayLists();
mHandler = new Handler();
mHandlerTask.run();
mainTimer();
}
}.start();
}
private void mainTimer() {
new CountDownTimer((int)DURATION*1000, 10) {
public void onTick(long millisUntilFinished) {
//mTimerView.setText("seconds remaining: " + millisUntilFinished / 1000 + ":" + millisUntilFinished / 1000. );
long millisecs = Math.round(millisUntilFinished % 1000 / 100);
mTimerView.setText("seconds remaining: " + millisUntilFinished / 1000 + ":" + millisecs );
}
public void onFinish() {
String energy = new DecimalFormat("#.##").format(accumulatedKineticEnergy.get(accumulatedKineticEnergy.size()-1));
mTimerView.setText("Accumulated Energy is " + energy + " Joule.");
}
}.start();
}
Runnable mHandlerTask = new Runnable() {
#Override
public void run() {
Log.i(TAG, "executed only once :( ");
if (a_x.size() < DURATION/INTERVAL) {
try {
calcAccList();
//...calc things...;
mHandler.postDelayed(this, (long) (1000*INTERVAL));
} catch (Exception e) {
e.getMessage();
}
}
else {
mHandler.removeCallbacks(mHandlerTask);
}
}
};
A countdown timer doesn't repeat itself when it expires, but you need to start it again. Maybe you can use the AlarmManager in this case to have a better design.
first of all, I'm a beginner to android world so please apologize me if it is stupid question..
I'm trying to do following:
Enable Mobile Data
Wait for 10 seconds
a. check if Mobile got IP address (data connected sucessfully)
b. if Not connected,Disable Data
c. Go to step 1
And these steps 1 to 3 are getting executed in For loop for User Given number of retries.
Now my problem is: I'm stuck at step No. 2. I'm unable to make waitfor(int seconds) function. I tried using Runnable PostDelayed method but it is not giving me required output.
for(retry = UserChoice; retry > 0 && !isDataAvailable ; retry -- ){
enableInternet()
delay(10)
isDataAvailable = GetInternetAvailibility()
if(!isDataAvailable){
disableInternet()
}
}
I tried to put isDataAvailable = GetInternetAvailibility() statement in postDelayed of handler but it is causing enableInternet() disableInternet() to execute at the same time while isDataAvailable = GetInternetAvailibility() gets executed after delay.
I can see from logs, that enableInternet() executes for UserChoice number of times without any delay.
Thread.sleep(10000) just freezes the UI for 10 seconds... How do I achieve this?
EDIT : Let me clear :
public void onClick(View v) {
// Perform action on click
for(i=0; i<3; i++ ){
System.out.println("Before..");
delay(5);
System.out.println("after..");
}
}
public void delay(int seconds){
milliseconds = seconds * 1000;
runOnUiThread(new Runnable() {
#Override
public void run() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
System.out.println("XXX"); //add your code here
}
}, milliseconds);
}
});
}
Now whenever I click button I can see in logs that System.out prints message as:
Before
afterBefore
afterBefore
after
XXXXXXXXX
But I want:
Before
XXX
After.Before
XXX
After.Before
XXX
After.
try this:
public void check() {
isDataAvailable = GetInternetAvailibility()
if (!isDataAvailable) {
disableInternet();
enableInternet();
if (retry > 0) {
retry--;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
check();
}
}, 10000);
}
}
}
This way may help you.
http://developer.android.com/reference/android/os/CountDownTimer.html
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
Try Below code.Hope that it will help
int i = 0;
int j = 3;
method() {
if (i < j) {
System.out.println("Before..");
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
System.out.println("XXXXXX");
i++;
System.out.println("after");
method();
}
}, 1000);
}
}
I tried to put isDataAvailable = GetInternetAvailibility() statement
in postDelayed of handler but it is causing enableInternet()
disableInternet() to execute at the same time while isDataAvailable =
GetInternetAvailibility() gets executed after delay.
Put the if statement and disableInternet() in the postDelayed. enableInternet will get called, 10 seconds later it will check to see if the internet is available, if not it will disableInternet.
I know this sort of question exists but I'm confused here. I'm using this code:
public class NewWaitAppActivity extends Activity {
private Handler mHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mHandler = new Handler();
lcmgr = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
Thread LocThread = new Thread(mLocationUpdater);
Log.d("TAG","About to start worker thread");
LocThread.start();
}
public void startTimer(View v) {
if (mStartTime == 0L) {
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
long millis = System.currentTimeMillis() - start;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
TextView timer = (TextView) findViewById(R.id.time_elapsed);
if (seconds < 10) {
timer.setText("" + minutes + ":0" + seconds);
} else {
timer.setText("" + minutes + ":" + seconds);
}
mHandler.postDelayed(this, 1000);
}
};
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
mStopTimer();
}
};
private Runnable mLocationUpdater = new Runnable(){
public void run(){
Log.d("TAG","Inside worker thread");
lcmgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
};
}
I am basically trying to stop the timer of the main thread when a location updates. The application doesn't even start, it gives the error mentioned above during runtime. The error is due to requestLocationUpdates(). It seems like I can't call stopTimer() inside onLocationChanged(). How can I correct this?
No need to even write a complicated solution:
locationManager.requestLocationUpdates(provider, 5000, 0, mylistener, Looper.getMainLooper());
This will work just fine.
whats the need of calling "lcmgr.requestLocationUpdates(....)" from the thread you created, when it is itself an asynchronous callback based mechanism?Just move this code in the onCreate() of your activity and things should work fine.Also this error comes when you try to create a handler inside a thread which is not intended to loop at all (ie. the threads that dont call Looper.prepare, as your stack trace states also). More explanation about this error can be found in this site also.But a good explanation is also given here. http://www.aviyehuda.com/2010/12/android-multithreading-in-a-ui-environment/
You can't access/generate Event thread specific events, and you don't need to request location updates in a thread, instead you can use service to achieve the same.
I use the following code to update a timer in my UI.
The problem with this code however, is that with each second passed, it updates by +1 second.
I think I understand why this happens, however I don't know how to fix it.
private Handler mHandler = new Handler();
....
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
mDifference = System.currentTimeMillis() - mStartTime;
workSum = workSum + mDifference;
TextViewTime.setText("Time so far: " + formatTime(workSum));
mHandler.postDelayed(this, 1000);
}
};
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_button:
startButton.setEnabled(false);
stopButton.setEnabled(true);
if (mStartTime == 0L) {
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 1000);
}
Help would be greatly appreciated!
workSum = workSum + mDifference; seems to be your problem, because mDifference is incrementing each time.
I think workSum = mDifference; will solve it, or even
mDifference = System.currentTimeMillis() - mStartTime;
TextViewTime.setText("Time so far: " + formatTime(mDifference));