For a more detailed version of this question, please see How to make MediaPlayer wait for ObjectAnimator (and generally control Android UI sequence)? Thanks. - Code-Read
I am attempting to build an Android app that starts up with this sequence:
- Zoom its main View in (a TextView);
- After the view is fully zoomed in, emit a sound;
- After the sound is emitted, execute the main program.
I first tried simply entering the zoom code (ObjectAnimator) before the sound code (MediaPlayer) in my program. But the code does not run in order of appearance. MediaPlayer plays in parallel with ObjectAnimator, regardless of code order. Why this is happening and how do I prevent it?
Attempting to cope, I have applied various timing and locking approaches to make MediaPlayer wait on ObjectAnimator. I've searched much here and elsewhere for solutions. So far the only ones I've found are:
- Run MediaPlayer from a
Handler().postDelayed
, and - Have
AnimatorListenerAdapter()
launch MediaPlayer when the animation completes.
These both work, but (1) isn't precise as I must hard code the amount of time to wait (and manage this value manually), and (2) isn't general and the main application code still starts before MediaPlayer finishes. Numerous Answers recommend using AsyncTask to control Android UI sequences, but AsyncTask only applies to two tasks, waiting on one in a background thread, which really isn't appropriate with sequences of more than two stages.
Android - wait for animation to finish before continuing? is on this problem also. The accepted answer is AnimatorListenerAdaptor(), but the OP asks, That works for now but if I then want more lines of code to run after the animation has finished do I have to basically have my whole code in the onAnimationEnd method? and I agree - this does not seem reasonable.
With further testing, it appears my question might be simplified to: How do I make subsequent routines wait for ObjectAnimator?
The code below illustrates this latter question. Boolean waitLock
is set to true. Then ObjectAnimator is launched. Then a while() loop waits for waitLock
to be set to false by onAnimationEnd(). ObjectAnimator never completes, waitLock
is never set to false
, and the while() loops indefinitely. Why?
However, if waitLock
is set to false initially, ObjectAnimator completes and the application exits normally. Why does ObjectAnimator complete in this case but not in the other?
public class MainActivity extends Activity {
private boolean waitLock;
View mainView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainView = findViewById(R.id.mainView);
waitLock = true;
ObjectAnimator scalexAnim = ObjectAnimator.ofFloat(mainView, "scaleX", 0f, 1f);
scalexAnim.setDuration(1500);
scalexAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
Log.w("sA", "onAnimationStart reached");
super.onAnimationStart(animator);
}
@Override
public void onAnimationEnd(Animator animation) {
Log.w("sA", "onAnimationEnd reached");
waitLock = false;
super.onAnimationEnd(animation);
}
});
Log.w("zI", "starting.."); zoomIn.start(); Log.w("zI", "started");
while (waitLock == true) {
SystemClock.sleep(1000);
Log.w("while(waitLock)", "sleep 1000ms");
}
Log.w("onCreate", "exit");
}
Here is corresponding logcat output when waitLock
is set to true:
07-02 13:34:14.850 9233-9233/com.code_read.sequentialcontroltest W/sA﹕ starting..
07-02 13:34:14.860 9233-9233/com.code_read.sequentialcontroltest W/sA﹕ onAnimationStart reached
07-02 13:34:14.860 9233-9233/com.code_read.sequentialcontroltest W/sA﹕ started
07-02 13:34:15.861 9233-9233/com.code_read.sequentialcontroltest W/while(waitLock)﹕ sleep 1000ms
07-02 13:34:16.862 9233-9233/com.code_read.sequentialcontroltest W/while(waitLock)﹕ sleep 1000ms
07-02 13:34:17.863 9233-9233/com.code_read.sequentialcontroltest W/while(waitLock)﹕ sleep 1000ms
07-02 13:34:18.864 9233-9233/com.code_read.sequentialcontroltest W/while(waitLock)﹕ sleep 1000ms