If your app plays audio or video
there's a bunch of new features in Android 11
that will make your users' lives easier as well as updated libraries which you
the developer, can take advantage of.
Let's jump straight in.
So I'm really excited about the new Media Controls
in Android 11.
On previous versions of Android
media notifications were displayed on top of each other
with all the other notifications.
With multiple media apps, things could get pretty cluttered.
On Android 11
media notifications have been moved next to the Quick Settings panel
and are known as Media Controls.
This is a dedicated, persistent space
for controlling media playback.
It shows current and recent MediaSessions in a carousel
and there's even an output switcher
so you can easily switch between playback devices.
More on this later on.
So as a media app developer
you can support these Media Controls by creating a MediaSession
and using MediaStyle for your notification.
These APIs have been around since Lollipop so chances are you're doing this already.
To understand exactly how the Media Controls are created
using the notification and MediaSession
let's take a look at some code.
First, we create a MediaSession.
This is usually done inside a service if your app plays audio in the background.
Then create a MediaStyle object
and supply your MediaSession token to it.
Now create a notification which is styled by your MediaStyle object.
By doing this, you've connected your MediaSession
to the Media Controls.
You also want to specify any actions
which your users can perform, such as pausing and skipping
to the next track.
And this can be done using addAction.
The Media Controls have two possible views.
The collapsed view is shown on the lock screen
and when swiping down from the top of the screen.
This can contain up to three actions
and these are specified using setShowActionsInCompactView.
The expanded view is shown
when the user expands the Quick Settings area.
It can have up to five actions.
Once you've posted the notification
all other information is pulled from the MediaSession's metadata
and playback state.
First let's take a look at the metadata.
This is set using setMetadata
and can be constructed using a builder.
There are four metadata fields which are displayed
in the Media Controls.
These are Title
artist
although this could be used for the name of the TV channel or video series
album art
this could be a screenshot or header image for video content
and lastly, duration.
If the duration isn't set, such as for live broadcast
then the progress indicator won't be shown on the Seek Bar.
Talking of the Seek Bar
this is updated from the MediaSession's playback state
in a similar way using setPlaybackState.
Position is used to update the elapsed time in the progress bar.
Playback speed determines the rate at which the elapsed time changes
useful when you want to play content faster than normal
like, for example, this video.
Adding the SEEK_TO action indicates
that seeking is supported and makes the position marker draggable.
If this is not supplied, Seek will be disabled
but progress will still be shown.
So we've covered creating a MediaStyle notification
including specifying the actions which your app supports
setting metadata for the track title and other information
and using playback state to control the Seek Bar.
This is everything you need to know to ensure your Media Controls look great.
So now let's take a look at a related feature of Android 11
called Media Resumption.
This feature allows you to find
and resume playback of your TV episode, podcast
or drum-and-bass set at the exact point you left off
even after you've rebooted your device.
It creates Media Controls for up to five recent media apps
and puts them in a carousel below the Quick Settings area.
To support this feature
your app must provide a MediaBrowserService.
This allows the system to retrieve information about the content
which your app recently played.
After beating, the system UI will call your MediaBrowserServices
onGetRoot method.
Now usually, you'd return the root of your media tree from this method
but the system UI also specifies the EXTRA_RECENT hint.
You should treat EXTRA_RECENT as a special case
and prepare to resume playback where the user left off.
So you should return the root of a media tree
that contains the most recently played media item
as the first element.
The system UI will call your onLoadChildren method
to obtain this media tree
which is a list of media item objects.
For the first playable media item in this list
the system UI will create static Media Controls
with just a Play button.
If the user taps the Play button
the system UI will make another call to onGetRoot
with the EXTRA_RECENT hint.
This is so you can prepare your previously played content as before
just in case anything has changed since the static controls were created.
System UI will then connect to your MediaSession
and issue a play command to it.
You should override the MediaSession onPlay callback
in order to start playback of your media content
and create your MediaStyle notification.
Once you post the notification, the static Media Controls will be swapped
with the Media Controls created from your notification.
As well as being able to resume MediaSessions
Android 11 also allows you to easily transfer playback
from one device to another.
This is known as seamless media transfer
and it's done through the Output Switcher.
When you type on the Output Switcher
you'll see a list of media routes available to your app.
By default, only local media routes are shown
such as the built-in speaker
and Bluetooth headphones.
If your app supports other media routes
such as remote playback, you'll need to let the system know.
And here's how you do that.
First you add the MediaRouter Jetpack library to your app.
Seamless media transfer is supported from 1.2 alpha02 onwards.
Next, add the MediaTransferReceiver class
to your Android manifest.
Now, in your app
obtain a MediaRouter singleton
which is an object that maintains the state
of all currently available media routes.
Create a MediaRouteSelector and specify the route categories
which your app supports.
The categories you define here determine
the routes which are displayed in the Output Switcher.
Here we'll just specify the REMOTE_PLAYBACK category
which is used for cast devices.
If you want to support transfer from remote to local devices
you'll need to explicitly enable this
using setTransferToLocalEnabled.
We can now use our selector when adding a MediaRouter callback.
We also supply a callback object so we can be informed
of changes to media routes.
Here's the callback class.
The method we overwrite is onRouteSelected
which will be called whenever a new media route has been selected.
When this happens, we need to consider
the reason why it was selected.
If the existing route was disconnected
for example, Bluetooth headphones were switched off
we should pause or stop playback.
If the route was actively changed
for example, when switching from a phone to a cast device
then we should continue playing the media from its previous playback position.
This is the seamless part of seamless media transfer.
To get started testing your app with these new media features
download the latest Android 11 beta.
Media controls are supported from beta 2.5 onwards.
You can test your media browser service implementation
using the Media Controller Tester.
Lastly, the Universal Android Music Player
or UAMP for short, contains a reference implementation
for these new features.
It's the canonical code sample for many of the media APIs
and uses ExoPlayer under the hood.
It's also been recently updated to support playback through cast devices.
Check it out on GitHub.
Right. Let's talk about media streaming and 5G.
When streaming media over a network
it's important to be aware of whether that network is metered.
This can help you decide which media streams
are most appropriate to serve to the user.
Historically, the meteredness of a network has been constant
so you only needed to detect this once per connection.
With 5G networks, however
the meteredness of a network can change whilst the connection is still active.
Essentially, meteredness becomes dynamic.
For this reason, Android 11 introduced a new network capabilities constant
called TEMPORARILY_NOT_METERED.
This indicates that a usually metered network
is temporarily unmetered.
To handle meteredness changes in your app
you should first obtain a reference to ConnectivityManager
then register a network callback
and override the onCapabilitiesChanged method.
This is called as soon as you register the callback
so you can detect the current capabilities of the network.
If the network has either the TEMPORARILY_NOT_METERED
or NOT_METERED capability
you know it's unmetered and opens up the possibility to serve
higher-bit rate content, depending on bandwidth.
Just remember to serve more conservative streams
when the user is back on the metered network.
Now let's talk about updates to media APIs and libraries.
From NDK 21, OpenSL ES is deprecated.
For many years, this has been the go-to API
for apps and games requiring low-latency audio and/or portability.
If you're using OpenSL ES
you should migrate your code to use the Oboe library.
It's an open-source library
which is backward compatible to API 16.
It's designed for high performance and ease of use.
It uses the latest AAudio API on devices that support it
falling back to OpenSL ES on older devices.
It's usually simple to migrate
since Oboe has a much-simplified API.
And adding the dependency has been simplified in recent releases
so you no longer need to build Oboe from source.
From version 1.3 onwards
the library is available from Google's Maven Repository
and can be added the same way you add a Jetpack library.
You can open an audio stream in just a few lines of code.
And the newest release, 1.42
sees the addition of streams creation via shared pointer
to ease lifecycle handling.
Check out the full migration guide here.
In Android 11, the MediaCodec API has had some updates as well.
You now have more control over allocating input and output buffers
allowing you to manage the memory associated
with encoding and decoding more efficiently.
There's also support for low-latency decoding
which is especially useful when streaming live content
such as games and live broadcasts.
So we've covered the new media controls
playback resumption and seamless media transfer
as well as handling 5G networks and supporting the latest media APIs.
For a full list of features in Android 11
check out the official release notes
and be sure to check out UAMP
the canonical code sample for music streaming
and playback on Android.
Thanks for watching.