A little while ago I needed a flashing text in Android. 

Pretty easy you'd think: stick two animations in an AnimationSet, set the repeatMode to Animation.RESTART and repeatCount to Animation.INFITITE like this:
XML
| 
<set xmlns:android="http://schemas.android.com/apk/res/android"
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    android:duration="1000"
/>
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0.9"
    android:toAlpha="0.0"
    android:duration="1000"
    android:startOffset="1000"
/>
</set> 
 | 
Activity code
| 
AnimationSet c = (AnimationSet) AnimationUtils.loadAnimation(this, R.anim.flash);
c.setRepeatMode(Animation.RESTART);
c.setRepeatCount(Animation.INFINITE);
TextView tv = (TextView) findViewById(R.id.flashingTextView);
tv.clearAnimation();
tv.startAnimation(c); 
 | 
and you're done.
But no! It only runs one time, or 1.5 times or whatever; definitely not endlessly. 
This pretty basic requirement of looping a set of animations indefinitely is apparently a 
known bug. I haven't been able to find out if it's still an outstanding issue today (August 2010) but unless I implemented it incorrectly, it is definitely present in SDK 1.6.
Based on the answers in that thread and the example code 
here, I came up with the following solution:
XML
A fadein.xml and a fadeout.xml. See the end of this post for the complete code.
Activity code
| 
    // Get ref to what we're going to animate (fade-in and fade-out indefinitely)
    tv = (TextView) findViewById(R.id.flashingTextView);
    // Setup fadein/out animations
   fadeIn = AnimationUtils.loadAnimation(this, R.anim.fadein);
   fadeIn.setAnimationListener( myFadeInAnimationListener );
   fadeOut = AnimationUtils.loadAnimation(this, R.anim.fadeout);
   fadeOut.setAnimationListener( myFadeOutAnimationListener );
   
   // And start with the fade in
   launchInAnimation();
    public void launchInAnimation() {
       tv.startAnimation(fadeIn);
    }    
    public void launchOutAnimation() {
       // Launch the second animation :
       tv = (TextView) findViewById(R.id.flashingTextView);
       tv.startAnimation(fadeOut);
    }    
     
 | 
Two listeners which start the other animation at the end of an animation:
| 
    private class LocalFadeInAnimationListener implements AnimationListener {
       public void onAnimationEnd(Animation animation) {
           tv.post(mLaunchFadeOutAnimation);
        }
       public void onAnimationRepeat(Animation animation) {
       }
       public void onAnimationStart(Animation animation) {
       }
    };
    
    private class LocalFadeOutAnimationListener implements AnimationListener {
       public void onAnimationEnd(Animation animation) {
           tv.post(mLaunchFadeInAnimation);
      }
       public void onAnimationRepeat(Animation animation) {
      }
      public void onAnimationStart(Animation animation) {
      }
    };
    
    private LocalFadeInAnimationListener myFadeInAnimationListener = new LocalFadeInAnimationListener();
    private LocalFadeOutAnimationListener myFadeOutAnimationListener = new LocalFadeOutAnimationListener(); 
 | 
Runnables that do the fading
| 
    private Runnable mLaunchFadeOutAnimation = new Runnable() {
       public void run() {
            launchOutAnimation();
       }
    };    
    
    private Runnable mLaunchFadeInAnimation = new Runnable() {
       public void run() {
        launchInAnimation();
       }
    };     
 | 
Note that I improved efficiency of the mentioned example code by only setting the animations one time and getting the TextView to animate only once.
That's it!
Note: in the logcat I do get these messages (2-3 times in about 5 minutes):
| 
08-22 15:33:28.078: WARN/SurfaceComposerClient(252): lock_layer timed out (is the CPU pegged?) layer=0, lcblk=0x41048020, 
state=00000002 (was 00000043)
08-22 15:33:28.078: WARN/SurfaceComposerClient(252): lock_layer() timed out but didn't appear to need to be locked and 
we recovered (layer=0, lcblk=0x41048020, state=00000002) 
 | 
Pretty strange, the CPU doesn't seem to be pegged... It says it recovers, but I guess the warning is there for a reason. Can the code be modified to avoid these warnings?  
It might be a 
platform bug. Indeed I do see it appear in 1.6 but not in 2.1.
Full code (tested on 1.6) can be downloaded 
here.