Hi i'm running an animation and after 2 seconds i want to stop it and close the whole application.
This is my animation:
public void onImageButtonOkClick(View view) {
setContentView(R.layout.success);
final ImageView mAnimLogo = (ImageView) findViewById(R.id.loading_image);
final AnimationDrawable mAnimation = (AnimationDrawable) mAnimLogo.getDrawable();
mAnimLogo.post(new Runnable() {
#Override
public void run() {
mAnimLogo.setVisibility(View.VISIBLE);
mAnimation.start();
}
});
}
and i tried to use finish() after a timer was called - the application closed, but without any animations.
Any Suggestions?
Edit:
public void delay() {
Timer timer = new Timer();
try {
synchronized(timer){
timer.wait(2000);
getParent().finish();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i solved this problem by using a recursive function to check the animation
private void checkAnimation(AnimationDrawable animationDrawable){
final AnimationDrawable animation = animationDrawable;
int timeBetweenChecks = 300;
Handler h = new Handler();
h.postDelayed(new Runnable(){
public void run(){
if (animation.getCurrent() != animation.getFrame(animation.getNumberOfFrames() - 1)){
checkAnimation(animation);
} else{
finish();
}
}
}, timeBetweenChecks);
};
Related
I have a code that plays 5 sounds with 1 second delay between the sounds and I want this part of code to be executed every 5 seconds (so it will run in a row so far as a boolean variable is true, and when it becomes false the tread run stopped - I have a button to both start and stop this executions). Everything works perfectly, but the issue is that I can't get rid of the 5 seconds delay in the first time I click the button, so when I first click, the sounds beggins only after 5 seconds. How can I make it start right away and only after the first time start taking the delays?
Here is the button onClick code:
public void clickHandlerStartTempo(final View view) {
if (!tempoOn) {
Toast toast = Toast.makeText(getApplicationContext(), "Start Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = true;
final Handler handler = new Handler();
final int delay = 5000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
if (tempoOn) {
runCode(view);
handler.postDelayed(this, delay);
}
}
}, delay);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "Stop Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = false;
}
}
And here is the runCode method:
public void runCode(View view) {
Runnable runnable = new Runnable() {
#Override
public void run() {
playSound(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 4; i++) {
if (tempoOn) {
playSound(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
return;
}
}
}
};
Thread thread = new Thread(runnable);
Log.i(TAG, "runCode: Thread id = " + thread.getId());
thread.start();
}
I'm new to android development and any help would be very much appreciated.
Thanks.
First you need to playsound without thread after that you will execute your reaming 5 second logic stop thread after 4 count.
public void onStartPress(){
playSound();
someMethod();
}
public void someMethod(){
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
playSound();
someMethod();
}
},1000);
}
Don't use actual Threads unless you really want to do something off the Ui thread. Most of the time you do want to keep things on the Ui thread.
For simple repeating tasks, you can easily repurpose the CountDownTimer class. Often with an (almost) infinite run time or Long.MAX_VALUE (292 million years). The fist onTick happens immediately after starting.
private CountDownTimer mTimer;
private void start() {
if (mTimer == null) {
mTimer = new CountDownTimer(Long.MAX_VALUE, 5000) {
#Override
public void onTick(long millisUntilFinished) {
// start a beeping countdown
new CountDownTimer(5000, 1000) {
private int state = 1;
#Override
public void onTick(long millisUntilFinished) {
playSound(state);
state = state + 1 % 2;
}
#Override
public void onFinish() {
playSound(0);
}
}.start();
}
#Override
public void onFinish() { /* ignore, never happens */ }
};
mTimer.start();
}
}
private void stop() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}
How to make a picture that would be updated every 30 seconds ?
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Picasso.with(this).load("http://i.imgur.com/DvpvklR.png").memoryPolicy(MemoryPolicy.NO_CACHE).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
You are going to want to use something like a thread to do this.
For example, below your image view:
Runnable imageUpdater = new Runnable() {
#Override
public void run() {
while (true) {
try {
sleep(30000); // 30 seconds in milliseconds
} catch(InterruptedException e) {
// Someone called thread.interrupt() and tried
// to stop the thread executing
return;
}
// Here load the image in the same way as above:
// But you will need to go onto the UI thread first.
image.post(new Runnable() {
public void run() {
Picasso.with(YourActivity.this).load( "http://i.imgur.com/DvpvklR.png").memoryPolicy(MemoryPolicy.NO_CACHE).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
}
});
}
}
};
Then you just start the runnable:
Handler handler = new Handler();
handler.post(imageUpdater);
String[] imageLink = {http://i.imgur.com/DvpvklR.png,
http://i.imgur.com/DvpvklR.png, http://i.imgur.com/DvpvklR.png};
int position = 0;
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(runnable);
}
}, 30 * 1000, 30*1000);
Runnable runnable = new Runnable() {
#Override
public void run() {
Picasso.with(this).load(imageLink[position%imageLink.length]).memoryPolicy(MemoryPolicy.NO_CACHE).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
position++;
}
};
Hope the above code will help you :)
In one activity of my app, there are an imagview and a textview that are changing every 3 seconds.
I first set this up with a handler and thread runnable. It works fine, but when I use removeCallbacks with the pause button, it will not pause in the middle of the Thread. It completes the Thread runnable before pausing. I need it to pause when the button is clicked no matter where it is in the runnable.
I thought about using an asynctask but I'm not sure how this would work.
I know there has to be a way to do this, as you can pause almost any game you download. Does anyone have any suggestions on the best/easiest way to do this?
Thanks so much!! :)
public class Workout extends AppCompatActivity {
private String[] messages = {"1", "2", "3", "4", "5"};
final Handler handler = new Handler();
private int nextIndex;
String mDrawableName[] = {"bodypart70", "equipment70", "settings70", "time70", "bodypart70"};
private int nextImage;
ImageView image;
private ProgressBar progressBar;
private int progressStatus = 0;
Runnable r = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout);
image = (ImageView) findViewById(R.id.exerciseImage);
final TextView text = (TextView)findViewById(R.id.textView4);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
//changing
r = new Runnable(){
#Override
public void run(){
if (messages.length > nextIndex) {
//change textview
text.setText(messages[nextIndex++]);
//change image
int resID = getResources().getIdentifier(mDrawableName[nextImage++] , "drawable", getPackageName());
image.setImageResource(resID);
//restart progress bar
progressStatus = 0;
progress();
//do it after 3 seconds
handler.postDelayed(this, 3000);
}
}
};
handler.postDelayed(r, 0);
}
public void progress(){
new Thread(new Runnable() {
public void run() {
long timerEnd = System.currentTimeMillis() + 3 * 1000;
while (timerEnd > System.currentTimeMillis()) {
progressStatus = 3 - (int) (timerEnd - System.currentTimeMillis()) / 1000;
// Update the progress bar
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
}
});
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w("App", "Progress thread cannot sleep");
}
}
}
}).start();
}
public void pauseWorkout(View view){
handler.removeCallbacks(r);
}
public void resumeWorkout(View view){
handler.postDelayed(r, 0);
}
}
It looks like the while-loop in your progress() function is still working after you press your pause button.
Try the following: Create a global boolean that indicates you're in a paused or resuming state. Put it at the top of your code:
boolean resume = true;
Update your while condition in progress()
while (resume && timerEnd > System.currentTimeMillis()) {
Update your workout functions:
public void pauseWorkout(View view){
handler.removeCallbacks(r);
resume = false;
}
public void resumeWorkout(View view){
handler.postDelayed(r, 0);
resume = true;
}
So I have thread where it checks every 10ms's if drag is almost outside draggingzone. Basicly my thread code is doing nothing 99% of time so should I make it to pause and resume only when needed? Or does this literally do nothing when right and left are false?
My code looks like this
timer = new Thread() { //new thread
public void run() {
b = true;
try {
do {
sleep(10);
runOnUiThread(new Runnable() {
#Override
public void run() {
if (right) {
dragzone.moveleft(-5);
} else if (left) {
dragzone.moveleft(5);
}
}
});
}
while (b);
} catch (InterruptedException e) {
}
}
;
};
timer.start();
It looks like using a Thread here is not necessary, and you should switch to using a Handler and postDelayed()
First, declare your Handler, boolean, and a Runnable as instance variables:
Handler handler;
boolean b;
Runnable checkDragZone = new Runnable(){
#Override
public void run() {
if (right) {
dragzone.moveleft(-5);
} else if (left) {
dragzone.moveleft(5);
}
if (b){
handler.postDelayed(this, 10);
}
}
};
To start monitoring, set b to true, and start the Runnable:
handler = new Handler();
b = true;
handler.postDelayed(checkDragZone, 10);
To stop it (temporarily or permanently), just set b to false:
b = false;
It's not really a good practice to keep it running. You can start it when you detect the Drag action and then release it when it's finished.
Runnable runnable;
Thread globalThread;
public void startThread() {
if (threadController) {
runnable = new Runnable() {
#Override
public void run() {
while (threadController) {
for (int i = 0; i < adapter.getCount(); i++) {
final int value = i;
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
viewPager.setCurrentItem(value, true);
}
});
}
}
}
};
globalThread = new Thread(runnable);
globalThread.start();
} else {
return;
}
}
#Override
public void onPause() {
super.onPause();
threadController = false;
handler.removeCallbacks(runnable);
runnable = null;
if (globalThread != null) {
globalThread.interrupt();
}
}
#Override
public void onDestroy() {
super.onDestroy();
threadController = false;
}
Your resolve must be like this globalThread.interrupt();
This my java code how I implemented.
new Thread(new Runnable() {
public void run() {
int count=0;
while (true) {
if(count>5)
count=0;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(""+e);
}
ImageView image = (ImageView) findViewById(R.id.slider);
image.setImageResource(pics[count]);
count++;
}
}
}).start();
I have created a separate Thread to change the images dynamically
Thats because you're trying to set a picture from thread different than UI thread. And you're only allowed to change the UI from the UI thread.
final ImageView image = (ImageView) findViewById(R.id.slider);
image.post(new Runnable() {
#Override
public void run() {
image.setImageResource(pics[count]);
});
This will post your changes into the UI thread's queue.
You can achieve it using the Handler's postDelayed method
public class MyRunnable implements Runnable {
private ImageView imageView;
private boolean exit = false;
public MyRunnable(ImageView n) {
imageView = n;
}
private void setExit() {
exit = true;
}
#Override
public void run() {
if (exit) {
imageView.removeCallbacks(null);
imageView = null;
return;
}
imageView.setImageResource(pics[count++%5]);
imageView.postDelayed(this, 1000);
}
}
Declare a member:
MyRunnable mRunnable = null;
onResume
ImageView image = (ImageView) findViewById(R.id.slider);
image.postDelayed(mRunnable = new MyRunnable(image), 1000);
and onPause call
mRunnable.setExit();
Or you could put your image in Drawable and then use
ImageView.setImageResource (int resId)
Didn't tried but should work fine