So I am trying to have a picture automatically refresh every 2 seconds. I've tried the handler/timer method, but I'm confused as how to call it and for some reason can not get it to actually refresh...
private void refreshPicture(final String refreshRate, final String userName, final String userPicture) {
final Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = Long.parseLong(refreshRate);
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
//my method where i refresh image
getUserPicture(userName, userPicture);
timerHandler.postDelayed(this, 500);
}
};
}
You forgot to initiate the first call of the runnable. After defining the timerRunnable, you have to call timerHandler.post(timerRunnable); once. Also, if you want to have it refreshed every 2 seconds, you have to put 2000 instead of 500 as value in postDelayed().
Don’t forget to call timerHandler.removeCallbacks(timerRunnable) when you want to stop refreshing.
Related
I got a fragment which got a control called RingProgress which is simply a ring that fills itself according to a percentage value given. For example, if I do:
ringProgress.setProgress(20);
It means that 20% of the ring will now be filled.
What I'm trying to do is to animate the ring being filled over a few seconds. So what I've tried to do is this:
#Override
public void onResume()
{
super.onResume();
HandlerThread handlerThread = new HandlerThread("countdown");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable()
{
#Override
public void run()
{
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
int totalSeconds = secondsToStart + minutesToStart * 60;
int secondsPassed = 0;
#Override
public void run()
{
if(secondsPassed == totalSeconds)
{
timer.cancel();
}
final int currentProgress = (secondsPassed / totalSeconds) * 100;
secondsPassed++;
getActivity().runOnUiThread(new Runnable()
{
#Override
public void run()
{
mRingProgressBar.setProgress(currentProgress);
}
});
}
}, 0, 1000);
}
});
}
The problem is that the update of the ring is not shown until the time is up. For example, if I set it for 5 seconds then when the fragment loads the ring is set to 0, then nothing happens for 5 seconds and then the ring is full with 100% all at once..
How can I start this animation properly?
I guess the problem is with
final int currentProgress = (secondsPassed / totalSeconds) * 100;
secondsPassed / totalSeconds return int value so it will be 0 or 1 only. And you multiply it to 100.
You have to use float or double instead
something like
final int currentProgress = Math.round(((float) secondsPassed)/((float) totalSeconds)*100f);
On this line:
Handler handler = new Handler(handlerThread.getLooper());
You are trying to get the looper from a handlerThread. But how sure you are the looper has already been initialized?
From the documentation of getLooper()
This method returns the Looper associated with this thread. If this thread not been started or for any reason is isAlive() returns false, this method will return null. If this thread has been started, this method will block until the looper has been initialized.
onLooperPrepared() is the callback, where you can be sure, that the Looper has been initialized, and therefore you can construct logics on that.
Thus, what you have to do, is to subclass HandlerThread and create appropriate logics from onLooperPrepared() callback.
Here's a nice post which will help you out. See implementation of MyWorkerThread class there.
Instead of using a handler, you could use a property animator as follows:
ObjectAnimator.ofInt(mRingProgressBar, "progress", 0, 100)
.setDuration(totalSeconds * 1000) //time is in miliseconds
.start();
This will find a method setProgress() in your mRingProgressBarand set the value according to the limits given. In the example above, 0 to 100.
You can read more about it here
Since you want to run on a different thread, you can use this handler in the top of the class:
private int progress = 0;
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
ringProgress.setProgress(progress);
progress += 20;
if (progress == 100) { //clear??
}
timerHandler.postDelayed(this, 1000);
}
};
In inCreate set the max:
ringProgress.setMax(100);
This will complete the animation within 5 seconds, then you can clear the animation. If you want smaller increments, change the line below (update every tenth of a second), and change the steps
timerHandler.postDelayed(this, 100);
I want to run a for loop every 5 minutes for an Android application. Is there a better method than this where less processing is done
for(;;) {
// code
final long NANOSEC_PER_SEC = 1000 * 1000 * 1000;
long startTime = System.nanoTime();
while ((System.nanoTime() - startTime) < 5 * 60 * NANOSEC_PER_SEC) {
}
}
CountDownTimer is a good class for this kind of work. It looks like this:
long duration = 12345;
long ticksInterval = 5000; // 5 second in millis
new CountDownTimer(duration, ticksInterval){
public void onTick(long remaining) {
// Do something each ticksInterval millis
}
public void onFinish() {
// Do something after duration millis
}
}.start();
That said, I don't think you can use this for an infinite amount of time since it requires an ending time. Though you can hack to restart it once it's finished.
You should go for set Repeat Alert for every 5 Minute and Run your code inside that .
Also you can go for use of Handler like below code .
final int REPEAT_CALL=2;
final int mFIVE_MINUTE=5*60*1000;
private Handler mHandler=new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case REPEAT_CALL:
//This will get execute by every 5 minute so write you for loop code here.
mHandler.sendEmptyMessageDelayed(REPEAT_CALL,mFIVE_MINUTE);
break;
}
}
};
You can start it by calling this :
mHandler.sendEmptyMessageDelayed(REPEAT_CALL,10);
Then after it will call by every 5 minute .
You can cancel this call back by calling below method:
mHandler.removeMessages(REPEAT_CALL);
I am using handler.postDelayed method to create some delay for some animation stuff.
Like this:
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
// Start Animation.
}
}, 6000);
Later, How can I get the remaining time until the animation starts?
You can simply save the time in a var when you call post delayed
long startTime = System.nanoTime();
h.postDelayed(...
and then when you need to check the remaining time you can calculate the elapsed time like
long elapsedTime = System.nanoTime()-startTime;
So in your case
long remainingTime = 6000 - elapsedTime;
I am using a Timer in my android app.
This is what i am using,
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
public void run()
{
//Called each time when 1000 milliseconds (1 second) (the period parameter)
runOnUiThread(new Runnable() {
public void run()
{
TextView tv = (TextView) findViewById(R.id.timer);
tv.setText(String.valueOf(time));
time += 1;
}
});
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);
In my code, there's only seconds as you can see But I want it in Minutes and seconds like 00:01.
So, how to do it. Please help me.
Thanks in Advance.
An approach to obtain the String you're looking for, would look like.-
int seconds = time % 60;
int minutes = time / 60;
String stringTime = String.format("%02d:%02d", minutes, seconds);
tv.setText(stringTime);
If you need to show the results only in your second Activity, I'd recommend passing time value into args bundle, and generate the String from the activity which will display it.
I'm trying to port a PC Java program to the Android platform. The PC application uses a Swing.Timer to trigger an update every second. The associated listener, upon being called, gets new data from a database, then updates/redraws the screen using Graphics2D. I've learned how to use Android's Canvas to draw the same things that I do with the PC application. Now I'm trying to learn how to use the equivalent Timer in Android. Unfortunately things don't seem as straightforward on the Android platform. There are Timers, Handlers, AlarmManagers, and AsyncTasks. It would seem that AsyncTasks and AlarmManagers are more appropriate for one time (heavy duty?) tasks (right? wrong?) With regard to Timers and Handlers, I've seen many posts that say don't use Timer, use Handlers instead. I found the approach used in the code below somewhere out there on the web and tried it. It seems like it should do what I want but it hangs the GUI whenever I click the stop button. Does anyone know why it does that?
Thanks times a million
Bill
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dateFormat = new SimpleDateFormat(dateFormatString);
mHandler = new Handler();
mUpdateTimeTask = new MyRunnable();
Button button = (Button) findViewById(R.id.start_button);
button.setOnClickListener(new MyStartListener());
button = (Button) findViewById(R.id.stop_button);
button.setOnClickListener(new MyStopListener());
}
class MyStartListener implements View.OnClickListener {
public void onClick(View v) {
if (startUptimeMillis == 0L) {
startUptimeMillis = SystemClock.uptimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
};
class MyStopListener implements View.OnClickListener {
public void onClick(View v) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
};
class MyRunnable implements Runnable {
public void run() {
final long start = startUptimeMillis;
long millis = SystemClock.uptimeMillis() - start;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
TextView tv = (TextView) findViewById(R.id.time_textView);
tv.setText(dateFormat.format(calendar.getTime()));
mHandler.postAtTime(this, (((minutes * 60) + seconds + 1) * 1000));
}
};
EDIT:
The problem is that postAtTime needs an absolute time at which to start, not a delay which is what my example is using. (See postAtTime here)
So I replaced all of the timing code above with the below and it does what I want!!:
long millis = SystemClock.uptimeMillis();
mHandler.postAtTime(this, millis+1000);
I don't see how this could hang your app, unless you mean the start button doesn't work any more... Perhaps you want to add this to your stop listener:
public void onClick(View v) {
startUptimeMillis = 0l; // Reset startUptimeMillis
mHandler.removeCallbacks(mUpdateTimeTask);
}
As far as Timers, AsyncsTask, etc... You are correct, the best way to program an event in the near future in Android is with a Handler and Runnable. AlarmManagers are not intended for fast callbacks like in animations and AsyncTasks are better for heavy duty computation.
I would like a to offer a simpler update Runnable:
class MyRunnable implements Runnable {
public void run() {
// You should make this a class variable and initialize it in onCreate(),
// there is no need to search for the same View every second.
TextView tv = (TextView) findViewById(R.id.time_textView);
final long now = System.currentTimeMillis();
tv.setText(dateFormat.format(now));
mHandler.postAtTime(this, 1000 - (now - start) % 1000); // Accounts for millisecond offsets over time
// mHandler.postDelayed(this, 1000); // Effected by minute offsets
}
};