title: Android MediaBrowserService customize audio src and meta data
body: <p>I am building a audio player i have completed all the Songs browsing (UI) activities and to handle audio playback  i am using google sample audio player <a href="https://github.com/googlesamples/android-MediaBrowserService" rel="nofollow noreferrer">this</a> and i read all the src from this sample and there is class <code>MusicLibrary</code> in sample code and it contains a sample list of songs like below</p>
  
  <pre><code>public class MusicLibrary {
  
      private static final TreeMap&lt;String, MediaMetadataCompat&gt; music = new TreeMap&lt;&gt;();
      private static final HashMap&lt;String, Integer&gt; albumRes = new HashMap&lt;&gt;();
      private static final HashMap&lt;String, String&gt; musicFileName = new HashMap&lt;&gt;();
  
      static {
          createMediaMetadataCompat(
                  "Jazz_In_Paris",
                  "Jazz in Paris",
                  "Media Right Productions",
                  "Jazz &amp; Blues",
                  "Jazz",
                  103,
                  TimeUnit.SECONDS,
                  "http://www.noiseaddicts.com/samples_1w72b820/2537.mp3",
                  R.drawable.album_jazz_blues,
                  "https://upload.wikimedia.org/wikipedia/en/a/ac/Audioslave_-_Audioslave.jpg");
          createMediaMetadataCompat(
                  "The_Coldest_Shoulder",
                  "The Coldest Shoulder",
                  "The 126ers",
                  "Youtube Audio Library Rock 2",
                  "Rock",
                  160,
                  TimeUnit.SECONDS,
                  "http://www.noiseaddicts.com/samples_1w72b820/4201.mp3",
                  R.drawable.album_youtube_audio_library_rock_2,
                  "https://theflagcompany.in/wp-content/uploads/2018/10/Indian-National-Flag-300x300.jpeg");
      }
  </code></pre>
  
  <p>but i am unable to find a method which shows how to add a song in current playlist from other activities for example in my current app there is search activity where user can search any song from internet and i want to add track from this search activity by two different ways <strong>1.</strong> add and play song <strong>2.</strong> only add song in the end of playlist.</p>
  
  <p>Sample code track object use album art image from drawable folder but in my app i need to show album art from internet (Last FM API) not from local folder i tried to edit <code>MusicLibrary</code> class and created a bitmap from URI  unable to make it work so this is alos i need to modify in sample code.</p>
  
  <p>Sample code contains only on simple activity where when you open it opens a audio player interface but in my app in HomeActivity  there are some fragments  and a mini  player at bottom now like below </p>
  
  <p><a href="https://i.stack.imgur.com/xBZMK.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xBZMK.jpg" alt="enter image description here"></a></p>
  
  <p><strong>Please help me with these two things</strong>  </p>
  
  <ul>
  <li>add songs to player from my code</li>
  <li>use internet image for <code>METADATA_KEY_ALBUM_ART</code></li>
  </ul>
  
  <p>i just want to merge these two things and i am new to android so no luck please guide me so that i can complete my project. Thanks in advance :)       </p>
  
  <p><strong>My Main Activity</strong></p>
  
  <pre><code>public class MainActivity extends AppCompatActivity {
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
      }
  
      //add song in sample player service from this method
      public void addSongQue(Song song) {
  
          title = song.getTile;
          artist = song.getArtist;
          mp3Url = song.getSrc;
          albumArtImage = song.getAlbumArt;
          .......
          ...
  
      }
  
  
   }  
  </code></pre>
  
  <p><strong>Sample Code Player Activity</strong> <a href="https://github.com/googlesamples/android-MediaBrowserService" rel="nofollow noreferrer">full sample src is here</a></p>
  
  <pre><code>import android.content.Context;
  import android.os.Bundle;
  import android.support.annotation.NonNull;
  import android.support.v4.media.MediaBrowserCompat;
  import android.support.v4.media.MediaMetadataCompat;
  import android.support.v4.media.session.MediaControllerCompat;
  import android.support.v4.media.session.MediaSessionCompat;
  import android.support.v4.media.session.PlaybackStateCompat;
  import android.support.v7.app.AppCompatActivity;
  import android.view.View;
  import android.widget.Button;
  import android.widget.ImageView;
  import android.widget.TextView;
  
  import com.example.android.mediasession.R;
  import com.example.android.mediasession.client.MediaBrowserHelper;
  import com.example.android.mediasession.service.MusicService;
  import com.example.android.mediasession.service.contentcatalogs.MusicLibrary;
  
  import java.util.List;
  
  public class MainActivity extends AppCompatActivity {
  
      private ImageView mAlbumArt;
      private TextView mTitleTextView;
      private TextView mArtistTextView;
      private ImageView mMediaControlsImage;
      private MediaSeekBar mSeekBarAudio;
  
      private MediaBrowserHelper mMediaBrowserHelper;
  
      private boolean mIsPlaying;
  
  
      //https://github.com/googlesamples/android-MediaBrowserService
  
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
  
  
  
  
          mTitleTextView = findViewById(R.id.song_title);
          mArtistTextView = findViewById(R.id.song_artist);
          mAlbumArt = findViewById(R.id.album_art);
          mMediaControlsImage = findViewById(R.id.media_controls);
          mSeekBarAudio = findViewById(R.id.seekbar_audio);
  
          final ClickListener clickListener = new ClickListener();
          findViewById(R.id.button_previous).setOnClickListener(clickListener);
          findViewById(R.id.button_play).setOnClickListener(clickListener);
          findViewById(R.id.button_next).setOnClickListener(clickListener);
  
          mMediaBrowserHelper = new MediaBrowserConnection(this);
          mMediaBrowserHelper.registerCallback(new MediaBrowserListener());
      }
  
      @Override
      public void onStart() {
          super.onStart();
          mMediaBrowserHelper.onStart();
      }
  
      @Override
      public void onStop() {
          super.onStop();
          mSeekBarAudio.disconnectController();
          mMediaBrowserHelper.onStop();
      }
  
      /**
       * Convenience class to collect the click listeners together.
       * &lt;p&gt;
       * In a larger app it's better to split the listeners out or to use your favorite
       * library.
       */
      private class ClickListener implements View.OnClickListener {
          @Override
          public void onClick(View v) {
              switch (v.getId()) {
                  case R.id.button_previous:
                      mMediaBrowserHelper.getTransportControls().skipToPrevious();
                      break;
                  case R.id.button_play:
                      if (mIsPlaying) {
                          mMediaBrowserHelper.getTransportControls().pause();
                      } else {
                          mMediaBrowserHelper.getTransportControls().play();
                      }
                      break;
                  case R.id.button_next:
                      mMediaBrowserHelper.getTransportControls().skipToNext();
                      break;
              }
          }
      }
  
      /**
       * Customize the connection to our {@link android.support.v4.media.MediaBrowserServiceCompat}
       * and implement our app specific desires.
       */
      private class MediaBrowserConnection extends MediaBrowserHelper {
          private MediaBrowserConnection(Context context) {
              super(context, MusicService.class);
          }
  
          @Override
          protected void onConnected(@NonNull MediaControllerCompat mediaController) {
              mSeekBarAudio.setMediaController(mediaController);
          }
  
          @Override
          protected void onChildrenLoaded(@NonNull String parentId,
                                          @NonNull List&lt;MediaBrowserCompat.MediaItem&gt; children) {
              super.onChildrenLoaded(parentId, children);
  
              final MediaControllerCompat mediaController = getMediaController();
  
              // Queue up all media items for this simple sample.
              for (final MediaBrowserCompat.MediaItem mediaItem : children) {
                  mediaController.addQueueItem(mediaItem.getDescription());
              }
  
              // Call prepare now so pressing play just works.
              mediaController.getTransportControls().prepare();
          }
      }
  
      /**
       * Implementation of the {@link MediaControllerCompat.Callback} methods we're interested in.
       * &lt;p&gt;
       * Here would also be where one could override
       * {@code onQueueChanged(List&lt;MediaSessionCompat.QueueItem&gt; queue)} to get informed when items
       * are added or removed from the queue. We don't do this here in order to keep the UI
       * simple.
       */
      private class MediaBrowserListener extends MediaControllerCompat.Callback {
          @Override
          public void onPlaybackStateChanged(PlaybackStateCompat playbackState) {
              mIsPlaying = playbackState != null &amp;&amp;
                      playbackState.getState() == PlaybackStateCompat.STATE_PLAYING;
              mMediaControlsImage.setPressed(mIsPlaying);
          }
  
          @Override
          public void onMetadataChanged(MediaMetadataCompat mediaMetadata) {
              if (mediaMetadata == null) {
                  return;
              }
              mTitleTextView.setText(
                      mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
              mArtistTextView.setText(
                      mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
              mAlbumArt.setImageBitmap(MusicLibrary.getAlbumBitmap(
                      MainActivity.this,
                      mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)));
          }
  
          @Override
          public void onSessionDestroyed() {
              super.onSessionDestroyed();
          }
  
          @Override
          public void onQueueChanged(List&lt;MediaSessionCompat.QueueItem&gt; queue) {
              super.onQueueChanged(queue);
          }
      }
  }
  </code></pre>
  
  <p><strong>MusicLibrary Class where two sample songs</strong> </p>
  
  <pre><code>import android.content.ContentResolver;
  import android.content.Context;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.support.v4.media.MediaBrowserCompat;
  import android.support.v4.media.MediaMetadataCompat;
  
  import com.example.android.mediasession.BuildConfig;
  import com.example.android.mediasession.R;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.TreeMap;
  import java.util.concurrent.TimeUnit;
  
  
  public class MusicLibrary {
  
      private static final TreeMap&lt;String, MediaMetadataCompat&gt; music = new TreeMap&lt;&gt;();
      private static final HashMap&lt;String, Integer&gt; albumRes = new HashMap&lt;&gt;();
      private static final HashMap&lt;String, String&gt; musicFileName = new HashMap&lt;&gt;();
  
      static {
          createMediaMetadataCompat(
                  "Jazz_In_Paris",
                  "Jazz in Paris",
                  "Media Right Productions",
                  "Jazz &amp; Blues",
                  "Jazz",
                  103,
                  TimeUnit.SECONDS,
                  "http://www.noiseaddicts.com/samples_1w72b820/2537.mp3",
                  R.drawable.album_jazz_blues,
                  "https://upload.wikimedia.org/wikipedia/en/a/ac/Audioslave_-_Audioslave.jpg");
          createMediaMetadataCompat(
                  "The_Coldest_Shoulder",
                  "The Coldest Shoulder",
                  "The 126ers",
                  "Youtube Audio Library Rock 2",
                  "Rock",
                  160,
                  TimeUnit.SECONDS,
                  "http://www.noiseaddicts.com/samples_1w72b820/4201.mp3",
                  R.drawable.album_youtube_audio_library_rock_2,
                  "https://theflagcompany.in/wp-content/uploads/2018/10/Indian-National-Flag-300x300.jpeg");
      }
  
      public static String getRoot() {
          return "root";
      }
  
      private static String getAlbumArtUri(String albumArtResName) {
          return ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                  BuildConfig.APPLICATION_ID + "/drawable/" + albumArtResName;
      }
  
      public static String getMusicFilename(String mediaId) {
          return musicFileName.containsKey(mediaId) ? musicFileName.get(mediaId) : null;
      }
  
      private static int getAlbumRes(String mediaId) {
          return albumRes.containsKey(mediaId) ? albumRes.get(mediaId) : 0;
      }
  
      public static Bitmap getAlbumBitmap(Context context, String mediaId) {
          return BitmapFactory.decodeResource(context.getResources(),
                  MusicLibrary.getAlbumRes(mediaId));
      }
  
      public static List&lt;MediaBrowserCompat.MediaItem&gt; getMediaItems() {
          List&lt;MediaBrowserCompat.MediaItem&gt; result = new ArrayList&lt;&gt;();
          for (MediaMetadataCompat metadata : music.values()) {
              result.add(
                      new MediaBrowserCompat.MediaItem(
                              metadata.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE));
          }
          return result;
      }
  
      public static MediaMetadataCompat getMetadata(Context context, String mediaId) {
          MediaMetadataCompat metadataWithoutBitmap = music.get(mediaId);
          Bitmap albumArt = getAlbumBitmap(context, mediaId);
  
          // Since MediaMetadataCompat is immutable, we need to create a copy to set the album art.
          // We don't set it initially on all items so that they don't take unnecessary memory.
          MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
          for (String key :
                  new String[]{
                          MediaMetadataCompat.METADATA_KEY_MEDIA_ID,
                          MediaMetadataCompat.METADATA_KEY_ALBUM,
                          MediaMetadataCompat.METADATA_KEY_ARTIST,
                          MediaMetadataCompat.METADATA_KEY_GENRE,
                          MediaMetadataCompat.METADATA_KEY_TITLE
                  }) {
              builder.putString(key, metadataWithoutBitmap.getString(key));
          }
          builder.putLong(
                  MediaMetadataCompat.METADATA_KEY_DURATION,
                  metadataWithoutBitmap.getLong(MediaMetadataCompat.METADATA_KEY_DURATION));
          builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt);
          return builder.build();
      }
  
      private static void createMediaMetadataCompat(
              String mediaId,
              String title,
              String artist,
              String album,
              String genre,
              long duration,
              TimeUnit durationUnit,
              String musicFilename,
              int albumArtResId,
              String albumArtResName) {
          music.put(
                  mediaId,
                  new MediaMetadataCompat.Builder()
                          .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId)
                          .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, album)
                          .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
                          .putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
                                   TimeUnit.MILLISECONDS.convert(duration, durationUnit))
                          .putString(MediaMetadataCompat.METADATA_KEY_GENRE, genre)
                          .putString(
                                  MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI,
                                  getAlbumArtUri(albumArtResName))
                          .putString(
                                  MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,
                                  getAlbumArtUri(albumArtResName))
                          .putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
                          .build());
          albumRes.put(mediaId, albumArtResId);
          musicFileName.put(mediaId, musicFilename);
      }
  }
  </code></pre>