The newer versions include a bugfix that automatically highlights
when our project requires enhanced Java 8 desugaring.
Issue: androidx/media#1312
PiperOrigin-RevId: 631373018
Since Kotlin 2.0 the compiler became better at detecting incorrect
annotation applications. The @OptIn annotation can't be applied to an
expression, so when compiling with Kotlin 2.0 it results in an error.
PiperOrigin-RevId: 604596657
The `PlaybackService` of the demo app is declared
as `androidx.media3.session.MediaSessionService` instead
of `androidx.media3.session.MediaLibraryService`. While
this technically works, its confusing to do that in the
demo app.
Generally, apps that declare the legacy
`android.media.browse.MediaBrowserService` should also
declare `androidx.media3.session.MediaLibraryService`
and the demo app should reflect this common case.
Issue: androidx/media#672
PiperOrigin-RevId: 595320994
When MediaItems are added from the controller, we currently completely
replace the item with the one from our database, overriding any
potential additional information the controller may have set.
Also forward the onAddMediaItems/onSetMediaItems callbacks to common
helper methods instead of redirecting them through super methods
#minor-release
Issue: androidx/media#706
PiperOrigin-RevId: 573799351
Future.isDone and getDone doesn't imply the Future was successful
and it may have been cancelled or failed.
In case where we handle failure, we should also handle cancellation
to avoid CancellationException to bubble up unchecked.
In demo app code where we use isDone for field initialization, we
want to crash in the failure case (usually security exception where
the connection is disallowed), but we want to gracefully handle
cancellation. Cancellation of these variables usually happens in
Activity.onDestroy/onStop, but methods may be called after this point.
#minor-release
PiperOrigin-RevId: 572178018
The current metadata updates are triggered by item transitions,
but depending on the speed of loading the playlist, the first
metadata may only be known later via metadata-change callbacks.
Slow playlist loading also means the UI stays empty and it's
beneficial to show a placeholder to avoid the impressions the
UI hangs.
Finally, clean-up by removing unused string constants and merging
all listeners into onEvents
#minor-release
PiperOrigin-RevId: 571951529
To support Automotive with the session demo, we need a separate app module.
To do this we need to split the service into its own module and make it
usable from different modules.
PiperOrigin-RevId: 568975271
The library already maintains the subscribed controllers internally. This
change adds `MediaLibrarySession.getSubscribedControllers(mediaId)` to
access subscribed controllers for a given media ID.
To accept a subscription, `MediaLibraryService.Callback.onSubscribe` is
required to return `RESULT_SUCCESS`. So far, this isn't the case for the
default implementation of the library.
This change implements `Callback.onSubscribe` to conditionally
provide `RESULT_SUCCESS`. The default calls `Callback.onGetItem(mediaId)` to
assess the availability of the media item. If the app retruns `RESULT_SUCCESS`
with a browsable item, the subscription is accepted. If receiving a valid item
fails, the subscription is rejected.
Issue: androidx/media#561
PiperOrigin-RevId: 568925079
With this change, the notification controller that is connected by
`MediaNotificationManager`, is used as a proxy controller of the
System UI controller. An app can use the proxy at connection time
and during the lifetime of the session for configuration of the
platform session and the media notification on all API levels.
This includes using custom layout and available player and session
commands of the proxy to maintain the platform session (actions,
custom actions, session extras) and the `MediaNotification.Provider`.
The legacy System UI controller is hidden from the public API,
instead the app interacts with the Media3 proxy:
- System UI is hidden from `MediaSession.getConnectedControllers()`.
- Calls from System UI to methods of `MediaSession.Callback`/
`MediaLibrarySession.Callback` are mapped to the `ControllerInfo`
of the proxy controller.
- When `getControllerForCurrentRequest()` is called during an operation of
System UI the proxy `ControllerInfo` is returned.
PiperOrigin-RevId: 567606117
This helps to highlight and document new requirements for apps,
e.g. to add the FOREGROUND_SERVICE_MEDIA_PLAYBACK permission for
background playback.
Issue: google/ExoPlayer#11239
PiperOrigin-RevId: 548666056
This change also marks the buttons of the custom layout as
enabled/disabled according to available commands in the controller.
Accordingly, `CommandButton.Builder.setEnabled(boolean)` is deprecated
because the value is overridden by the library.
Issue: androidx/media#38
#minor-release
PiperOrigin-RevId: 547272588
This change deprecates `PlayerView.setUseArtwork(boolean)` and
introduces `setArtworkDisplayMode(mode)` and
`artworkDisplayMode="off|fit|fill"` instead.
- off: no artwork is displayed (like deprecated useArtwork=false)
- fit: letterbox like media (like deprecated useArtwork=true)
- fill: scales the artwork to fill the entire width/weight of the player view
#minor-release
PiperOrigin-RevId: 534167226
Basically this change removes a bug that makes video playback stuck when
a video is playing and the user taps the UMO notification to get to
the player activity.
- Use `launchMode="singleTop"` for `PlayerActivity`
- Change session activity to a back stacked activity on service `onDestroy`.
Using a back stacked activity `onDestroy()` will be useful once this demo
app implements playback resumption.
The rest of the changes are aesthetic:
- clean up and optimize screen space usage in UI of `PlayerActivity`
- changed some colors, paddings and spacings
- adds a default artwork for the `PlayerView`
PiperOrigin-RevId: 534152052
This is a pre-requisite for the Android Studio upgrade assistant to
upgrade from AGP 7.2.2 to 8.0.1, otherwise it fails and complains
this is missing.
Issue: androidx/media#409
PiperOrigin-RevId: 533463246
The current code flags a lint error:
```
Error: Call requires API level 24 (current min is 16): java.lang.Iterable#forEach [NewApi]
```
I think this is a bit confusing because this is calling the Java
[`Iterable.forEach`](https://developer.android.com/reference/java/lang/Iterable#forEach(java.util.function.Consumer%3C?%20super%20T%3E))
method which was added in Java 8 (and therefore is only available on
API 24 and up), but there is **also** a Kotlin
[`List.forEach`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/for-each.html)
method which is available in all versions of Kotlin (and therefore all
Android versions). Since this is a Kotlin file, at first glance you
would assume this is the Kotlin method - but it's not.
This also doesn't seem to be flagged by Android Studio, but is caught
by Gradle lint on the command line.
#minor-release
PiperOrigin-RevId: 529112610
To reliably reject the System UI playback resumption notification on
all API levels (specifically API 30), the backward compatibility layer
needs to return `null` for the library root.
This is not possible in the Media3 implementation. This change allows
an app to return a `LibraryResult.ofError(RESULT_ERROR_NOT_SUPPORTED)`
that then is translated to return null by the backwards compatibility
layer.
Issue: androidx/media#355
Issue: androidx/media#167
Issue: androidx/media#27
See https://developer.android.com/guide/topics/media/media-controls#mediabrowserservice_implementation
PiperOrigin-RevId: 527276529
The PlayerView methods are documented to only be needed for sphrerical
playbacks, which we are not using in the session demo app.
PiperOrigin-RevId: 525986709
The button gets only updated after an onTracksChanged callback but
isn't set to the initial state similar to other changes triggered
by callbacks (e.g. updateRepeatSwitchUI)
PiperOrigin-RevId: 522274800
The folder type has a mix of information about the item. It shows
whether the item is browsable (type != FOLDER_TYPE_NONE) and
which Bluetooth folder type to set for legacy session information.
It's a lot clearer to split this into a boolean isBrowsable and
use the existing mediaType to map back to the bluetooth folder type
where required.
folderType is not marked as deprecated yet as this would be an API
change, which will be done later.
PiperOrigin-RevId: 493544589
When app is deployed with device's screen being off, MainActivity's onStart is called swiftly by its onStop. The onStop method cancels the browserFuture task which in turn "completes" the task. Upon task "completion", pushRoot() runs and then throws error as it calls get() a cancelled task.
PiperOrigin-RevId: 492416445
PlayableFolderActivity currently uses two seperate commands
to set the playlist and then seek to the requested item.
This is slightly inefficient and also causes analytics
listeners to believe the first item in the playlist was
briefly active.
#minor-release
Issue: androidx/media#180
PiperOrigin-RevId: 480031682
Replacing remaining usage of MoreExecutors.directExecutor. This allows the service to be switched to run in another process and the app still works the same as if it is running in the same process.
Issue: androidx/media#100
PiperOrigin-RevId: 471547177
This allows the service to be switched to run in another process and the app still works the same as if it is running in the same process.
Issue: androidx/media#100
PiperOrigin-RevId: 458460005
These legacy callbacks are currently forwarded to onSetMediaUri which
will be removed in the future.
Also make sure to only call player.prepare/play after the items have
been set.
The calls to onAddQueueItem are also forwarded to onAddMediaItems to
actually allow a session to resolve these items to playable media, which
wasn't possible so far.
PiperOrigin-RevId: 453625204
The MediaItemFiller is not flexible enough for most realworld usages
because:
- it doesn't allow asynchronous resolution of MediaItems (e.g. to
look up URIs from a database)
- it doesn't allow to batch updates for multiple items or do more
advanced customizations (e.g. expanding a mediaId representing
a playlist to multiple items).
Both issues can be solved by passing in a list of items and
returning a ListenableFuture. The callback itself can also move
into MediaSession.Callback for consistency with the other
callbacks.
PiperOrigin-RevId: 451857319