/**
   * Actual implementation of onLoadChildren that assumes that MusicProvider is already initialized.
   */
  private void loadChildrenImpl(
      final String parentMediaId, final Result<List<MediaBrowserCompat.MediaItem>> result) {
    LogHelper.d(TAG, "OnLoadChildren: parentMediaId=", parentMediaId);

    List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();

    if (MEDIA_ID_ROOT.equals(parentMediaId)) {
      LogHelper.d(TAG, "OnLoadChildren.ROOT");
      mediaItems.add(
          new MediaBrowserCompat.MediaItem(
              new MediaDescriptionCompat.Builder()
                  .setMediaId(MEDIA_ID_MUSICS_BY_GENRE)
                  .setTitle(getString(R.string.browse_genres))
                  .setIconUri(
                      Uri.parse(
                          "android.resource://" + "com.example.android.uamp/drawable/ic_by_genre"))
                  .setSubtitle(getString(R.string.browse_genre_subtitle))
                  .build(),
              MediaBrowserCompat.MediaItem.FLAG_BROWSABLE));

    } else if (MEDIA_ID_MUSICS_BY_GENRE.equals(parentMediaId)) {
      LogHelper.d(TAG, "OnLoadChildren.GENRES");
      for (String genre : mMusicProvider.getGenres()) {
        MediaBrowserCompat.MediaItem item =
            new MediaBrowserCompat.MediaItem(
                new MediaDescriptionCompat.Builder()
                    .setMediaId(createBrowseCategoryMediaID(MEDIA_ID_MUSICS_BY_GENRE, genre))
                    .setTitle(genre)
                    .setSubtitle(getString(R.string.browse_musics_by_genre_subtitle, genre))
                    .build(),
                MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
        mediaItems.add(item);
      }

    } else if (parentMediaId.startsWith(MEDIA_ID_MUSICS_BY_GENRE)) {
      String genre = MediaIDHelper.getHierarchy(parentMediaId)[1];
      LogHelper.d(TAG, "OnLoadChildren.SONGS_BY_GENRE  genre=", genre);
      for (MediaMetadataCompat track : mMusicProvider.getMusicsByGenre(genre)) {
        // Since mediaMetadata fields are immutable, we need to create a copy, so we
        // can set a hierarchy-aware mediaID. We will need to know the media hierarchy
        // when we get a onPlayFromMusicID call, so we can create the proper queue based
        // on where the music was selected from (by artist, by genre, random, etc)
        String hierarchyAwareMediaID =
            MediaIDHelper.createMediaID(
                track.getDescription().getMediaId(), MEDIA_ID_MUSICS_BY_GENRE, genre);
        MediaMetadataCompat trackCopy =
            new MediaMetadataCompat.Builder(track)
                .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, hierarchyAwareMediaID)
                .build();
        MediaBrowserCompat.MediaItem bItem =
            new MediaBrowserCompat.MediaItem(trackCopy.getDescription(), MediaItem.FLAG_PLAYABLE);
        mediaItems.add(bItem);
      }
    } else {
      LogHelper.w(TAG, "Skipping unmatched parentMediaId: ", parentMediaId);
    }
    LogHelper.d(TAG, "OnLoadChildren sending ", mediaItems.size(), " results for ", parentMediaId);
    result.sendResult(mediaItems);
  }
Пример #2
0
  @Override
  public void play(QueueItem item) {
    mPlayOnFocusGain = true;
    tryToGetAudioFocus();
    registerAudioNoisyReceiver();
    String mediaId = item.getDescription().getMediaId();
    boolean mediaHasChanged = !TextUtils.equals(mediaId, mCurrentMediaId);
    if (mediaHasChanged) {
      mCurrentPosition = 0;
      mCurrentMediaId = mediaId;
    }

    if (mState == PlaybackStateCompat.STATE_PAUSED && !mediaHasChanged && mMediaPlayer != null) {
      configMediaPlayerState();
    } else {
      mState = PlaybackStateCompat.STATE_STOPPED;
      relaxResources(false); // release everything except MediaPlayer
      MediaMetadataCompat track =
          mMusicProvider.getMusic(
              MediaIDHelper.extractMusicIDFromMediaID(item.getDescription().getMediaId()));

      String source =
          MusicProvider.getTrackSource(track.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID));

      try {
        createMediaPlayerIfNeeded();

        mState = PlaybackStateCompat.STATE_BUFFERING;

        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mMediaPlayer.setDataSource(source);

        // Starts preparing the media player in the background. When
        // it's done, it will call our OnPreparedListener (that is,
        // the onPrepared() method on this class, since we set the
        // listener to 'this'). Until the media player is prepared,
        // we *cannot* call start() on it!
        mMediaPlayer.prepareAsync();

        // If we are streaming from the internet, we want to hold a
        // Wifi lock, which prevents the Wifi radio from going to
        // sleep while the song is playing.
        mWifiLock.acquire();

        if (mCallback != null) {
          mCallback.onPlaybackStatusChanged(mState);
        }

      } catch (IOException ex) {
        LogHelper.e(TAG, ex, "Exception playing song");
        if (mCallback != null) {
          mCallback.onError(ex.getMessage());
        }
      }
    }
  }
 @Override
 public void onMetadataChanged(MediaMetadataCompat metadata) {
   if (metadata == null) {
     return;
   }
   LogHelper.d(
       TAG,
       "Received metadata state change to mediaId=",
       metadata.getDescription().getMediaId(),
       " song=",
       metadata.getDescription().getTitle());
   PlaybackControlsFragment.this.onMetadataChanged(metadata);
 }
 @Override
 public void onCustomAction(@NonNull String action, Bundle extras) {
   if (CUSTOM_ACTION_THUMBS_UP.equals(action)) {
     LogHelper.i(TAG, "onCustomAction: favorite for current track");
     MediaMetadataCompat track = getCurrentPlayingMusic();
     if (track != null) {
       String musicId = track.getString(MediaMetadataCompat.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 onMetadataChanged(MediaMetadataCompat metadata) {
    LogHelper.d(TAG, "onMetadataChanged ", metadata);
    if (getActivity() == null) {
      LogHelper.w(
          TAG,
          "onMetadataChanged called when getActivity null,"
              + "this should not happen if the callback was properly unregistered. Ignoring.");
      return;
    }
    if (metadata == null) {
      return;
    }

    mTitle.setText(metadata.getDescription().getTitle());
    mSubtitle.setText(metadata.getDescription().getSubtitle());
    String artUrl = null;
    if (metadata.getDescription().getIconUri() != null) {
      artUrl = metadata.getDescription().getIconUri().toString();
    }
    if (!TextUtils.equals(artUrl, mArtUrl)) {
      mArtUrl = artUrl;
      Bitmap art = metadata.getDescription().getIconBitmap();
      AlbumArtCache cache = AlbumArtCache.getInstance();
      if (art == null) {
        art = cache.getIconImage(mArtUrl);
      }
      if (art != null) {
        mAlbumArt.setImageBitmap(art);
      } else {
        cache.fetch(
            artUrl,
            new AlbumArtCache.FetchListener() {
              @Override
              public void onFetched(String artUrl, Bitmap bitmap, Bitmap icon) {
                if (icon != null) {
                  LogHelper.d(
                      TAG, "album art icon of w=", icon.getWidth(), " h=", icon.getHeight());
                  if (isAdded()) {
                    mAlbumArt.setImageBitmap(icon);
                  }
                }
              }
            });
      }
    }
  }
Пример #6
0
  private static List<MediaSessionCompat.QueueItem> convertToQueue(
      Iterable<MediaMetadataCompat> tracks, String... categories) {
    List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
    int count = 0;
    for (MediaMetadataCompat track : tracks) {

      // We create a hierarchy-aware mediaID, so we know what the queue is about by looking
      // at the QueueItem media IDs.
      String hierarchyAwareMediaID =
          MediaIDHelper.createMediaID(track.getDescription().getMediaId(), categories);

      MediaMetadataCompat trackCopy =
          new MediaMetadataCompat.Builder(track)
              .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, hierarchyAwareMediaID)
              .build();

      // We don't expect queues to change after created, so we use the item index as the
      // queueId. Any other number unique in the queue would work.
      MediaSessionCompat.QueueItem item =
          new MediaSessionCompat.QueueItem(trackCopy.getDescription(), count++);
      queue.add(item);
    }
    return queue;
  }
 private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
   MediaMetadataCompat currentMusic = getCurrentPlayingMusic();
   if (currentMusic != null) {
     // Set appropriate "Favorite" icon on Custom action:
     String musicId = currentMusic.getString(MediaMetadataCompat.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));
     Bundle customActionExtras = new Bundle();
     WearHelper.setShowCustomActionOnWear(customActionExtras, true);
     stateBuilder.addCustomAction(
         new PlaybackStateCompat.CustomAction.Builder(
                 CUSTOM_ACTION_THUMBS_UP, getString(R.string.favorite), favoriteIcon)
             .setExtras(customActionExtras)
             .build());
   }
 }
  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;
    }
    MediaSessionCompat.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
    String musicId =
        MediaIDHelper.extractMusicIDFromMediaID(queueItem.getDescription().getMediaId());
    MediaMetadataCompat track = mMusicProvider.getMusic(musicId);
    if (track == null) {
      throw new IllegalArgumentException("Invalid musicId " + musicId);
    }
    final String trackId = track.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID);
    if (!TextUtils.equals(musicId, 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) {
                  MediaSessionCompat.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
                  MediaMetadataCompat track = mMusicProvider.getMusic(trackId);
                  track =
                      new MediaMetadataCompat.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(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)

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

                  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);
                  }
                }
              });
    }
  }
 @Override
 public MediaMetadataCompat getMetadata() {
   Object metadataObj = MediaControllerCompatApi21.getMetadata(mControllerObj);
   return metadataObj != null ? MediaMetadataCompat.fromMediaMetadata(metadataObj) : null;
 }
Пример #10
0
 @Override
 public void onMetadataChanged(Object metadataObj) {
   Callback.this.onMetadataChanged(MediaMetadataCompat.fromMediaMetadata(metadataObj));
 }