Having all sorts of fun trying to get the desired metadata, lockscreen and cast popup behaviour working in a music app that utilizes a custom receiver on Chromecast. Here's where I've got to..
private void _dummyRemotePlay(long id,String mUrl,String artist,String title,String iUrl) {
// CODE THAT CHANGES BEHAVIOUR
MediaTrack.Builder b = new MediaTrack.Builder(id,MediaTrack.TYPE_AUDIO);
b.setSubtype(MediaTrack.SUBTYPE_METADATA);
// END CODE THAT CHANGES BEHAVIOUR
MediaMetadata mdata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MUSIC_TRACK);
mdata.putString(MediaMetadata.KEY_ARTIST, artist);
mdata.putString(MediaMetadata.KEY_TITLE, title);
mdata.addImage(new WebImage(Uri.parse(iUrl)));
MediaInfo mi = new MediaInfo.Builder(mUrl)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("audio/mpeg")
.setMetadata(mdata)
.build();
MediaQueueItem qi = new
MediaQueueItem.Builder(mi).setAutoplay(true).setPreloadTime(20).build();
MediaQueueItem[] qa = new MediaQueueItem[]{qi,qi}; // Two so SKIP_NEXT works...
_remoteMediaClient.queueLoad(qa,0,MediaStatus.REPEAT_MODE_REPEAT_OFF, null);}
Without the call to b.setSubType(MediaTrack.SUBTYPE_METADATA) the cast popup works (image, controls etc), a cast notification appears and the cast volume is adjusted by the volume keys. What doesn't work is the lockscreen metadata and controls. The artist is unknown and the controls do nothing.
With the b.setSubType call the lockscreen works fine (artist correctly displayed, controls work). However, there's no cast notification and the cast popup has no media selected (no image, no controls, just volume slider and end cast). Also the volume keys are not bound to cast volume.
Arrived at this point just playing around. Originally called b.build() to create a MediaTrack, added it to a list and called .setMediaTracks(list) on the MediaInfo.builder. Distilled it down to just the above though. The b.setSubType call on just a builder without a MediaTrack being built is enough to switch behaviour.
What I'm looking for is correct lockscreen behaviour, correct cast dialog image and control, volume keys working. I'm indifferent to a cast notification as the app has one anyway. It seems I can't achieve all of this.
Related
I am using exo-player and media session extension like this.
mediaSessionCompat = new MediaSessionCompat(activity, activity.getPackageName());
MediaSessionConnector sessionConnector = new MediaSessionConnector(mediaSessionCompat);
sessionConnector.setPlayer(exoPlayer);
mediaSessionCompat.setActive(true);
When I enter into PIP window, it shows 3 control buttons (play/pause, skip-to-next, skip-to-previous). I only want the play/pause button and want to remove skip-to-next and skip-to-previous buttons.
How would I do that?
While I'm not extremely familiar with the way PIP displays supported actions, you may want to review precisely which actions your MediaSession is reporting.
For some background, I provided a snippet for declaring supported actions in my MediaSession codelab.
In your case, MediaSessionConnector seems to have discovered that there is a playback queue. You may want to instead review how the content of your queue is being provided into your ExoPlayer's media source.
There are two ways of validating that the MediaSession only contains the right actions:
Media Controller Test is mobile app that allows you to see which actions are reported and test them in a nifty UI.
You can instead inspect the output of adb shell dumpsys media_session:
Note that in this example of YouTube, the playback queue contains 5 items and therefore the action ACTION_SKIP_TO_NEXT is included in the bitwise mask:
For details about these action constants, I can recommend reading more about the actions as declared in PlaybackState.
Once you've confirmed that the MediaSession is reporting the right actions, the PIP display should no longer show skipping next and previous.
I do have my own application for media playback - it's using MediaSessionCompat (with combination with ExoPlayer and it's MediaSessionConnector plugin).
On Samsung phone I experience a small issue with AOD (Always On Display) and lock screen. Both contains a small media controller (three buttons) and track title and album - I assume it works with MediaSession.
My problem is that it always shows Unknown / Unknown for title / album (but buttons are working correctly). I'm sure that I'm feeding correctly MediaSession metadata, as it is used in Activities, where using onMetadataChange callback and it contains correct title.
I'm somehow lost, not sure where to look for issue and fix. It's clearly in my app, because other players are working fine (showing title on AOD), but I do not know what else I need to do apart of settings metadata in MediaSession?
So shortly
Exoplayer uses MediaDescriptionCompat to get meta from play queue. Then it maps it to MediaMetadataCompat and title is mapped to key MEDIA_KEY_DISPLAY_TITLE , where Samsung is using key MEDIA_KEY_TITLE only.
Solution was to add MEDIA_KEY_TITLE to MediaDescriptionCompat.extras.
Another item displayed in Samsung AOD, lock screen is MediaMetadataCompat.METADATA_KEY_ARTIST
Another example of useless complexity in Android - why we need to two classes for metadata, which are almost the same MediaMetadataCompat vs MediaDescriptionCompat?
#Ivan's answer worked for me. Here is an example in Kotlin:
mediaSessionConnector = MediaSessionConnector(mediaSession).also {
it.setPlayer(player)
}
mediaSessionConnector.setQueueNavigator(object : TimelineQueueNavigator(mediaSession){
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
val extra = Bundle()
extra.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "podcastEpisode")
return MediaDescriptionCompat.Builder().setExtras(extra).setTitle("podcastTitle").build()
}
})
This issue was also very helpful.
I would like to set the italic "Contents hidden" message for a public notification manually.
Android seem to set "Contents hidden" automatically if only a VISIBILITY_PRIVATE notification without a public counterpart is presented.
Here, the setContent-parts are automatically replaced.
For an example from K9mail see screenshot 1.
However, I would like to use a custom layout for the public notification while letting the notification look similar (i.e., "Contents hidden").
It is a notification for a music player, which should provide buttons for pause and play next songs.
So, how can I either
access the (localized) value for "Contents hidden" that Android is actually using (not implementing it manually) or
tell Android to replace all "setContent"-parts automatically as if I would not provide a public notification.
Any suggestions?
For the sake of completeness - the issue is related with this pull request: https://github.com/gateship-one/odyssey/pull/120
Pretty simple just use:
String foo = mContext.getString(android.content.res.Resources.getSystem().getIdentifier("notification_hidden_text", "string", "android"));
I just wanted to know how to disable the youtube icon that comes in the YouTubeStandalonePlayer. Is it possible?
I don't want to take the user to youtube on clicking the icon. Is there any way to disable the youtube icon?
The below is the code how I am playing the the video using the YouTubeStandalonePlayer.
String videoId = getVideoId(cardsInfo.getCard_video_url());
Intent intent = YouTubeStandalonePlayer.createVideoIntent(getActivity(), getResources().getString(R.string.android_key), videoId, 0, true, false);
startActivity(intent);
According to the API, you can't.
But, you can try and use the other (not standalone) classes, which might give you better control as suggested in the docs: There are two ways to play videos. The first option is to place a YouTubePlayerFragment or YouTubePlayerView in your View hierarchy and then use the YouTubePlayer to control video playback in the View. **This gives a fine control of the experience**. If they don't let it, you could atleast have better control of the flow/UI-visibility because you are controling the Activity (in contrast of giving the control to the standalone activity)
So building a new app specifically for the Android TV interface (lollipop leanback) and I'm using the PlaybackOverlayFragment that is provided by the framework which has a PlaybackControlsRow with all the usual controls on it.
The problem is, the default behavior is for the user to have to click the "Play" button to start the video and I want it to start automatically. That part is easy and I have it working but then the Play/Pause icons on the provided control are out of sync (showing play when should be pause) because the item was started outside of the events of clicking on that control.
Documentation is sparse on these framework elements and examining the class I can't find any public method that would allow me to put this control in the proper "mode" or tell it to display the play or pause icon myself.
Anyone with experience with these yet that would know how to do this?
In order to change the state of the button, even after adding your Actions to the Adapter, you'll need to notify the changes to the adapter that has your Action.
mPlayPauseAction.nextIndex(); // next index, if it was pause, it'll be play
notifyChanged(mPlayPauseAction);
// where notifyChanged(Action action) is:
private void notifyChanged(Action action) {
ArrayObjectAdapter adapter = mPrimaryActionsAdapter; // reference to your adapter
if (adapter.indexOf(action) >= 0) {
adapter.notifyArrayItemRangeChanged(adapter.indexOf(action), 1);
return;
}
}
Well, I partially answered my own question.
If I know before the PlaybackControlsRow is created that I want to set it to the pause state (actually, playing state but showing pause button) then if I call setIndex(PlaypauseAction.PAUSE) on the PlayPauseAction before adding it to the controlsrow then it works.
It doesn't appear that I can modify it myself after adding it but that may be something else I'm doing wrong.