title: Android MediaPlayer audio crossfade
body: <p>I'm developing a music streaming app which has to have a crossfade function e.g. when there are 5s left to the end of the first song it should start fading out and the next song should start fading in in the very same moment so that for a moment there will be two tracks playing at once.</p>
  
  <p>I was trying to use two MediaPlayer objects but always only one plays. The fade out and fade in effects work perfectly fine if I play just one track.</p>
  
  <p>I check when to start the crossfade in this runnable:</p>
  
  <pre><code>private Runnable mUpdateTimeTask = new Runnable() {
          public void run() {
  
              long totalDuration = 0;
              long currentDuration = 0;
  
              if(musicPlayer.isPlaying()) {
                  totalDuration = musicPlayer.getDuration();
                  currentDuration = musicPlayer.getCurrentPosition();
  
                  // Updating progress bar
                  int progress = (utils.getProgressPercentage(currentDuration, totalDuration));
                  trackPb.setProgress(progress);
  
                  if (!trackDownloaded &amp;&amp; currentDuration &gt; 100) {
                      Log.i(TagsContainer.MUSIC_PLAYER_TAG,"next track download started");
                      trackDownloaded = true;
                      new TrackLoader().execute();
  
                  }
  
                  long crossFadeValue = currentDuration + CROSSFADE_DURATION;
                  if (crossFadeValue &gt; totalDuration &amp;&amp; !fadeStarted &amp;&amp; currentDuration &gt; 100) {
                      fadeStarted = true;
                      crossFade();
                  }
                  // Running this thread after 100 milliseconds
  
              }
              mHandler.postDelayed(this, 100);
          }
      };
  </code></pre>
  
  <p>Crossfade's functions look like this:</p>
  
  <pre><code>private void crossFade() {
  
          fadeOut(musicPlayer, CROSSFADE_DURATION);
          fadeIn(musicPlayer2, CROSSFADE_DURATION);
      }
  
      public void fadeOut(final MediaPlayer _player, final int duration) {
          final float deviceVolume = getDeviceVolume();
          final Handler h = new Handler();
          h.postDelayed(new Runnable() {
              private float time = duration;
              private float volume = 0.0f;
  
              @Override
              public void run() {
                  if (!_player.isPlaying())
                      _player.start();
                  // can call h again after work!
                  time -= 100;
                  volume = (deviceVolume * time) / duration;
                  _player.setVolume(volume, volume);
                  if (time &gt; 0)
                      h.postDelayed(this, 100);
                  else {
                      _player.stop();
                      _player.release();
                  }
              }
          }, 100); // 1 second delay (takes millis)
  
  
      }
  
      public void fadeIn(final MediaPlayer _player, final int duration) {
          final float deviceVolume = getDeviceVolume();
          final Handler h = new Handler();
          h.postDelayed(new Runnable() {
              private float time = 0.0f;
              private float volume = 0.0f;
  
              @Override
              public void run() {
                  if (!_player.isPlaying())
                      _player.start();
                  // can call h again after work!
                  time += 100;
                  volume = (deviceVolume * time) / duration;
                  _player.setVolume(volume, volume);
                  if (time &lt; duration)
                      h.postDelayed(this, 100);
              }
          }, 100); // 1 second delay (takes millis)
  
      }
  </code></pre>