I need to display 4 "Toast"s spaced by 2 seconds between them.
How do I do this in such a way that they wait for each other and that the program itself waits until the last of them has displayed?
simply use handlers.
handler has a method called sendMessageDelayed(Message msg, long delayMillis).
just schedule your messages at the interval of 2 seconds.
here is a sample code.
int i=1;
while(i<5){
Message msg=Message.obtain();
msg.what=0;
hm.sendMessageDealayed(msg, i*2);
i++;
}
now this code will call handler's method handleMessage after every 2 seconds.
here is your Handler
Handler hm = new Handler(){
public void handleMessage(Message msg)
{
//Toast code.
}
};
and you are done.
Thanks.
Handlers are definitely the way to go but I would just postDelayed instead of handling an empty message.
Also extending Toast and creating a method for showing it longer is nice.
Sample Code:
// make sure to declare a handler in the class
private final Handler mHandler = new Handler();
// The method to show longer
/**
* Show the Toast Longer by repeating it.
* Depending upon LENGTH_LONG (3.5 seconds) or LENGTH_SHORT (2 seconds)
* - The number of times to repeat will extend the length by a factor
*
* #param number of times to repeat
*/
public void showLonger(int repeat) {
// initial show
super.show();
// to keep the toast from fading in/out between each show we need to check for what Toast duration is set
int duration = this.getDuration();
if (duration == Toast.LENGTH_SHORT) {
duration = 1000;
} else if (duration == Toast.LENGTH_LONG) {
duration = 2000;
}
for (int i = 1; i <= repeat; i++) {
// show again
handler.postDelayed(new Runnable() {
#Override
public void run() {
show();
}
}, i * duration);
}
}
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);
Ok, I have got following code from https://github.com/hongyangAndroid/Android-CircleMenu . Here, from print trace, I came to find that constructor is only invoked once, whereas run() method is recursively called till some condition.
My question is, why only run() method is recursively called from postDelayed(), why not constructor? and how variable anglePerSecond retains the value ? I want to understand it's flow. Thanks you.
//Automatic scrolling tasks
private class AutoFlingRunnable implements Runnable{
private float anglePerSecond;
public AutoFlingRunnable(float velocity){
this.anglePerSecond = velocity;
}
public void run(){
if((int)Math.abs(anglePerSecond) < 20){
isFling = false;
return;
}
isFling = true;
//anglePerSecond/30 in order to avoid rolling too fast
mStartAngle += (anglePerSecond/30);
//Gradually reduce this value
anglePerSecond /= 1.0666F;
postDelayed(this, 30);
//gradually reduce this value
requestLayout(); //re-layout views
}
}
When you want to update the textView in the Activity, for example , a textView with the countdowntimer, you normally update it with the following code
final int time = 50;
final TextView textView = new TextView(this);
textView.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
textView.setText(String.format("Remaing Time : %d s", time));
}
/*
* Update it after 1 second
* 1秒後更新
*/
},1000);
If you understand the above code, then try to understand the following
textView.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
textView.setText(String.format("Remaing Time : %d s", time));
/*
* Update it after 1 second
* 1秒後更新
*/
textView.postDelayed(this, 1000);
}
/*
* Update it after 1 second
* 1秒後更新
*/
},1000);
Actually, it is the same progress inside the library you provided.
It is dosing sth like that.
1.call AutoFlingRunnable consturctor to create
2.Method call in line 366
3.run the AutoFlingRunnable run() method
4.run the same runnable run() method after 0.03 second in line 574
5.back to step 3
I've made a simple Android music player. I want to have a TextView that shows the current time in the song in minutes:seconds format. So the first thing I tried was to make the activity Runnable and put this in run():
int position = 0;
while (MPService.getMP() != null && position<MPService.duration) {
try {
Thread.sleep(1000);
position = MPService.getSongPosition();
} catch (InterruptedException e) {
return;
}
// ... convert position to formatted minutes:seconds string ...
currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);
But that fails because I can only touch a TextView in the thread where it was created. So then I tried using runOnUiThread(), but that doesn't work because then Thread.sleep(1000) is called repeatedly on the main thread, so the activity just hangs at a blank screen. So any ideas how I can solve this?
new code:
private int startTime = 0;
private Handler timeHandler = new Handler();
private Runnable updateTime = new Runnable() {
public void run() {
final int start = startTime;
int millis = appService.getSongPosition() - start;
int seconds = (int) ((millis / 1000) % 60);
int minutes = (int) ((millis / 1000) / 60);
Log.d("seconds",Integer.toString(seconds)); // no problem here
if (seconds < 10) {
// this is hit, yet the text never changes from the original value of 0:00
currentTime.setText(String.format("%d:0%d",minutes,seconds));
} else {
currentTime.setText(String.format("%d:%d",minutes,seconds));
}
timeHandler.postAtTime(this,(((minutes*60)+seconds+1)*1000));
}
};
private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder rawBinder) {
appService = ((MPService.LocalBinder)rawBinder).getService();
// start playing the song, etc.
if (startTime == 0) {
startTime = appService.getSongPosition();
timeHandler.removeCallbacks(updateTime);
timeHandler.postDelayed(updateTime,1000);
}
}
what about this:
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
//your code
}
}, delay, period);
Use a Timer for this (instead of a while loop with a Thread.Sleep in it). See this article for an example of how to use a timer to update a UI element periodically:
Updating the UI from a timer
Edit: updated way-back link, thanks to Arialdo: http://web.archive.org/web/20100126090836/http://developer.android.com/intl/zh-TW/resources/articles/timed-ui-updates.html
Edit 2: non way-back link, thanks to gatoatigrado: http://android-developers.blogspot.com/2007/11/stitch-in-time.html
You have to use a handler to handle the interaction with the GUI. Specifically a thread cannot touch ANYTHING on the main thread. You do something in a thread and if you NEED something to be changed in your main thread, then you call a handler and do it there.
Specifically it would look something like this:
Thread t = new Thread(new Runnable(){
... do stuff here
Handler.postMessage();
}
Then somewhere else in your code, you do
Handler h = new Handler(){
something something...
modify ui element here
}
Idea its like this, thread does something, notifies the handler, the handler then takes this message and does something like update a textview on the UI thread.
This is one more Timer example and I'm using this code in my project.
https://stackoverflow.com/a/18028882/1265456
I think the below blog article clearly gives a very nice solution. Especially, if you are a background service and want to regularly update your UI from this service using a timer-like functionality.
It really helped me, much more than the 2007 blog link posted by MusiGenesis above.
https://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from-a-background-service/
Hi
In my android application i am using videoview.
I would like to start a timer and stop the player after 30 minutes.
I tried using the below code but the alert is displaying before the time is reached.
public final void timerAlert() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mVideoView.pause();
Alerts.ShowAlert("Cannot play",
"Subscribed time has been completed", context);
}
}, realtime);
Where realtime is the time after which i want the dialogue to be executed.
And am calling this in onprepared listener of player.
Please let me know if i require to change anything.
Please forward your valuable suggestions.
Thanks in advance :)
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 1) {
Log.d(tag, "Handling msg.");
// YOUR CODE GOES HERE..
// DISPLAY DIALOG..
msg.what = 2;
}
};
};
// USE HANDLER
mHandler.sendEmptyMessageDelayed(1, 30 * 60 * 1000); // 30 Minutes = 30 * 60 * 1000
First you create handler , processe Message : apply your logic here..
use handler to send delayed message after 30Minutes. ( See Comment)
Thanks :)