@Override
  public void stop() {
    cleanUp();

    if (mPlayerEngineListener != null) {
      mPlayerEngineListener.onTrackStop();
    }
  }
 public void run() {
   if (mPlayerEngineListener != null) {
     // TODO use getCurrentPosition less frequently (usage of currentTimeMillis or
     // uptimeMillis)
     if (mCurrentMediaPlayer != null)
       mPlayerEngineListener.onTrackProgress(
           mCurrentMediaPlayer.getCurrentPosition() / 1000);
     mHandler.postDelayed(this, 1000); // 让mUpdateTimeTask延时一秒
   }
 }
  @Override
  public void pause() {
    if (mCurrentMediaPlayer != null) {
      // still preparing
      if (mCurrentMediaPlayer.preparing) {
        mCurrentMediaPlayer.playAfterPrepare = false;
        return;
      }

      // check if we play, then pause
      if (mCurrentMediaPlayer.isPlaying()) {
        mCurrentMediaPlayer.pause();
        if (mPlayerEngineListener != null) mPlayerEngineListener.onTrackPause();
        return;
      }
    }
  }
  private InternalMediaPlayer build(PlaylistEntry playlistEntry) {
    final InternalMediaPlayer mediaPlayer = new InternalMediaPlayer();

    // try to setup local path
    String path = JamendoApplication.getInstance().getDownloadManager().getTrackPath(playlistEntry);
    if (path == null)
      // fallback to remote one
      path = playlistEntry.getTrack().getStream();

    // some albums happen to contain empty stream url, notify of error, abort playback
    if (path.length() == 0) {
      if (mPlayerEngineListener != null) {
        mPlayerEngineListener.onTrackStreamError();
        mPlayerEngineListener.onTrackChanged(mPlaylist.getSelectedTrack());
      }
      stop();
      return null;
    }

    try {
      mediaPlayer.setDataSource(path);
      mediaPlayer.playlistEntry = playlistEntry;
      // mediaPlayer.setScreenOnWhilePlaying(true);

      mediaPlayer.setOnCompletionListener(
          new OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
              if (!mPlaylist.isLastTrackOnList()
                  || mPlaylist.getPlaylistPlaybackMode() == PlaylistPlaybackMode.REPEAT
                  || mPlaylist.getPlaylistPlaybackMode()
                      == PlaylistPlaybackMode.SHUFFLE_AND_REPEAT) {
                next();
              } else {
                stop();
              }
            }
          });

      mediaPlayer.setOnPreparedListener(
          new OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
              mediaPlayer.preparing = false;

              // we may start playing
              if (mPlaylist.getSelectedTrack() == mediaPlayer.playlistEntry
                  && mediaPlayer.playAfterPrepare) {
                mediaPlayer.playAfterPrepare = false;
                play();
              }
            }
          });

      mediaPlayer.setOnBufferingUpdateListener(
          new OnBufferingUpdateListener() {

            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
              if (mPlayerEngineListener != null) {
                mPlayerEngineListener.onTrackBuffering(percent);
              }
            }
          });

      mediaPlayer.setOnErrorListener(
          new OnErrorListener() {

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
              Log.w(
                  JamendoApplication.TAG,
                  "PlayerEngineImpl fail, what (" + what + ") extra (" + extra + ")");

              if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
                // we probably lack network
                if (mPlayerEngineListener != null) {
                  mPlayerEngineListener.onTrackStreamError();
                }
                stop();
                return true;
              }

              // not sure what error code -1 exactly stands for but it causes player to start to
              // jump songs
              // if there are more than 5 jumps without playback during 1 second then we abort
              // further playback
              if (what == -1) {
                long failTime = System.currentTimeMillis();
                if (failTime - mLastFailTime > FAIL_TIME_FRAME) {
                  // outside time frame
                  mTimesFailed = 1;
                  mLastFailTime = failTime;
                  Log.w(
                      JamendoApplication.TAG,
                      "PlayerEngineImpl " + mTimesFailed + " fail within FAIL_TIME_FRAME");
                } else {
                  // inside time frame
                  mTimesFailed++;
                  if (mTimesFailed > ACCEPTABLE_FAIL_NUMBER) {
                    Log.w(
                        JamendoApplication.TAG,
                        "PlayerEngineImpl too many fails, aborting playback");
                    if (mPlayerEngineListener != null) {
                      mPlayerEngineListener.onTrackStreamError();
                    }
                    stop();
                    return true;
                  }
                }
              }
              return false;
            }
          });

      // start preparing
      Log.i(
          JamendoApplication.TAG,
          "Player [buffering] " + mediaPlayer.playlistEntry.getTrack().getName());
      mediaPlayer.preparing = true;
      mediaPlayer.prepareAsync();

      // this is a new track, so notify the listener
      if (mPlayerEngineListener != null) {
        mPlayerEngineListener.onTrackChanged(mPlaylist.getSelectedTrack());
      }

      return mediaPlayer;
    } catch (IllegalArgumentException e) {
      e.printStackTrace();
    } catch (IllegalStateException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
  @Override
  public void play() {

    if (mPlayerEngineListener.onTrackStart() == false) {
      return; // apparently sth prevents us from playing tracks
    }

    // check if there is anything to play
    if (mPlaylist != null) {

      // check if media player is initialized
      if (mCurrentMediaPlayer == null) {
        mCurrentMediaPlayer = build(mPlaylist.getSelectedTrack());
      }

      // check if current media player is set to our song
      if (mCurrentMediaPlayer != null
          && mCurrentMediaPlayer.playlistEntry != mPlaylist.getSelectedTrack()) {
        cleanUp(); // this will do the cleanup job
        mCurrentMediaPlayer = build(mPlaylist.getSelectedTrack());
      }

      // check if there is any player instance, if not, abort further execution
      if (mCurrentMediaPlayer == null) return;

      // check if current media player is not still buffering
      if (!mCurrentMediaPlayer.preparing) {

        // prevent double-press
        if (!mCurrentMediaPlayer.isPlaying()) {
          // i guess this mean we can play the song
          Log.i(
              JamendoApplication.TAG,
              "Player [playing] " + mCurrentMediaPlayer.playlistEntry.getTrack().getName());

          // starting timer
          mHandler.removeCallbacks(mUpdateTimeTask);
          mHandler.postDelayed(mUpdateTimeTask, 1000);

          // Actual equalizer
          Equalizer equalizer = JamendoApplication.getInstance().getMyEqualizer();

          // Mantain the settings of the equalizer for the new media
          Equalizer newEqualizer = new Equalizer(0, mCurrentMediaPlayer.getAudioSessionId());
          if (equalizer != null) {
            newEqualizer.setProperties(equalizer.getProperties());
          }

          // Enable equalizer before media starts
          JamendoApplication.getInstance().setMyEqualizer(newEqualizer);
          JamendoApplication.getInstance().getMyEqualizer().setEnabled(true);
          mCurrentMediaPlayer.start();
        }
      } else {
        // tell the mediaplayer to play the song as soon as it ends preparing
        mCurrentMediaPlayer.playAfterPrepare = true;
      }
    }

    // Change application media
    JamendoApplication.getInstance().setMyCurrentMedia(mCurrentMediaPlayer);
  }