diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index ad9eb3a7212fe..8b233a39c3593 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -892,6 +892,10 @@ include the action bar on devices running Android 2.1 or higher." Building a Details View +
TV apps may allow users to play music or other media in the background while using other +applications. If your app allows this type of use, it must must +provide a means for the user to return to the app to pause the music or switch to a new song. The +Android framework enables TV apps to do this by displaying a Now Playing card on the home +screen in the recommendations row.
+ +The Now Playing card is a system artifact that displays on the +home screen in the recommendations row for an active media session. It includes the media metadata +such as the album art, title, and app icon. When the user selects it, the system opens the the app +that owns the session.
+ +This lesson shows how to use the {@link android.media.session.MediaSession} class to implement +the Now Playing card.
+ +A playback app can run as an activity or +as a service. The service is required for +background playback because it can continue to play media even after the activity that launched it +has been destroyed. For this discussion, the media playback app is assumed to be running in a +{@link android.service.media.MediaBrowserService}.
+ +In your service's {@link android.service.media.MediaBrowserService#onCreate() onCreate()} +method, create a new {@link android.media.session.MediaSession#MediaSession(android.content.Context, java.lang.String) MediaSession}, +set the callback and flags appropriate to a media app, and set the session token for the +{@link android.service.media.MediaBrowserService}.
+ ++mSession = new MediaSession(this, "MusicService"); +mSession.setCallback(new MediaSessionCallback()); +mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | + MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); + +// for the MediaBrowserService +setSessionToken(mSession.getSessionToken()); ++ +
Note: The Now Playing card will display only for a media session with +the {@link android.media.session.MediaSession#FLAG_HANDLES_TRANSPORT_CONTROLS} flag set.
+ +The Now Playing card shows up after {@link android.media.session.MediaSession#setActive(boolean) setActive(true)} +is called, if the session is the highest priority session in the system. Also, note that your app +must request the audio focus, as described in +Managing Audio Focus.
+ +
+private void handlePlayRequest() {
+
+ tryToGetAudioFocus();
+
+ if (!mSession.isActive()) {
+ mSession.setActive(true);
+ }
+...
+
+
+The card is removed from the home screen when {@link android.media.session.MediaSession#setActive(boolean) setActive(false)} +is called or if another app initiates media playback. You may want to remove the card from the home +screen some time after playback is paused, depending on how long you want to keep the card up, +usually 5 to 30 minutes.
+ +As with any media app, update the playback state in the {@link android.media.session.MediaSession} +so that the card can display the current metadata, as shown in the following example:
+ +
+private void updatePlaybackState() {
+ long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
+ if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
+ position = mMediaPlayer.getCurrentPosition();
+ }
+ PlaybackState.Builder stateBuilder = new PlaybackState.Builder()
+ .setActions(getAvailableActions());
+ stateBuilder.setState(mState, position, 1.0f);
+ mSession.setPlaybackState(stateBuilder.build());
+}
+private long getAvailableActions() {
+ long actions = PlaybackState.ACTION_PLAY |
+ PlaybackState.ACTION_PLAY_FROM_MEDIA_ID |
+ PlaybackState.ACTION_PLAY_FROM_SEARCH;
+ if (mPlayingQueue == null || mPlayingQueue.isEmpty()) {
+ return actions;
+ }
+ if (mState == PlaybackState.STATE_PLAYING) {
+ actions |= PlaybackState.ACTION_PAUSE;
+ }
+ if (mCurrentIndexOnQueue > 0) {
+ actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
+ }
+ if (mCurrentIndexOnQueue < mPlayingQueue.size() - 1) {
+ actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
+ }
+ return actions;
+}
+
+
+For the track currently playing, set the {@link android.media.MediaMetadata} with the +{@link android.media.session.MediaSession#setMetadata(android.media.MediaMetadata) setMetadata()} +method. This method of the media session object lets you provide information to the Now Playing card +about the track such as the title, subtitle, and various icons. The following example assumes your +track's data is stored in a custom data class, {@code MediaData}.
+ +
+private void updateMetadata(MediaData myData) {
+ MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();
+ // To provide most control over how an item is displayed set the
+ // display fields in the metadata
+ metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE,
+ myData.displayTitle);
+ metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE,
+ myData.displaySubtitle);
+ metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI,
+ myData.artUri);
+ // And at minimum the title and artist for legacy support
+ metadataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE,
+ myData.title);
+ metadataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST,
+ myData.artist);
+ // A small bitmap for the artwork is also recommended
+ metadataBuilder.putString(MediaMetadata.METADATA_KEY_ART,
+ myData.artBitmap);
+ // Add any other fields you have for your data as well
+ mSession.setMetadata(metadataBuilder.build());
+}
+
+
+When the user selects the Now Playing card, the system opens the app that owns the session. +If your app provides a {@link android.app.PendingIntent} to pass to +{@link android.media.session.MediaSession#setSessionActivity(android.app.PendingIntent) setSessionActivity()}, +the system launches the activity you specify, as demonstrated below. If not, the default system +intent opens. The activity you specify must provide playback controls that allow users to pause or +stop playback.
+ ++Intent intent = new Intent(mContext, MyActivity.class); + PendingIntent pi = PendingIntent.getActivity(context, 99 /*request code*/, + intent, PendingIntent.FLAG_UPDATE_CURRENT); + mSession.setSessionActivity(pi); ++