private synchronized void retrieveMedia() {
    try {
      if (mCurrentState == State.NON_INITIALIZED) {
        mCurrentState = State.INITIALIZING;

        int slashPos = CATALOG_URL.lastIndexOf('/');
        String path = CATALOG_URL.substring(0, slashPos + 1);
        JSONObject jsonObj = fetchJSONFromUrl(CATALOG_URL);
        if (jsonObj == null) {
          return;
        }
        JSONArray tracks = jsonObj.getJSONArray(JSON_MUSIC);
        if (tracks != null) {
          for (int j = 0; j < tracks.length(); j++) {
            MediaMetadata item = buildFromJSON(tracks.getJSONObject(j), path);
            String musicId = item.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
            mMusicListById.put(musicId, new MutableMediaMetadata(musicId, item));
          }
          buildListsByGenre();
        }
        mCurrentState = State.INITIALIZED;
      }
    } catch (JSONException e) {
      LogHelper.e(TAG, e, "Could not retrieve music list");
    } finally {
      if (mCurrentState != State.INITIALIZED) {
        // Something bad happened, so we reset state to NON_INITIALIZED to allow
        // retries (eg if the network connection is temporary unavailable)
        mCurrentState = State.NON_INITIALIZED;
      }
    }
  }
  public synchronized void updateMusic(String musicId, MediaMetadata metadata) {
    MutableMediaMetadata track = mMusicListById.get(musicId);
    if (track == null) {
      return;
    }

    String oldGenre = track.metadata.getString(MediaMetadata.METADATA_KEY_GENRE);
    String newGenre = metadata.getString(MediaMetadata.METADATA_KEY_GENRE);

    track.metadata = metadata;

    // if genre has changed, we need to rebuild the list by genre
    if (!oldGenre.equals(newGenre)) {
      buildListsByGenre();
    }
  }
 @Override
 public void onCustomAction(String action, Bundle extras) {
   if (CUSTOM_ACTION_THUMBS_UP.equals(action)) {
     LogHelper.i(TAG, "onCustomAction: favorite for current track");
     MediaMetadata track = getCurrentPlayingMusic();
     if (track != null) {
       String musicId = track.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
       mMusicProvider.setFavorite(musicId, !mMusicProvider.isFavorite(musicId));
     }
     // playback state needs to be updated because the "Favorite" icon on the
     // custom action will change to reflect the new favorite state.
     updatePlaybackState(null);
   } else {
     LogHelper.e(TAG, "Unsupported action: ", action);
   }
 }
 private void setCustomAction(PlaybackState.Builder stateBuilder) {
   MediaMetadata currentMusic = getCurrentPlayingMusic();
   if (currentMusic != null) {
     // Set appropriate "Favorite" icon on Custom action:
     String musicId = currentMusic.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
     int favoriteIcon = R.drawable.ic_star_off;
     if (mMusicProvider.isFavorite(musicId)) {
       favoriteIcon = R.drawable.ic_star_on;
     }
     LogHelper.d(
         TAG,
         "updatePlaybackState, setting Favorite custom action of music ",
         musicId,
         " current favorite=",
         mMusicProvider.isFavorite(musicId));
     stateBuilder.addCustomAction(
         CUSTOM_ACTION_THUMBS_UP, getString(R.string.favorite), favoriteIcon);
   }
 }
  private void updateMetadata() {
    if (!QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
      LogHelper.e(TAG, "Can't retrieve current metadata.");
      updatePlaybackState(getResources().getString(R.string.error_no_metadata));
      return;
    }
    MediaSession.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
    String musicId =
        MediaIDHelper.extractMusicIDFromMediaID(queueItem.getDescription().getMediaId());
    MediaMetadata track = mMusicProvider.getMusic(musicId);
    final String trackId = track.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
    if (!musicId.equals(trackId)) {
      IllegalStateException e = new IllegalStateException("track ID should match musicId.");
      LogHelper.e(
          TAG,
          "track ID should match musicId.",
          " musicId=",
          musicId,
          " trackId=",
          trackId,
          " mediaId from queueItem=",
          queueItem.getDescription().getMediaId(),
          " title from queueItem=",
          queueItem.getDescription().getTitle(),
          " mediaId from track=",
          track.getDescription().getMediaId(),
          " title from track=",
          track.getDescription().getTitle(),
          " source.hashcode from track=",
          track.getString(MusicProvider.CUSTOM_METADATA_TRACK_SOURCE).hashCode(),
          e);
      throw e;
    }
    LogHelper.d(TAG, "Updating metadata for MusicID= " + musicId);
    mSession.setMetadata(track);

    // Set the proper album artwork on the media session, so it can be shown in the
    // locked screen and in other places.
    if (track.getDescription().getIconBitmap() == null
        && track.getDescription().getIconUri() != null) {
      String albumUri = track.getDescription().getIconUri().toString();
      AlbumArtCache.getInstance()
          .fetch(
              albumUri,
              new AlbumArtCache.FetchListener() {
                @Override
                public void onFetched(String artUrl, Bitmap bitmap, Bitmap icon) {
                  MediaSession.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
                  MediaMetadata track = mMusicProvider.getMusic(trackId);
                  track =
                      new MediaMetadata.Builder(track)

                          // set high resolution bitmap in METADATA_KEY_ALBUM_ART. This is used, for
                          // example, on the lockscreen background when the media session is active.
                          .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)

                          // set small version of the album art in the DISPLAY_ICON. This is used on
                          // the MediaDescription and thus it should be small to be serialized if
                          // necessary..
                          .putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, icon)
                          .build();

                  MediaDescription md;
                  mMusicProvider.updateMusic(trackId, track);

                  // If we are still playing the same music
                  String currentPlayingId =
                      MediaIDHelper.extractMusicIDFromMediaID(
                          queueItem.getDescription().getMediaId());
                  if (trackId.equals(currentPlayingId)) {
                    mSession.setMetadata(track);
                  }
                }
              });
    }
  }