diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index c32439333a..dfc78ad58c 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -17,10 +17,10 @@ body: tracker: https://github.com/google/ExoPlayer/issues?q=is%3Aissue - type: dropdown attributes: - label: Media3 Version + label: Version description: What version of Media3 (or ExoPlayer) are you using? options: - - Media3 1.1.0-alpha01 + - Media3 1.1.0 - Media3 1.0.2 - Media3 1.0.1 - Media3 1.0.0 @@ -33,6 +33,8 @@ body: - Media3 1.0.0-alpha02 - Media3 1.0.0-alpha01 - Media3 `main` branch + - Media3 pre-release (alpha, beta or RC not in this list) + - ExoPlayer 2.19.0 - ExoPlayer 2.18.7 - ExoPlayer 2.18.6 - ExoPlayer 2.18.5 @@ -54,6 +56,12 @@ body: - Older (unsupported) validations: required: true + - type: textarea + attributes: + label: More version details + description: | + Required if you selected `main` or `dev-v2` (please provide an exact commit SHA), + or 'pre-release' or 'older' (please provide the version). - type: textarea attributes: label: Devices that reproduce the issue @@ -114,7 +122,7 @@ body: * Attach a file here * Include a media URL * Refer to a piece of media from the demo app (e.g. `Misc > Dizzy (MP4)`) - * If you don't want to post media publicly please email the info to dev.exoplayer@gmail.com with subject 'Issue #\' after filing this issue, and note that you will do this here. + * If you don't want to post media publicly please email the info to android-media-github@google.com with subject 'Issue #\' after filing this issue, and note that you will do this here. * If you are certain the issue does not depend on the media being played, enter "Not applicable" here. For DRM-protected media please also include the scheme and license server URL. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 386abe6bf9..3f753dbd18 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -39,6 +39,6 @@ Don't forget to check ExoPlayer's supported formats and devices, if applicable (https://developer.android.com/guide/topics/media/exoplayer/supported-formats). If there's something you don't want to post publicly, please submit the issue, -then email the link/bug report to dev.exoplayer@gmail.com using a subject in the -format "Issue #1234", where #1234 is your issue number (we don't reply to -emails). +then email the link/bug report to android-media-github@google.com using a +subject in the format "Issue #1234", where #1234 is your issue number (we don't +reply to emails). diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 0000000000..f5071cd805 --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5908bd201c..04120620fe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,24 @@ you made on top of `main` using $ git diff -U0 main... | google-java-format-diff.py -p1 -i ``` +### Push access to PR branches + +Please ensure maintainers of this repository have push access to your PR branch +by ticking the `Allow edits from maintainers` checkbox when creating the PR (or +after it's created). See the +[GitHub docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) +for more info. This allows us to make changes and fixes to the PR while it goes +through internal review, and ensures we don't create an +['evil' merge](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefevilmergeaevilmerge) +when it gets merged. + +This checkbox only appears on PRs from individual-owned forks +(https://github.com/orgs/community/discussions/5634). If you open a PR from an +organization-owned fork we will ask you to open a new one from an +individual-owned fork. If this isn't possible we can still merge the PR, but it +will result in an 'evil' merge because the changes and fixes we make during +internal review will be part of the merge commit. + ## Contributor license agreement Contributions to any Google project must be accompanied by a Contributor diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fc703b1471..77fdf3ec00 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,300 @@ # Release notes +## 1.1 + +### 1.1.0 (2023-07-05) + +This release corresponds to the +[ExoPlayer 2.19.0 release](https://github.com/google/ExoPlayer/releases/tag/r2.19.0). + +This release contains the following changes since the +[1.0.2 release](#102-2023-05-18): + +* Common Library: + * Add suppression reason for unsuitable audio route and play when ready + change reason for suppressed too long. + ([#15](https://github.com/androidx/media/issues/15)). + * Add commands to Player: + * `COMMAND_GET_METADATA` + * `COMMAND_SET_PLAYLIST_METADATA` + * `COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS` + * `COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS` + * Add overloaded methods to Player which allow users to specify volume + flags: + * `void setDeviceVolume(int, int)` + * `void increaseDeviceVolume(int)` + * `void decreaseDeviceVolume(int)` + * `void setDeviceMuted(boolean, int)` + * Add `Builder` for `DeviceInfo` and deprecate existing constructor. + * Add `DeviceInfo.routingControllerId` to specify the routing controller + ID for remote playbacks. + * Add `Player.replaceMediaItem(s)` as a shortcut to adding and removing + items at the same position + ([#8046](https://github.com/google/ExoPlayer/issues/8046)). +* ExoPlayer: + * Allow ExoPlayer to have control of device volume methods only if + explicitly opted in. Use + `ExoPlayer.Builder.setDeviceVolumeControlEnabled` to have access to: + * `getDeviceVolume()` + * `isDeviceMuted()` + * `setDeviceVolume(int)` and `setDeviceVolume(int, int)` + * `increaseDeviceVolume(int)` and `increaseDeviceVolume(int, int)` + * `decreaseDeviceVolume(int)` and `decreaseDeviceVolume(int, int)` + * Add `FilteringMediaSource` that allows to filter available track types + from a `MediaSource`. + * Add support for including Common Media Client Data (CMCD) in the + outgoing requests of adaptive streaming formats DASH, HLS, and + SmoothStreaming. The following fields, `br`, `bl`, `cid`, `rtp`, and + `sid`, have been incorporated + ([#8699](https://github.com/google/ExoPlayer/issues/8699)). API + structure and API methods: + * CMCD logging is disabled by default, use + `MediaSource.Factory.setCmcdConfigurationFactory(CmcdConfiguration.Factory + cmcdConfigurationFactory)` to enable it. + * All keys are enabled by default, override + `CmcdConfiguration.RequestConfig.isKeyAllowed(String key)` to filter + out which keys are logged. + * Override `CmcdConfiguration.RequestConfig.getCustomData()` to enable + custom key logging. + * Add additional action to manifest of main demo to make it easier to + start the demo app with a custom `*.exolist.json` file + ([#439](https://github.com/androidx/media/pull/439)). + * Add `ExoPlayer.setVideoEffects()` for using `Effect` during video + playback. + * Update `SampleQueue` to store `sourceId` as a `long` rather than an + `int`. This changes the signatures of public methods + `SampleQueue.sourceId` and `SampleQueue.peekSourceId`. + * Add parameters to `LoadControl` methods `shouldStartPlayback` and + `onTracksSelected` that allow associating these methods with the + relevant `MediaPeriod`. + * Change signature of + `ServerSideAdInsertionMediaSource.setAdPlaybackStates(Map)` by adding a timeline parameter that contains the + periods with the UIDs used as keys in the map. This is required to avoid + concurrency issues with multi-period live streams. + * Deprecate `EventDispatcher.withParameters(int windowIndex, @Nullable + MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs)` and + `BaseMediaSource.createEventDispatcher(..., long mediaTimeOffsetMs)`. + The variant of the methods without the `mediaTimeOffsetUs` can be called + instead. Note that even for the deprecated variants, the offset is not + anymore added to `startTimeUs` and `endTimeUs` of the `MediaLoadData` + objects that are dispatched by the dispatcher. + * Rename `ExoTrackSelection.blacklist` to `excludeTrack` and + `isBlacklisted` to `isTrackExcluded`. + * Fix inconsistent behavior between `ExoPlayer.setMediaItem(s)` and + `addMediaItem(s)` when called on an empty playlist. +* Transformer: + * Remove `Transformer.Builder.setMediaSourceFactory(MediaSource.Factory)`. + Use `ExoPlayerAssetLoader.Factory(MediaSource.Factory)` and + `Transformer.Builder.setAssetLoaderFactory(AssetLoader.Factory)` + instead. + * Remove `Transformer.startTransformation(MediaItem, + ParcelFileDescriptor)`. + * Fix a bug where transformation could get stuck (leading to muxer + timeout) if the end of the video stream was signaled at the moment when + an input frame was pending processing. + * Query codecs via `MediaCodecList` instead of using + `findDecoder/EncoderForFormat` utilities, to expand support. + * Remove B-frame configuration in `DefaultEncoderFactory` because it + doesn't work on some devices. +* Track selection: + * Add + `DefaultTrackSelector.Parameters.allowInvalidateSelectionsForRendererCapabilitiesChange` + which is disabled by default. When enabled, the `DefaultTrackSelector` + will trigger a new track selection when the renderer capabilities + changed. +* Extractors: + * Ogg: Fix bug when seeking in files with a long duration + ([#391](https://github.com/androidx/media/issues/391)). + * FMP4: Fix issue where `TimestampAdjuster` initializes a wrong timestamp + offset with metadata sample time from emsg atom + ([#356](https://github.com/androidx/media/issues/356)). +* Audio: + * Fix bug where some playbacks fail when tunneling is enabled and + `AudioProcessors` are active, e.g. for gapless trimming + ([#10847](https://github.com/google/ExoPlayer/issues/10847)). + * Encapsulate Opus frames in Ogg packets in direct playbacks (offload). + * Extrapolate current position during sleep with offload scheduling. + * Add `Renderer.release()` and `AudioSink.release()` for releasing the + resources at the end of player's lifecycle. + * Listen to audio capabilities changes in `DefaultAudioSink`. Add a + required parameter `context` in the constructor of `DefaultAudioSink`, + with which the `DefaultAudioSink` will register as the listener to the + `AudioCapabilitiesReceiver` and update its `audioCapabilities` property + when informed with a capabilities change. + * Propagate audio capabilities changes via a new event + `onAudioCapabilitiesChanged` in `AudioSink.Listener` interface, and a + new interface `RendererCapabilities.Listener` which triggers + `onRendererCapabilitiesChanged` events. + * Add `ChannelMixingAudioProcessor` for applying scaling/mixing to audio + channels. + * Add new int value `DISCARD_REASON_AUDIO_BYPASS_POSSIBLE` to + `DecoderDiscardReasons` to discard audio decoder when bypass mode is + possible after audio capabilities change. + * Add direct playback support for DTS Express and DTS:X + ([#335](https://github.com/androidx/media/pull/335)). +* Video: + * Make `MediaCodecVideoRenderer` report a `VideoSize` with a width and + height of 0 when the renderer is disabled. + `Player.Listener.onVideoSizeChanged` is called accordingly when + `Player.getVideoSize()` changes. With this change, ExoPlayer's video + size with `MediaCodecVideoRenderer` has a width and height of 0 when + `Player.getCurrentTracks` does not support video, or the size of the + supported video track is not yet determined. +* DRM: + * Reduce the visibility of several internal-only methods on + `DefaultDrmSession` that aren't expected to be called from outside the + DRM package: + * `void onMediaDrmEvent(int)` + * `void provision()` + * `void onProvisionCompleted()` + * `onProvisionError(Exception, boolean)` +* Muxer: + * Add a new muxer library which can be used to create an MP4 container + file. +* IMA extension: + * Enable multi-period live DASH streams for DAI. Please note that the + current implementation does not yet support seeking in live streams + ([#10912](https://github.com/google/ExoPlayer/issues/10912)). + * Fix a bug where a new ad group is inserted in live streams because the + calculated content position in consecutive timelines varies slightly. +* Session: + * Add helper method `MediaSession.getControllerForCurrentRequest` to + obtain information about the controller that is currently calling + a`Player` method. + * Add `androidx.media3.session.MediaButtonReceiver` to enable apps to + implement playback resumption with media button events sent by, for + example, a Bluetooth headset + ([#167](https://github.com/androidx/media/issues/167)). + * Add default implementation to `MediaSession.Callback.onAddMediaItems` to + allow requested `MediaItems` to be passed onto `Player` if they have + `LocalConfiguration` (e.g. URI) + ([#282](https://github.com/androidx/media/issues/282)). + * Add "seek to previous" and "seek to next" command buttons on compact + media notification view by default for Android 12 and below + ([#410](https://github.com/androidx/media/issues/410)). + * Add default implementation to `MediaSession.Callback.onAddMediaItems` to + allow requested `MediaItems` to be passed onto `Player` if they have + `LocalConfiguration` (e.g. URI) + ([#282](https://github.com/androidx/media/issues/282)). + * Add "seek to previous" and "seek to next" command buttons on compact + media notification view by default for Android 12 and below + ([#410](https://github.com/androidx/media/issues/410)). +* UI: + * Add Util methods `shouldShowPlayButton` and + `handlePlayPauseButtonAction` to write custom UI elements with a + play/pause button. +* RTSP Extension: + * For MPEG4-LATM, use default profile-level-id value if absent in Describe + Response SDP message + ([#302](https://github.com/androidx/media/issues/302)). + * Use base Uri for relative path resolution from the RTSP session if + present in DESCRIBE response header + ([#11160](https://github.com/google/ExoPlayer/issues/11160)). +* DASH Extension: + * Remove the media time offset from `MediaLoadData.startTimeMs` and + `MediaLoadData.endTimeMs` for multi period DASH streams. + * Fix a bug where re-preparing a multi-period live Dash media source + produced a `IndexOutOfBoundsException` + ([#10838](https://github.com/google/ExoPlayer/issues/10838)). +* HLS Extension: + * Add + `HlsMediaSource.Factory.setTimestampAdjusterInitializationTimeoutMs(long)` + to set a timeout for the loading thread to wait for the + `TimestampAdjuster` to initialize. If the initialization doesn't + complete before the timeout, a `PlaybackException` is thrown to avoid + the playback endless stalling. The timeout is set to zero by default + ([#323](https://github.com/androidx/media/issues//323)). +* Test Utilities: + * Check for URI scheme case insensitivity in `DataSourceContractTest`. +* Remove deprecated symbols: + * Remove `DefaultAudioSink` constructors, use `DefaultAudioSink.Builder` + instead. + * Remove `HlsMasterPlaylist`, use `HlsMultivariantPlaylist` instead. + * Remove `Player.stop(boolean)`. Use `Player.stop()` and + `Player.clearMediaItems()` (if `reset` is `true`) instead. + * Remove two deprecated `SimpleCache` constructors, use a non-deprecated + constructor that takes a `DatabaseProvider` instead for better + performance. + * Remove `DefaultBandwidthMeter` constructor, use + `DefaultBandwidthMeter.Builder` instead. + * Remove `DefaultDrmSessionManager` constructors, use + `DefaultDrmSessionManager.Builder` instead. + * Remove two deprecated `HttpDataSource.InvalidResponseCodeException` + constructors, use a non-deprecated constructor that accepts additional + fields(`cause`, `responseBody`) to enhance error logging. + * Remove `DownloadHelper.forProgressive`, `DownloadHelper.forHls`, + `DownloadHelper.forDash`, and `DownloadHelper.forSmoothStreaming`, use + `DownloadHelper.forMediaItem` instead. + * Remove deprecated `DownloadService` constructor, use a non deprecated + constructor that includes the option to provide a + `channelDescriptionResourceId` parameter. + * Remove deprecated String constants for Charsets (`ASCII_NAME`, + `UTF8_NAME`, `ISO88591_NAME`, `UTF16_NAME` and `UTF16LE_NAME`), use + Kotlin Charsets from the `kotlin.text` package, the + `java.nio.charset.StandardCharsets` or the + `com.google.common.base.Charsets` instead. + * Remove deprecated `WorkManagerScheduler` constructor, use a non + deprecated constructor that includes the option to provide a `Context` + parameter instead. + * Remove the deprecated methods `createVideoSampleFormat`, + `createAudioSampleFormat`, `createContainerFormat`, and + `createSampleFormat`, which were used to instantiate the `Format` class. + Instead use `Format.Builder` for creating instances of `Format`. + * Remove the deprecated methods `copyWithMaxInputSize`, + `copyWithSubsampleOffsetUs`, `copyWithLabel`, + `copyWithManifestFormatInfo`, `copyWithGaplessInfo`, + `copyWithFrameRate`, `copyWithDrmInitData`, `copyWithMetadata`, + `copyWithBitrate` and `copyWithVideoSize`, use `Format.buildUpon()` and + setter methods instead. + * Remove deprecated `ExoPlayer.retry()`, use `prepare()` instead. + * Remove deprecated zero-arg `DefaultTrackSelector` constructor, use + `DefaultTrackSelector(Context)` instead. + * Remove deprecated `OfflineLicenseHelper` constructor, use + `OfflineLicenseHelper(DefaultDrmSessionManager, + DrmSessionEventListener.EventDispatcher)` instead. + * Remove deprecated `DownloadManager` constructor, use the constructor + that takes an `Executor` instead. + * Remove deprecated `Cue` constructors, use `Cue.Builder` instead. + * Remove deprecated `OfflineLicenseHelper` constructor, use + `OfflineLicenseHelper(DefaultDrmSessionManager, + DrmSessionEventListener.EventDispatcher)` instead. + * Remove four deprecated `AnalyticsListener` methods: + * `onDecoderEnabled`, use `onAudioEnabled` and/or `onVideoEnabled` + instead. + * `onDecoderInitialized`, use `onAudioDecoderInitialized` and/or + `onVideoDecoderInitialized` instead. + * `onDecoderInputFormatChanged`, use `onAudioInputFormatChanged` + and/or `onVideoInputFormatChanged` instead. + * `onDecoderDisabled`, use `onAudioDisabled` and/or `onVideoDisabled` + instead. + * Remove the deprecated `Player.Listener.onSeekProcessed` and + `AnalyticsListener.onSeekProcessed`, use `onPositionDiscontinuity` with + `DISCONTINUITY_REASON_SEEK` instead. + * Remove `ExoPlayer.setHandleWakeLock(boolean)`, use `setWakeMode(int)` + instead. + * Remove deprecated + `DefaultLoadControl.Builder.createDefaultLoadControl()`, use `build()` + instead. + * Remove deprecated `MediaItem.PlaybackProperties`, use + `MediaItem.LocalConfiguration` instead. Deprecated field + `MediaItem.playbackProperties` is now of type + `MediaItem.LocalConfiguration`. + +### 1.1.0-rc01 (2023-06-21) + +Use the 1.1.0 [stable version](#110-2023-07-05). + +### 1.1.0-beta01 (2023-06-07) + +Use the 1.1.0 [stable version](#110-2023-07-05). + +### 1.1.0-alpha01 (2023-05-10) + +Use the 1.1.0 [stable version](#110-2023-07-05). + +## 1.0 + ### 1.0.2 (2023-05-18) This release corresponds to the diff --git a/api.txt b/api.txt index c2f1a94d1a..198848a746 100644 --- a/api.txt +++ b/api.txt @@ -127,6 +127,11 @@ package androidx.media3.common { field public static final int USAGE_VOICE_COMMUNICATION = 2; // 0x2 field public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3; // 0x3 field public static final java.util.UUID UUID_NIL; + field public static final int VOLUME_FLAG_ALLOW_RINGER_MODES = 2; // 0x2 + field public static final int VOLUME_FLAG_PLAY_SOUND = 4; // 0x4 + field public static final int VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8 + field public static final int VOLUME_FLAG_SHOW_UI = 1; // 0x1 + field public static final int VOLUME_FLAG_VIBRATE = 16; // 0x10 field public static final int WAKE_MODE_LOCAL = 1; // 0x1 field public static final int WAKE_MODE_NETWORK = 2; // 0x2 field public static final int WAKE_MODE_NONE = 0; // 0x0 @@ -163,6 +168,9 @@ package androidx.media3.common { @IntDef(open=true, value={androidx.media3.common.C.TRACK_TYPE_UNKNOWN, androidx.media3.common.C.TRACK_TYPE_DEFAULT, androidx.media3.common.C.TRACK_TYPE_AUDIO, androidx.media3.common.C.TRACK_TYPE_VIDEO, androidx.media3.common.C.TRACK_TYPE_TEXT, androidx.media3.common.C.TRACK_TYPE_IMAGE, androidx.media3.common.C.TRACK_TYPE_METADATA, androidx.media3.common.C.TRACK_TYPE_CAMERA_MOTION, androidx.media3.common.C.TRACK_TYPE_NONE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface C.TrackType { } + @IntDef(flag=true, value={androidx.media3.common.C.VOLUME_FLAG_SHOW_UI, androidx.media3.common.C.VOLUME_FLAG_ALLOW_RINGER_MODES, androidx.media3.common.C.VOLUME_FLAG_PLAY_SOUND, androidx.media3.common.C.VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE, androidx.media3.common.C.VOLUME_FLAG_VIBRATE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.VolumeFlags { + } + @IntDef({androidx.media3.common.C.WAKE_MODE_NONE, androidx.media3.common.C.WAKE_MODE_LOCAL, androidx.media3.common.C.WAKE_MODE_NETWORK}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.WakeMode { } @@ -170,9 +178,18 @@ package androidx.media3.common { field public static final int PLAYBACK_TYPE_LOCAL = 0; // 0x0 field public static final int PLAYBACK_TYPE_REMOTE = 1; // 0x1 field public static final androidx.media3.common.DeviceInfo UNKNOWN; - field public final int maxVolume; - field public final int minVolume; + field @IntRange(from=0) public final int maxVolume; + field @IntRange(from=0) public final int minVolume; field @androidx.media3.common.DeviceInfo.PlaybackType public final int playbackType; + field @Nullable public final String routingControllerId; + } + + public static final class DeviceInfo.Builder { + ctor public DeviceInfo.Builder(@androidx.media3.common.DeviceInfo.PlaybackType int); + method public androidx.media3.common.DeviceInfo build(); + method public androidx.media3.common.DeviceInfo.Builder setMaxVolume(@IntRange(from=0) int); + method public androidx.media3.common.DeviceInfo.Builder setMinVolume(@IntRange(from=0) int); + method public androidx.media3.common.DeviceInfo.Builder setRoutingControllerId(@Nullable String); } @IntDef({androidx.media3.common.DeviceInfo.PLAYBACK_TYPE_LOCAL, androidx.media3.common.DeviceInfo.PLAYBACK_TYPE_REMOTE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface DeviceInfo.PlaybackType { @@ -318,7 +335,7 @@ package androidx.media3.common { method public androidx.media3.common.MediaItem.LiveConfiguration.Builder setTargetOffsetMs(long); } - public static class MediaItem.LocalConfiguration { + public static final class MediaItem.LocalConfiguration { field @Nullable public final androidx.media3.common.MediaItem.AdsConfiguration adsConfiguration; field @Nullable public final androidx.media3.common.MediaItem.DrmConfiguration drmConfiguration; field @Nullable public final String mimeType; @@ -369,14 +386,50 @@ package androidx.media3.common { public final class MediaMetadata { method public androidx.media3.common.MediaMetadata.Builder buildUpon(); field public static final androidx.media3.common.MediaMetadata EMPTY; - field public static final int FOLDER_TYPE_ALBUMS = 2; // 0x2 - field public static final int FOLDER_TYPE_ARTISTS = 3; // 0x3 - field public static final int FOLDER_TYPE_GENRES = 4; // 0x4 - field public static final int FOLDER_TYPE_MIXED = 0; // 0x0 - field public static final int FOLDER_TYPE_NONE = -1; // 0xffffffff - field public static final int FOLDER_TYPE_PLAYLISTS = 5; // 0x5 - field public static final int FOLDER_TYPE_TITLES = 1; // 0x1 - field public static final int FOLDER_TYPE_YEARS = 6; // 0x6 + field @Deprecated public static final int FOLDER_TYPE_ALBUMS = 2; // 0x2 + field @Deprecated public static final int FOLDER_TYPE_ARTISTS = 3; // 0x3 + field @Deprecated public static final int FOLDER_TYPE_GENRES = 4; // 0x4 + field @Deprecated public static final int FOLDER_TYPE_MIXED = 0; // 0x0 + field @Deprecated public static final int FOLDER_TYPE_NONE = -1; // 0xffffffff + field @Deprecated public static final int FOLDER_TYPE_PLAYLISTS = 5; // 0x5 + field @Deprecated public static final int FOLDER_TYPE_TITLES = 1; // 0x1 + field @Deprecated public static final int FOLDER_TYPE_YEARS = 6; // 0x6 + field public static final int MEDIA_TYPE_ALBUM = 10; // 0xa + field public static final int MEDIA_TYPE_ARTIST = 11; // 0xb + field public static final int MEDIA_TYPE_AUDIO_BOOK = 15; // 0xf + field public static final int MEDIA_TYPE_AUDIO_BOOK_CHAPTER = 2; // 0x2 + field public static final int MEDIA_TYPE_FOLDER_ALBUMS = 21; // 0x15 + field public static final int MEDIA_TYPE_FOLDER_ARTISTS = 22; // 0x16 + field public static final int MEDIA_TYPE_FOLDER_AUDIO_BOOKS = 26; // 0x1a + field public static final int MEDIA_TYPE_FOLDER_GENRES = 23; // 0x17 + field public static final int MEDIA_TYPE_FOLDER_MIXED = 20; // 0x14 + field public static final int MEDIA_TYPE_FOLDER_MOVIES = 35; // 0x23 + field public static final int MEDIA_TYPE_FOLDER_NEWS = 32; // 0x20 + field public static final int MEDIA_TYPE_FOLDER_PLAYLISTS = 24; // 0x18 + field public static final int MEDIA_TYPE_FOLDER_PODCASTS = 27; // 0x1b + field public static final int MEDIA_TYPE_FOLDER_RADIO_STATIONS = 31; // 0x1f + field public static final int MEDIA_TYPE_FOLDER_TRAILERS = 34; // 0x22 + field public static final int MEDIA_TYPE_FOLDER_TV_CHANNELS = 28; // 0x1c + field public static final int MEDIA_TYPE_FOLDER_TV_SERIES = 29; // 0x1d + field public static final int MEDIA_TYPE_FOLDER_TV_SHOWS = 30; // 0x1e + field public static final int MEDIA_TYPE_FOLDER_VIDEOS = 33; // 0x21 + field public static final int MEDIA_TYPE_FOLDER_YEARS = 25; // 0x19 + field public static final int MEDIA_TYPE_GENRE = 12; // 0xc + field public static final int MEDIA_TYPE_MIXED = 0; // 0x0 + field public static final int MEDIA_TYPE_MOVIE = 8; // 0x8 + field public static final int MEDIA_TYPE_MUSIC = 1; // 0x1 + field public static final int MEDIA_TYPE_NEWS = 5; // 0x5 + field public static final int MEDIA_TYPE_PLAYLIST = 13; // 0xd + field public static final int MEDIA_TYPE_PODCAST = 16; // 0x10 + field public static final int MEDIA_TYPE_PODCAST_EPISODE = 3; // 0x3 + field public static final int MEDIA_TYPE_RADIO_STATION = 4; // 0x4 + field public static final int MEDIA_TYPE_TRAILER = 7; // 0x7 + field public static final int MEDIA_TYPE_TV_CHANNEL = 17; // 0x11 + field public static final int MEDIA_TYPE_TV_SEASON = 19; // 0x13 + field public static final int MEDIA_TYPE_TV_SERIES = 18; // 0x12 + field public static final int MEDIA_TYPE_TV_SHOW = 9; // 0x9 + field public static final int MEDIA_TYPE_VIDEO = 6; // 0x6 + field public static final int MEDIA_TYPE_YEAR = 14; // 0xe field public static final int PICTURE_TYPE_ARTIST_PERFORMER = 8; // 0x8 field public static final int PICTURE_TYPE_A_BRIGHT_COLORED_FISH = 17; // 0x11 field public static final int PICTURE_TYPE_BACK_COVER = 4; // 0x4 @@ -411,9 +464,11 @@ package androidx.media3.common { field @Nullable public final Integer discNumber; field @Nullable public final CharSequence displayTitle; field @Nullable public final android.os.Bundle extras; - field @Nullable @androidx.media3.common.MediaMetadata.FolderType public final Integer folderType; + field @Deprecated @Nullable @androidx.media3.common.MediaMetadata.FolderType public final Integer folderType; field @Nullable public final CharSequence genre; + field @Nullable public final Boolean isBrowsable; field @Nullable public final Boolean isPlayable; + field @Nullable @androidx.media3.common.MediaMetadata.MediaType public final Integer mediaType; field @Nullable public final androidx.media3.common.Rating overallRating; field @Nullable public final Integer recordingDay; field @Nullable public final Integer recordingMonth; @@ -447,9 +502,11 @@ package androidx.media3.common { method public androidx.media3.common.MediaMetadata.Builder setDiscNumber(@Nullable Integer); method public androidx.media3.common.MediaMetadata.Builder setDisplayTitle(@Nullable CharSequence); method public androidx.media3.common.MediaMetadata.Builder setExtras(@Nullable android.os.Bundle); - method public androidx.media3.common.MediaMetadata.Builder setFolderType(@Nullable @androidx.media3.common.MediaMetadata.FolderType Integer); + method @Deprecated public androidx.media3.common.MediaMetadata.Builder setFolderType(@Nullable @androidx.media3.common.MediaMetadata.FolderType Integer); method public androidx.media3.common.MediaMetadata.Builder setGenre(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setIsBrowsable(@Nullable Boolean); method public androidx.media3.common.MediaMetadata.Builder setIsPlayable(@Nullable Boolean); + method public androidx.media3.common.MediaMetadata.Builder setMediaType(@Nullable @androidx.media3.common.MediaMetadata.MediaType Integer); method public androidx.media3.common.MediaMetadata.Builder setOverallRating(@Nullable androidx.media3.common.Rating); method public androidx.media3.common.MediaMetadata.Builder setRecordingDay(@IntRange(from=1, to=31) @Nullable Integer); method public androidx.media3.common.MediaMetadata.Builder setRecordingMonth(@IntRange(from=1, to=12) @Nullable Integer); @@ -467,7 +524,10 @@ package androidx.media3.common { method public androidx.media3.common.MediaMetadata.Builder setWriter(@Nullable CharSequence); } - @IntDef({androidx.media3.common.MediaMetadata.FOLDER_TYPE_NONE, androidx.media3.common.MediaMetadata.FOLDER_TYPE_MIXED, androidx.media3.common.MediaMetadata.FOLDER_TYPE_TITLES, androidx.media3.common.MediaMetadata.FOLDER_TYPE_ALBUMS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_ARTISTS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_GENRES, androidx.media3.common.MediaMetadata.FOLDER_TYPE_PLAYLISTS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_YEARS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface MediaMetadata.FolderType { + @Deprecated @IntDef({androidx.media3.common.MediaMetadata.FOLDER_TYPE_NONE, androidx.media3.common.MediaMetadata.FOLDER_TYPE_MIXED, androidx.media3.common.MediaMetadata.FOLDER_TYPE_TITLES, androidx.media3.common.MediaMetadata.FOLDER_TYPE_ALBUMS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_ARTISTS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_GENRES, androidx.media3.common.MediaMetadata.FOLDER_TYPE_PLAYLISTS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_YEARS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface MediaMetadata.FolderType { + } + + @IntDef({androidx.media3.common.MediaMetadata.MEDIA_TYPE_MIXED, androidx.media3.common.MediaMetadata.MEDIA_TYPE_MUSIC, androidx.media3.common.MediaMetadata.MEDIA_TYPE_AUDIO_BOOK_CHAPTER, androidx.media3.common.MediaMetadata.MEDIA_TYPE_PODCAST_EPISODE, androidx.media3.common.MediaMetadata.MEDIA_TYPE_RADIO_STATION, androidx.media3.common.MediaMetadata.MEDIA_TYPE_NEWS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_VIDEO, androidx.media3.common.MediaMetadata.MEDIA_TYPE_TRAILER, androidx.media3.common.MediaMetadata.MEDIA_TYPE_MOVIE, androidx.media3.common.MediaMetadata.MEDIA_TYPE_TV_SHOW, androidx.media3.common.MediaMetadata.MEDIA_TYPE_ALBUM, androidx.media3.common.MediaMetadata.MEDIA_TYPE_ARTIST, androidx.media3.common.MediaMetadata.MEDIA_TYPE_GENRE, androidx.media3.common.MediaMetadata.MEDIA_TYPE_PLAYLIST, androidx.media3.common.MediaMetadata.MEDIA_TYPE_YEAR, androidx.media3.common.MediaMetadata.MEDIA_TYPE_AUDIO_BOOK, androidx.media3.common.MediaMetadata.MEDIA_TYPE_PODCAST, androidx.media3.common.MediaMetadata.MEDIA_TYPE_TV_CHANNEL, androidx.media3.common.MediaMetadata.MEDIA_TYPE_TV_SERIES, androidx.media3.common.MediaMetadata.MEDIA_TYPE_TV_SEASON, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_MIXED, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_ARTISTS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_GENRES, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_PLAYLISTS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_YEARS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_AUDIO_BOOKS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_PODCASTS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_TV_CHANNELS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_TV_SERIES, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_TV_SHOWS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_RADIO_STATIONS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_NEWS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_VIDEOS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_TRAILERS, androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_MOVIES}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface MediaMetadata.MediaType { } @IntDef({androidx.media3.common.MediaMetadata.PICTURE_TYPE_OTHER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_FILE_ICON, androidx.media3.common.MediaMetadata.PICTURE_TYPE_FILE_ICON_OTHER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_FRONT_COVER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_BACK_COVER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_LEAFLET_PAGE, androidx.media3.common.MediaMetadata.PICTURE_TYPE_MEDIA, androidx.media3.common.MediaMetadata.PICTURE_TYPE_LEAD_ARTIST_PERFORMER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_ARTIST_PERFORMER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_CONDUCTOR, androidx.media3.common.MediaMetadata.PICTURE_TYPE_BAND_ORCHESTRA, androidx.media3.common.MediaMetadata.PICTURE_TYPE_COMPOSER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_LYRICIST, androidx.media3.common.MediaMetadata.PICTURE_TYPE_RECORDING_LOCATION, androidx.media3.common.MediaMetadata.PICTURE_TYPE_DURING_RECORDING, androidx.media3.common.MediaMetadata.PICTURE_TYPE_DURING_PERFORMANCE, androidx.media3.common.MediaMetadata.PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE, androidx.media3.common.MediaMetadata.PICTURE_TYPE_A_BRIGHT_COLORED_FISH, androidx.media3.common.MediaMetadata.PICTURE_TYPE_ILLUSTRATION, androidx.media3.common.MediaMetadata.PICTURE_TYPE_BAND_ARTIST_LOGO, androidx.media3.common.MediaMetadata.PICTURE_TYPE_PUBLISHER_STUDIO_LOGO}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface MediaMetadata.PictureType { @@ -486,7 +546,7 @@ package androidx.media3.common { field public static final String APPLICATION_MP4VTT = "application/x-mp4-vtt"; field public static final String APPLICATION_MPD = "application/dash+xml"; field public static final String APPLICATION_PGS = "application/pgs"; - field public static final String APPLICATION_RAWCC = "application/x-rawcc"; + field @Deprecated public static final String APPLICATION_RAWCC = "application/x-rawcc"; field public static final String APPLICATION_RTSP = "application/x-rtsp"; field public static final String APPLICATION_SS = "application/vnd.ms-sstr+xml"; field public static final String APPLICATION_SUBRIP = "application/x-subrip"; @@ -524,7 +584,11 @@ package androidx.media3.common { field public static final String AUDIO_VORBIS = "audio/vorbis"; field public static final String AUDIO_WAV = "audio/wav"; field public static final String AUDIO_WEBM = "audio/webm"; + field public static final String IMAGE_HEIC = "image/heic"; + field public static final String IMAGE_HEIF = "image/heif"; field public static final String IMAGE_JPEG = "image/jpeg"; + field public static final String IMAGE_PNG = "image/png"; + field public static final String IMAGE_WEBP = "image/webp"; field public static final String TEXT_SSA = "text/x-ssa"; field public static final String TEXT_VTT = "text/vtt"; field public static final String VIDEO_AV1 = "video/av01"; @@ -602,7 +666,7 @@ package androidx.media3.common { } public final class PlaybackParameters { - ctor public PlaybackParameters(float); + ctor public PlaybackParameters(@FloatRange(from=0, fromInclusive=false) float); ctor public PlaybackParameters(@FloatRange(from=0, fromInclusive=false) float, @FloatRange(from=0, fromInclusive=false) float); method @CheckResult public androidx.media3.common.PlaybackParameters withSpeed(@FloatRange(from=0, fromInclusive=false) float); field public static final androidx.media3.common.PlaybackParameters DEFAULT; @@ -623,7 +687,8 @@ package androidx.media3.common { method public void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); method public void clearVideoSurfaceView(@Nullable android.view.SurfaceView); method public void clearVideoTextureView(@Nullable android.view.TextureView); - method public void decreaseDeviceVolume(); + method @Deprecated public void decreaseDeviceVolume(); + method public void decreaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int); method public android.os.Looper getApplicationLooper(); method public androidx.media3.common.AudioAttributes getAudioAttributes(); method public androidx.media3.common.Player.Commands getAvailableCommands(); @@ -667,7 +732,8 @@ package androidx.media3.common { method @FloatRange(from=0, to=1.0) public float getVolume(); method public boolean hasNextMediaItem(); method public boolean hasPreviousMediaItem(); - method public void increaseDeviceVolume(); + method @Deprecated public void increaseDeviceVolume(); + method public void increaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int); method public boolean isCommandAvailable(@androidx.media3.common.Player.Command int); method public boolean isCurrentMediaItemDynamic(); method public boolean isCurrentMediaItemLive(); @@ -685,6 +751,8 @@ package androidx.media3.common { method public void removeListener(androidx.media3.common.Player.Listener); method public void removeMediaItem(int); method public void removeMediaItems(int, int); + method public void replaceMediaItem(int, androidx.media3.common.MediaItem); + method public void replaceMediaItems(int, int, java.util.List); method public void seekBack(); method public void seekForward(); method public void seekTo(long); @@ -695,8 +763,10 @@ package androidx.media3.common { method public void seekToNextMediaItem(); method public void seekToPrevious(); method public void seekToPreviousMediaItem(); - method public void setDeviceMuted(boolean); - method public void setDeviceVolume(@IntRange(from=0) int); + method @Deprecated public void setDeviceMuted(boolean); + method public void setDeviceMuted(boolean, @androidx.media3.common.C.VolumeFlags int); + method @Deprecated public void setDeviceVolume(@IntRange(from=0) int); + method public void setDeviceVolume(@IntRange(from=0) int, int); method public void setMediaItem(androidx.media3.common.MediaItem); method public void setMediaItem(androidx.media3.common.MediaItem, long); method public void setMediaItem(androidx.media3.common.MediaItem, boolean); @@ -716,12 +786,14 @@ package androidx.media3.common { method public void setVideoTextureView(@Nullable android.view.TextureView); method public void setVolume(@FloatRange(from=0, to=1.0) float); method public void stop(); - field public static final int COMMAND_ADJUST_DEVICE_VOLUME = 26; // 0x1a + field @Deprecated public static final int COMMAND_ADJUST_DEVICE_VOLUME = 26; // 0x1a + field public static final int COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS = 34; // 0x22 field public static final int COMMAND_CHANGE_MEDIA_ITEMS = 20; // 0x14 field public static final int COMMAND_GET_AUDIO_ATTRIBUTES = 21; // 0x15 field public static final int COMMAND_GET_CURRENT_MEDIA_ITEM = 16; // 0x10 field public static final int COMMAND_GET_DEVICE_VOLUME = 23; // 0x17 - field public static final int COMMAND_GET_MEDIA_ITEMS_METADATA = 18; // 0x12 + field @Deprecated public static final int COMMAND_GET_MEDIA_ITEMS_METADATA = 18; // 0x12 + field public static final int COMMAND_GET_METADATA = 18; // 0x12 field public static final int COMMAND_GET_TEXT = 28; // 0x1c field public static final int COMMAND_GET_TIMELINE = 17; // 0x11 field public static final int COMMAND_GET_TRACKS = 30; // 0x1e @@ -729,6 +801,7 @@ package androidx.media3.common { field public static final int COMMAND_INVALID = -1; // 0xffffffff field public static final int COMMAND_PLAY_PAUSE = 1; // 0x1 field public static final int COMMAND_PREPARE = 2; // 0x2 + field public static final int COMMAND_RELEASE = 32; // 0x20 field public static final int COMMAND_SEEK_BACK = 11; // 0xb field public static final int COMMAND_SEEK_FORWARD = 12; // 0xc field public static final int COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM = 5; // 0x5 @@ -738,9 +811,11 @@ package androidx.media3.common { field public static final int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 8; // 0x8 field public static final int COMMAND_SEEK_TO_PREVIOUS = 7; // 0x7 field public static final int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 6; // 0x6 - field public static final int COMMAND_SET_DEVICE_VOLUME = 25; // 0x19 + field @Deprecated public static final int COMMAND_SET_DEVICE_VOLUME = 25; // 0x19 + field public static final int COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS = 33; // 0x21 field public static final int COMMAND_SET_MEDIA_ITEM = 31; // 0x1f - field public static final int COMMAND_SET_MEDIA_ITEMS_METADATA = 19; // 0x13 + field @Deprecated public static final int COMMAND_SET_MEDIA_ITEMS_METADATA = 19; // 0x13 + field public static final int COMMAND_SET_PLAYLIST_METADATA = 19; // 0x13 field public static final int COMMAND_SET_REPEAT_MODE = 15; // 0xf field public static final int COMMAND_SET_SHUFFLE_MODE = 14; // 0xe field public static final int COMMAND_SET_SPEED_AND_PITCH = 13; // 0xd @@ -791,10 +866,12 @@ package androidx.media3.common { field public static final int MEDIA_ITEM_TRANSITION_REASON_SEEK = 2; // 0x2 field public static final int PLAYBACK_SUPPRESSION_REASON_NONE = 0; // 0x0 field public static final int PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS = 1; // 0x1 + field public static final int PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE = 2; // 0x2 field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY = 3; // 0x3 field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS = 2; // 0x2 field public static final int PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM = 5; // 0x5 field public static final int PLAY_WHEN_READY_CHANGE_REASON_REMOTE = 4; // 0x4 + field public static final int PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG = 6; // 0x6 field public static final int PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST = 1; // 0x1 field public static final int REPEAT_MODE_ALL = 2; // 0x2 field public static final int REPEAT_MODE_OFF = 0; // 0x0 @@ -807,7 +884,7 @@ package androidx.media3.common { field public static final int TIMELINE_CHANGE_REASON_SOURCE_UPDATE = 1; // 0x1 } - @IntDef({androidx.media3.common.Player.COMMAND_INVALID, androidx.media3.common.Player.COMMAND_PLAY_PAUSE, androidx.media3.common.Player.COMMAND_PREPARE, androidx.media3.common.Player.COMMAND_STOP, androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION, androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT, androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_BACK, androidx.media3.common.Player.COMMAND_SEEK_FORWARD, androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH, androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE, androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE, androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_GET_TIMELINE, androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS, androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES, androidx.media3.common.Player.COMMAND_GET_VOLUME, androidx.media3.common.Player.COMMAND_GET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VIDEO_SURFACE, androidx.media3.common.Player.COMMAND_GET_TEXT, androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS, androidx.media3.common.Player.COMMAND_GET_TRACKS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.Command { + @IntDef({androidx.media3.common.Player.COMMAND_INVALID, androidx.media3.common.Player.COMMAND_PLAY_PAUSE, androidx.media3.common.Player.COMMAND_PREPARE, androidx.media3.common.Player.COMMAND_STOP, androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION, androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT, androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_BACK, androidx.media3.common.Player.COMMAND_SEEK_FORWARD, androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH, androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE, androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE, androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_GET_TIMELINE, androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_GET_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_SET_PLAYLIST_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS, androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES, androidx.media3.common.Player.COMMAND_GET_VOLUME, androidx.media3.common.Player.COMMAND_GET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS, androidx.media3.common.Player.COMMAND_SET_VIDEO_SURFACE, androidx.media3.common.Player.COMMAND_GET_TEXT, androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS, androidx.media3.common.Player.COMMAND_GET_TRACKS, androidx.media3.common.Player.COMMAND_RELEASE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.Command { } public static final class Player.Commands { @@ -868,10 +945,10 @@ package androidx.media3.common { @IntDef({androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_SEEK, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.MediaItemTransitionReason { } - @IntDef({androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_REMOTE, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlayWhenReadyChangeReason { + @IntDef({androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_REMOTE, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlayWhenReadyChangeReason { } - @IntDef({androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlaybackSuppressionReason { + @IntDef({androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlaybackSuppressionReason { } public static final class Player.PositionInfo { @@ -1162,11 +1239,15 @@ package androidx.media3.common.util { method public static boolean checkCleartextTrafficPermitted(androidx.media3.common.MediaItem...); method @Nullable public static String getAdaptiveMimeTypeForContentType(@androidx.media3.common.C.ContentType int); method @Nullable public static java.util.UUID getDrmUuid(String); + method public static boolean handlePauseButtonAction(@Nullable androidx.media3.common.Player); + method public static boolean handlePlayButtonAction(@Nullable androidx.media3.common.Player); + method public static boolean handlePlayPauseButtonAction(@Nullable androidx.media3.common.Player); method @androidx.media3.common.C.ContentType public static int inferContentType(android.net.Uri); method @androidx.media3.common.C.ContentType public static int inferContentTypeForExtension(String); method @androidx.media3.common.C.ContentType public static int inferContentTypeForUriAndMimeType(android.net.Uri, @Nullable String); method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, android.net.Uri...); method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, androidx.media3.common.MediaItem...); + method @org.checkerframework.checker.nullness.qual.EnsuresNonNullIf(result=false, expression="#1") public static boolean shouldShowPlayButton(@Nullable androidx.media3.common.Player); } } @@ -1438,122 +1519,128 @@ package androidx.media3.session { field public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV = "android.media.playback.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_PREVIOUS"; } - public class MediaController implements androidx.media3.common.Player { - method public void addListener(androidx.media3.common.Player.Listener); - method public void addMediaItem(androidx.media3.common.MediaItem); - method public void addMediaItem(int, androidx.media3.common.MediaItem); - method public void addMediaItems(java.util.List); - method public void addMediaItems(int, java.util.List); - method public boolean canAdvertiseSession(); - method public void clearMediaItems(); - method public void clearVideoSurface(); - method public void clearVideoSurface(@Nullable android.view.Surface); - method public void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); - method public void clearVideoSurfaceView(@Nullable android.view.SurfaceView); - method public void clearVideoTextureView(@Nullable android.view.TextureView); - method public void decreaseDeviceVolume(); - method public android.os.Looper getApplicationLooper(); - method public androidx.media3.common.AudioAttributes getAudioAttributes(); - method public androidx.media3.common.Player.Commands getAvailableCommands(); - method public androidx.media3.session.SessionCommands getAvailableSessionCommands(); - method @IntRange(from=0, to=100) public int getBufferedPercentage(); - method public long getBufferedPosition(); - method @Nullable public androidx.media3.session.SessionToken getConnectedToken(); - method public long getContentBufferedPosition(); - method public long getContentDuration(); - method public long getContentPosition(); - method public int getCurrentAdGroupIndex(); - method public int getCurrentAdIndexInAdGroup(); - method public androidx.media3.common.text.CueGroup getCurrentCues(); - method public long getCurrentLiveOffset(); - method @Nullable public androidx.media3.common.MediaItem getCurrentMediaItem(); - method public int getCurrentMediaItemIndex(); - method public int getCurrentPeriodIndex(); - method public long getCurrentPosition(); - method public androidx.media3.common.Timeline getCurrentTimeline(); - method public androidx.media3.common.Tracks getCurrentTracks(); - method public androidx.media3.common.DeviceInfo getDeviceInfo(); - method @IntRange(from=0) public int getDeviceVolume(); - method public long getDuration(); - method public long getMaxSeekToPreviousPosition(); - method public androidx.media3.common.MediaItem getMediaItemAt(int); - method public int getMediaItemCount(); - method public androidx.media3.common.MediaMetadata getMediaMetadata(); - method public int getNextMediaItemIndex(); - method public boolean getPlayWhenReady(); - method public androidx.media3.common.PlaybackParameters getPlaybackParameters(); - method @androidx.media3.common.Player.State public int getPlaybackState(); - method @androidx.media3.common.Player.PlaybackSuppressionReason public int getPlaybackSuppressionReason(); - method @Nullable public androidx.media3.common.PlaybackException getPlayerError(); - method public androidx.media3.common.MediaMetadata getPlaylistMetadata(); - method public int getPreviousMediaItemIndex(); - method @androidx.media3.common.Player.RepeatMode public int getRepeatMode(); - method public long getSeekBackIncrement(); - method public long getSeekForwardIncrement(); - method @Nullable public android.app.PendingIntent getSessionActivity(); - method public boolean getShuffleModeEnabled(); - method public long getTotalBufferedDuration(); - method public androidx.media3.common.TrackSelectionParameters getTrackSelectionParameters(); - method public androidx.media3.common.VideoSize getVideoSize(); - method @FloatRange(from=0, to=1) public float getVolume(); - method public boolean hasNextMediaItem(); - method public boolean hasPreviousMediaItem(); - method public void increaseDeviceVolume(); - method public boolean isCommandAvailable(@androidx.media3.common.Player.Command int); - method public boolean isConnected(); - method public boolean isCurrentMediaItemDynamic(); - method public boolean isCurrentMediaItemLive(); - method public boolean isCurrentMediaItemSeekable(); - method public boolean isDeviceMuted(); - method public boolean isLoading(); - method public boolean isPlaying(); - method public boolean isPlayingAd(); - method public boolean isSessionCommandAvailable(@androidx.media3.session.SessionCommand.CommandCode int); - method public boolean isSessionCommandAvailable(androidx.media3.session.SessionCommand); - method public void moveMediaItem(int, int); - method public void moveMediaItems(int, int, int); - method public void pause(); - method public void play(); - method public void prepare(); - method public void release(); + @com.google.errorprone.annotations.DoNotMock public class MediaController implements androidx.media3.common.Player { + method public final void addListener(androidx.media3.common.Player.Listener); + method public final void addMediaItem(androidx.media3.common.MediaItem); + method public final void addMediaItem(int, androidx.media3.common.MediaItem); + method public final void addMediaItems(java.util.List); + method public final void addMediaItems(int, java.util.List); + method public final boolean canAdvertiseSession(); + method public final void clearMediaItems(); + method public final void clearVideoSurface(); + method public final void clearVideoSurface(@Nullable android.view.Surface); + method public final void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); + method public final void clearVideoSurfaceView(@Nullable android.view.SurfaceView); + method public final void clearVideoTextureView(@Nullable android.view.TextureView); + method @Deprecated public final void decreaseDeviceVolume(); + method public final void decreaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int); + method public final android.os.Looper getApplicationLooper(); + method public final androidx.media3.common.AudioAttributes getAudioAttributes(); + method public final androidx.media3.common.Player.Commands getAvailableCommands(); + method public final androidx.media3.session.SessionCommands getAvailableSessionCommands(); + method @IntRange(from=0, to=100) public final int getBufferedPercentage(); + method public final long getBufferedPosition(); + method @Nullable public final androidx.media3.session.SessionToken getConnectedToken(); + method public final long getContentBufferedPosition(); + method public final long getContentDuration(); + method public final long getContentPosition(); + method public final int getCurrentAdGroupIndex(); + method public final int getCurrentAdIndexInAdGroup(); + method public final androidx.media3.common.text.CueGroup getCurrentCues(); + method public final long getCurrentLiveOffset(); + method @Nullable public final androidx.media3.common.MediaItem getCurrentMediaItem(); + method public final int getCurrentMediaItemIndex(); + method public final int getCurrentPeriodIndex(); + method public final long getCurrentPosition(); + method public final androidx.media3.common.Timeline getCurrentTimeline(); + method public final androidx.media3.common.Tracks getCurrentTracks(); + method public final androidx.media3.common.DeviceInfo getDeviceInfo(); + method @IntRange(from=0) public final int getDeviceVolume(); + method public final long getDuration(); + method public final long getMaxSeekToPreviousPosition(); + method public final androidx.media3.common.MediaItem getMediaItemAt(int); + method public final int getMediaItemCount(); + method public final androidx.media3.common.MediaMetadata getMediaMetadata(); + method public final int getNextMediaItemIndex(); + method public final boolean getPlayWhenReady(); + method public final androidx.media3.common.PlaybackParameters getPlaybackParameters(); + method @androidx.media3.common.Player.State public final int getPlaybackState(); + method @androidx.media3.common.Player.PlaybackSuppressionReason public final int getPlaybackSuppressionReason(); + method @Nullable public final androidx.media3.common.PlaybackException getPlayerError(); + method public final androidx.media3.common.MediaMetadata getPlaylistMetadata(); + method public final int getPreviousMediaItemIndex(); + method @androidx.media3.common.Player.RepeatMode public final int getRepeatMode(); + method public final long getSeekBackIncrement(); + method public final long getSeekForwardIncrement(); + method @Nullable public final android.app.PendingIntent getSessionActivity(); + method public final boolean getShuffleModeEnabled(); + method public final long getTotalBufferedDuration(); + method public final androidx.media3.common.TrackSelectionParameters getTrackSelectionParameters(); + method public final androidx.media3.common.VideoSize getVideoSize(); + method @FloatRange(from=0, to=1) public final float getVolume(); + method public final boolean hasNextMediaItem(); + method public final boolean hasPreviousMediaItem(); + method @Deprecated public final void increaseDeviceVolume(); + method public final void increaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int); + method public final boolean isCommandAvailable(@androidx.media3.common.Player.Command int); + method public final boolean isConnected(); + method public final boolean isCurrentMediaItemDynamic(); + method public final boolean isCurrentMediaItemLive(); + method public final boolean isCurrentMediaItemSeekable(); + method public final boolean isDeviceMuted(); + method public final boolean isLoading(); + method public final boolean isPlaying(); + method public final boolean isPlayingAd(); + method public final boolean isSessionCommandAvailable(@androidx.media3.session.SessionCommand.CommandCode int); + method public final boolean isSessionCommandAvailable(androidx.media3.session.SessionCommand); + method public final void moveMediaItem(int, int); + method public final void moveMediaItems(int, int, int); + method public final void pause(); + method public final void play(); + method public final void prepare(); + method public final void release(); method public static void releaseFuture(java.util.concurrent.Future); - method public void removeListener(androidx.media3.common.Player.Listener); - method public void removeMediaItem(int); - method public void removeMediaItems(int, int); - method public void seekBack(); - method public void seekForward(); - method public void seekTo(long); - method public void seekTo(int, long); - method public void seekToDefaultPosition(); - method public void seekToDefaultPosition(int); - method public void seekToNext(); - method public void seekToNextMediaItem(); - method public void seekToPrevious(); - method public void seekToPreviousMediaItem(); - method public com.google.common.util.concurrent.ListenableFuture sendCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle); - method public void setDeviceMuted(boolean); - method public void setDeviceVolume(@IntRange(from=0) int); - method public void setMediaItem(androidx.media3.common.MediaItem); - method public void setMediaItem(androidx.media3.common.MediaItem, long); - method public void setMediaItem(androidx.media3.common.MediaItem, boolean); - method public void setMediaItems(java.util.List); - method public void setMediaItems(java.util.List, boolean); - method public void setMediaItems(java.util.List, int, long); - method public void setPlayWhenReady(boolean); - method public void setPlaybackParameters(androidx.media3.common.PlaybackParameters); - method public void setPlaybackSpeed(float); - method public void setPlaylistMetadata(androidx.media3.common.MediaMetadata); - method public com.google.common.util.concurrent.ListenableFuture setRating(String, androidx.media3.common.Rating); - method public com.google.common.util.concurrent.ListenableFuture setRating(androidx.media3.common.Rating); - method public void setRepeatMode(@androidx.media3.common.Player.RepeatMode int); - method public void setShuffleModeEnabled(boolean); - method public void setTrackSelectionParameters(androidx.media3.common.TrackSelectionParameters); - method public void setVideoSurface(@Nullable android.view.Surface); - method public void setVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); - method public void setVideoSurfaceView(@Nullable android.view.SurfaceView); - method public void setVideoTextureView(@Nullable android.view.TextureView); - method public void setVolume(@FloatRange(from=0, to=1) float); - method public void stop(); + method public final void removeListener(androidx.media3.common.Player.Listener); + method public final void removeMediaItem(int); + method public final void removeMediaItems(int, int); + method public final void replaceMediaItem(int, androidx.media3.common.MediaItem); + method public final void replaceMediaItems(int, int, java.util.List); + method public final void seekBack(); + method public final void seekForward(); + method public final void seekTo(long); + method public final void seekTo(int, long); + method public final void seekToDefaultPosition(); + method public final void seekToDefaultPosition(int); + method public final void seekToNext(); + method public final void seekToNextMediaItem(); + method public final void seekToPrevious(); + method public final void seekToPreviousMediaItem(); + method public final com.google.common.util.concurrent.ListenableFuture sendCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle); + method @Deprecated public final void setDeviceMuted(boolean); + method public final void setDeviceMuted(boolean, @androidx.media3.common.C.VolumeFlags int); + method @Deprecated public final void setDeviceVolume(@IntRange(from=0) int); + method public final void setDeviceVolume(@IntRange(from=0) int, @androidx.media3.common.C.VolumeFlags int); + method public final void setMediaItem(androidx.media3.common.MediaItem); + method public final void setMediaItem(androidx.media3.common.MediaItem, long); + method public final void setMediaItem(androidx.media3.common.MediaItem, boolean); + method public final void setMediaItems(java.util.List); + method public final void setMediaItems(java.util.List, boolean); + method public final void setMediaItems(java.util.List, int, long); + method public final void setPlayWhenReady(boolean); + method public final void setPlaybackParameters(androidx.media3.common.PlaybackParameters); + method public final void setPlaybackSpeed(float); + method public final void setPlaylistMetadata(androidx.media3.common.MediaMetadata); + method public final com.google.common.util.concurrent.ListenableFuture setRating(String, androidx.media3.common.Rating); + method public final com.google.common.util.concurrent.ListenableFuture setRating(androidx.media3.common.Rating); + method public final void setRepeatMode(@androidx.media3.common.Player.RepeatMode int); + method public final void setShuffleModeEnabled(boolean); + method public final void setTrackSelectionParameters(androidx.media3.common.TrackSelectionParameters); + method public final void setVideoSurface(@Nullable android.view.Surface); + method public final void setVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); + method public final void setVideoSurfaceView(@Nullable android.view.SurfaceView); + method public final void setVideoTextureView(@Nullable android.view.TextureView); + method public final void setVolume(@FloatRange(from=0, to=1) float); + method public final void stop(); } public static final class MediaController.Builder { @@ -1622,21 +1709,22 @@ package androidx.media3.session { field @IntRange(from=1) public final int notificationId; } - public class MediaSession { - method public void broadcastCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle); - method public java.util.List getConnectedControllers(); - method public String getId(); - method public androidx.media3.common.Player getPlayer(); - method @Nullable public android.app.PendingIntent getSessionActivity(); - method public androidx.media3.session.SessionToken getToken(); - method public void release(); - method public com.google.common.util.concurrent.ListenableFuture sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle); - method public void setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommands, androidx.media3.common.Player.Commands); - method public com.google.common.util.concurrent.ListenableFuture setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo, java.util.List); - method public void setCustomLayout(java.util.List); - method public void setPlayer(androidx.media3.common.Player); - method public void setSessionExtras(android.os.Bundle); - method public void setSessionExtras(androidx.media3.session.MediaSession.ControllerInfo, android.os.Bundle); + @com.google.errorprone.annotations.DoNotMock public class MediaSession { + method public final void broadcastCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle); + method public final java.util.List getConnectedControllers(); + method @Nullable public final androidx.media3.session.MediaSession.ControllerInfo getControllerForCurrentRequest(); + method public final String getId(); + method public final androidx.media3.common.Player getPlayer(); + method @Nullable public final android.app.PendingIntent getSessionActivity(); + method public final androidx.media3.session.SessionToken getToken(); + method public final void release(); + method public final com.google.common.util.concurrent.ListenableFuture sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle); + method public final void setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommands, androidx.media3.common.Player.Commands); + method public final com.google.common.util.concurrent.ListenableFuture setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo, java.util.List); + method public final void setCustomLayout(java.util.List); + method public final void setPlayer(androidx.media3.common.Player); + method public final void setSessionExtras(android.os.Bundle); + method public final void setSessionExtras(androidx.media3.session.MediaSession.ControllerInfo, android.os.Bundle); } public static final class MediaSession.Builder { @@ -1653,7 +1741,7 @@ package androidx.media3.session { method public default androidx.media3.session.MediaSession.ConnectionResult onConnect(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo); method public default com.google.common.util.concurrent.ListenableFuture onCustomCommand(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle); method public default void onDisconnected(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo); - method @androidx.media3.session.SessionResult.Code public default int onPlayerCommandRequest(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, @androidx.media3.common.Player.Command int); + method @Deprecated @androidx.media3.session.SessionResult.Code public default int onPlayerCommandRequest(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, @androidx.media3.common.Player.Command int); method public default void onPostConnect(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo); method public default com.google.common.util.concurrent.ListenableFuture onSetRating(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, String, androidx.media3.common.Rating); method public default com.google.common.util.concurrent.ListenableFuture onSetRating(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.common.Rating); @@ -1682,7 +1770,8 @@ package androidx.media3.session { method public final boolean isSessionAdded(androidx.media3.session.MediaSession); method @CallSuper @Nullable public android.os.IBinder onBind(@Nullable android.content.Intent); method @Nullable public abstract androidx.media3.session.MediaSession onGetSession(androidx.media3.session.MediaSession.ControllerInfo); - method public void onUpdateNotification(androidx.media3.session.MediaSession); + method @Deprecated public void onUpdateNotification(androidx.media3.session.MediaSession); + method public void onUpdateNotification(androidx.media3.session.MediaSession, boolean); method public final void removeSession(androidx.media3.session.MediaSession); field public static final String SERVICE_INTERFACE = "androidx.media3.session.MediaSessionService"; } diff --git a/build.gradle b/build.gradle index 0c15bce9e5..b6a5a5846f 100644 --- a/build.gradle +++ b/build.gradle @@ -17,9 +17,9 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.1' - classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.2' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21' + classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.4' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20' } } allprojects { diff --git a/common_library_config.gradle b/common_library_config.gradle index a831ddea0b..b2f7afab0d 100644 --- a/common_library_config.gradle +++ b/common_library_config.gradle @@ -25,9 +25,11 @@ android { aarMetadata { minCompileSdk = project.ext.compileSdkVersion } + multiDexEnabled true } compileOptions { + coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } @@ -39,3 +41,8 @@ android { unitTests.includeAndroidResources true } } + +dependencies { + implementation 'androidx.multidex:multidex:' + androidxMultidexVersion + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' +} diff --git a/constants.gradle b/constants.gradle index e159877c50..0665c6e805 100644 --- a/constants.gradle +++ b/constants.gradle @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. project.ext { - releaseVersion = '1.0.2' - releaseVersionCode = 1_000_002_3_00 + releaseVersion = '1.1.0' + releaseVersionCode = 1_001_000_3_00 minSdkVersion = 16 appTargetSdkVersion = 33 // API version before restricting local file access. @@ -27,35 +27,38 @@ project.ext { junitVersion = '4.13.2' // Use the same Guava version as the Android repo: // https://cs.android.com/android/platform/superproject/+/master:external/guava/METADATA - guavaVersion = '31.0.1-android' + guavaVersion = '31.1-android' mockitoVersion = '3.12.4' robolectricVersion = '4.8.1' // Keep this in sync with Google's internal Checker Framework version. checkerframeworkVersion = '3.13.0' checkerframeworkCompatVersion = '2.5.5' - errorProneVersion = '2.10.0' + errorProneVersion = '2.18.0' jsr305Version = '3.0.2' - kotlinAnnotationsVersion = '1.5.31' + kotlinAnnotationsVersion = '1.8.20' + // Updating this to 1.4.0+ will import Kotlin stdlib [internal ref: b/277891049]. androidxAnnotationVersion = '1.3.0' + // Updating this to 1.3.0+ will import Kotlin stdlib [internal ref: b/277891049]. androidxAnnotationExperimentalVersion = '1.2.0' - androidxAppCompatVersion = '1.3.1' - androidxCollectionVersion = '1.1.0' - androidxConstraintLayoutVersion = '2.0.4' - androidxCoreVersion = '1.7.0' + androidxAppCompatVersion = '1.6.1' + androidxCollectionVersion = '1.2.0' + androidxConstraintLayoutVersion = '2.1.4' + // Updating this to 1.9.0+ will import Kotlin stdlib [internal ref: b/277891049]. + androidxCoreVersion = '1.8.0' androidxFuturesVersion = '1.1.0' androidxMediaVersion = '1.6.0' - androidxMedia2Version = '1.2.0' + androidxMedia2Version = '1.2.1' androidxMultidexVersion = '2.0.1' - androidxRecyclerViewVersion = '1.2.1' - androidxMaterialVersion = '1.4.0' - androidxTestCoreVersion = '1.4.0' - androidxTestJUnitVersion = '1.1.3' - androidxTestRunnerVersion = '1.4.0' - androidxTestRulesVersion = '1.4.0' - androidxTestServicesStorageVersion = '1.4.0' - androidxTestTruthVersion = '1.4.0' + androidxRecyclerViewVersion = '1.3.0' + androidxMaterialVersion = '1.8.0' + androidxTestCoreVersion = '1.5.0' + androidxTestJUnitVersion = '1.1.5' + androidxTestRunnerVersion = '1.5.2' + androidxTestRulesVersion = '1.5.0' + androidxTestServicesStorageVersion = '1.4.2' + androidxTestTruthVersion = '1.5.0' truthVersion = '1.1.3' - okhttpVersion = '4.9.2' + okhttpVersion = '4.11.0' modulePrefix = ':' if (gradle.ext.has('androidxMediaModulePrefix')) { modulePrefix += gradle.ext.androidxMediaModulePrefix diff --git a/core_settings.gradle b/core_settings.gradle index 0ef4e443c4..15b52a5189 100644 --- a/core_settings.gradle +++ b/core_settings.gradle @@ -21,11 +21,12 @@ if (gradle.ext.has('androidxMediaModulePrefix')) { modulePrefix += gradle.ext.androidxMediaModulePrefix } -rootProject.name = gradle.ext.androidxMediaProjectName - include modulePrefix + 'lib-common' project(modulePrefix + 'lib-common').projectDir = new File(rootDir, 'libraries/common') +include modulePrefix + 'lib-container' +project(modulePrefix + 'lib-container').projectDir = new File(rootDir, 'libraries/container') + include modulePrefix + 'lib-session' project(modulePrefix + 'lib-session').projectDir = new File(rootDir, 'libraries/session') @@ -83,6 +84,9 @@ project(modulePrefix + 'lib-cast').projectDir = new File(rootDir, 'libraries/cas include modulePrefix + 'lib-effect' project(modulePrefix + 'lib-effect').projectDir = new File(rootDir, 'libraries/effect') +include modulePrefix + 'lib-muxer' +project(modulePrefix + 'lib-muxer').projectDir = new File(rootDir, 'libraries/muxer') + include modulePrefix + 'lib-transformer' project(modulePrefix + 'lib-transformer').projectDir = new File(rootDir, 'libraries/transformer') diff --git a/demos/cast/README.md b/demos/cast/README.md index b636d2c2e0..aae757dd62 100644 --- a/demos/cast/README.md +++ b/demos/cast/README.md @@ -1,7 +1,116 @@ # Cast demo -This app demonstrates integration with Google Cast, as well as switching between -Google Cast and local playback using ExoPlayer. +This app demonstrates switching between Google Cast and local playback by using +`CastPlayer` and `ExoPlayer`. + +## Building the demo app See the [demos README](../README.md) for instructions on how to build and run this demo. + +Test your streams by adding a `MediaItem` with URI and mime type to the +`DemoUtil` and deploy the app on a real device for casting. + +## Customization with `OptionsProvider` + +The Cast SDK behaviour in the demo app or your own app can be customized by +providing a custom `OptionsProvider` (see +[`DefaultCastOptionsProvider`](https://github.com/androidx/media/blob/release/libraries/cast/src/main/java/androidx/media3/cast/DefaultCastOptionsProvider.java) +also). + +Replace the default options provider in the `AndroidManifest.xml` with your own: + +```xml + +``` + +### Using a different Cast receiver app with the Media3 cast demo sender app + +The Media3 cast demo app is an implementation of an +[Android Cast *sender app*](https://developers.google.com/cast/docs/android_sender) +that uses a *default Cast receiver app* (running on the Cast device) that is +customized to support DRM protected streams +[by passing DRM configuration via `MediaInfo`](https://developers.google.com/cast/docs/android_sender/exoplayer). +Hence Widevine DRM credentials can also be populated with a +`MediaItem.DrmConfiguration.Builder` (see the samples in `DemoUtil` marked with +`Widevine`). + +If you test your own streams with this demo app, keep in mind that for your +production app you need to +[choose your own receiver app](https://developers.google.com/cast/docs/web_receiver#choose_a_web_receiver) +and have your own receiver app ID. + +If you have a receiver app already and want to quickly test whether it works +well together with the `CastPlayer`, then you can configure the demo app to use +your receiver: + +```java +public class MyOptionsProvider implements OptionsProvider { + @NonNull + @Override + public CastOptions getCastOptions(Context context) { + return new CastOptions.Builder() + .setReceiverApplicationId(YOUR_RECEIVER_APP_ID) + // other options + .build(); + } +} +``` + +You can also use the plain +[default Cast receiver app](https://developers.google.com/cast/docs/web_receiver#default_media_web_receiver) +by using `CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID`. + +#### Converting a Media3 `MediaItem` to a Cast `MediaQueueItem` + +This demo app uses the +[`DefaultMediaItemConverter`](https://github.com/androidx/media/blob/release/libraries/cast/src/main/java/androidx/media3/cast/DefaultMediaItemConverter.java) +to convert a Media3 `MediaItem` to a `MediaQueueItem` of the Cast API. Apps that +use a custom receiver app, can use a custom `MediaItemConverter` instance by +passing it into the constructor of `CastPlayer`. + +### Media session and notification + +This Media3 cast demo app uses the media session and notification support +provided by the Cast SDK. If your app already integrates with a `MediaSession`, +the Cast session can be disabled to avoid duplicate notifications or sessions: + +```java +public class MyOptionsProvider implements OptionsProvider { + @NonNull + @Override + public CastOptions getCastOptions(Context context) { + return new CastOptions.Builder() + .setCastMediaOptions( + new CastMediaOptions.Builder() + .setMediaSessionEnabled(false) + .setNotificationOptions(null) + .build()) + // other options + .build(); + } +} +``` + +## Supported media formats + +Whether a specific stream is supported on a Cast device largely depends on the +receiver app, the media player used by the receiver and the Cast device, rather +then the implementation of the sender that basically only provides media URI and +metadata. + +Generally, Google Cast and all Cast Web Receiver applications support the media +facilities and types listed on +[this page](https://developers.google.com/cast/docs/media). If you build a +custom receiver that uses a media player different to the media player of the +Cast receiver SDK, your app may support +[other formats or features](https://github.com/shaka-project/shaka-player) than +listed in the reference above. + +The Media3 team can't give support for building a receiver app or investigations +regarding support for certain media formats on a cast devices. Please consult +the Cast documentation around +[building a receiver application](https://developers.google.com/cast/docs/web_receiver) +for further details. diff --git a/demos/main/build.gradle b/demos/main/build.gradle index 2d7d92a0fb..45b67670e3 100644 --- a/demos/main/build.gradle +++ b/demos/main/build.gradle @@ -14,6 +14,7 @@ apply from: '../../constants.gradle' apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' android { compileSdkVersion project.ext.compileSdkVersion diff --git a/demos/main/src/main/AndroidManifest.xml b/demos/main/src/main/AndroidManifest.xml index 21d07e4ee5..10ce807160 100644 --- a/demos/main/src/main/AndroidManifest.xml +++ b/demos/main/src/main/AndroidManifest.xml @@ -52,6 +52,7 @@ + diff --git a/demos/main/src/main/assets/media.exolist.json b/demos/main/src/main/assets/media.exolist.json index ac7b5ce749..f37103c8fc 100644 --- a/demos/main/src/main/assets/media.exolist.json +++ b/demos/main/src/main/assets/media.exolist.json @@ -406,6 +406,18 @@ "name": "DASH VOD: Tears of Steel (11 periods, pre/mid/post), 2/5/2 ads [5/10s]", "uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1" }, + { + "name": "DASH live: Tears of Steel (mid), 3 ads each [10 s]", + "uri": "ssai://dai.google.com/?assetKey=jNVjPZwzSkyeGiaNQTPqiQ&format=0&adsId=1" + }, + { + "name": "DASH live: New Tears of Steel (mid), 3 ads each [10 s]", + "uri": "ssai://dai.google.com/?assetKey=PSzZMzAkSXCmlJOWDmRj8Q&format=0&adsId=12" + }, + { + "name": "DASH live: Unencrypted stream with 30s ad breaks every minute", + "uri": "ssai://dai.google.com/?assetKey=0ndl1dJcRmKDUPxTRjvdog&format=0&adsId=21" + }, { "name": "Playlist: No ads - HLS VOD: Demo (skippable pre/post) - No ads", "playlist": [ @@ -434,20 +446,6 @@ } ] }, - { - "name": "Playlist: No ads - HLS Live: Big Buck Bunny (mid) - No ads", - "playlist": [ - { - "uri": "https://html5demos.com/assets/dizzy.mp4" - }, - { - "uri": "ssai://dai.google.com/?assetKey=sN_IYUG8STe1ZzhIIE_ksA&format=2&adsId=3" - }, - { - "uri": "https://html5demos.com/assets/dizzy.mp4" - } - ] - }, { "name": "Playlist: No ads - DASH VOD: Tears of Steel (11 periods, pre/mid/post) - No ads", "playlist": [ @@ -494,7 +492,7 @@ ] }, { - "name": "Audio -> Video -> Audio", + "name": "Audio -> Video (MKV) -> Video (MKV) -> Audio -> Video (MKV) -> Video (DASH) -> Audio", "playlist": [ { "uri": "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/audio-141.mp4" @@ -502,6 +500,18 @@ { "uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv" }, + { + "uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv" + }, + { + "uri": "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/audio-141.mp4" + }, + { + "uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv" + }, + { + "uri": "https://storage.googleapis.com/wvmedia/clear/h264/tears/tears.mpd" + }, { "uri": "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/audio-141.mp4" } diff --git a/demos/main/src/main/java/androidx/media3/demo/main/IntentUtil.java b/demos/main/src/main/java/androidx/media3/demo/main/IntentUtil.java index f8023cbe63..95d25a94b6 100644 --- a/demos/main/src/main/java/androidx/media3/demo/main/IntentUtil.java +++ b/demos/main/src/main/java/androidx/media3/demo/main/IntentUtil.java @@ -94,7 +94,7 @@ public class IntentUtil { if (mediaItem.mediaMetadata.title != null) { intent.putExtra(TITLE_EXTRA, mediaItem.mediaMetadata.title); } - addPlaybackPropertiesToIntent(localConfiguration, intent, /* extrasKeySuffix= */ ""); + addLocalConfigurationToIntent(localConfiguration, intent, /* extrasKeySuffix= */ ""); addClippingConfigurationToIntent( mediaItem.clippingConfiguration, intent, /* extrasKeySuffix= */ ""); } else { @@ -104,7 +104,7 @@ public class IntentUtil { MediaItem.LocalConfiguration localConfiguration = checkNotNull(mediaItem.localConfiguration); intent.putExtra(URI_EXTRA + ("_" + i), localConfiguration.uri.toString()); - addPlaybackPropertiesToIntent(localConfiguration, intent, /* extrasKeySuffix= */ "_" + i); + addLocalConfigurationToIntent(localConfiguration, intent, /* extrasKeySuffix= */ "_" + i); addClippingConfigurationToIntent( mediaItem.clippingConfiguration, intent, /* extrasKeySuffix= */ "_" + i); if (mediaItem.mediaMetadata.title != null) { @@ -195,7 +195,7 @@ public class IntentUtil { return builder; } - private static void addPlaybackPropertiesToIntent( + private static void addLocalConfigurationToIntent( MediaItem.LocalConfiguration localConfiguration, Intent intent, String extrasKeySuffix) { intent .putExtra(MIME_TYPE_EXTRA + extrasKeySuffix, localConfiguration.mimeType) diff --git a/demos/session/build.gradle b/demos/session/build.gradle index 376c69534d..fb5ff78288 100644 --- a/demos/session/build.gradle +++ b/demos/session/build.gradle @@ -57,6 +57,8 @@ android { } dependencies { + // For detecting and debugging leaks only. LeakCanary is not needed for demo app to work. + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10' implementation 'androidx.core:core-ktx:' + androidxCoreVersion implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion implementation 'androidx.multidex:multidex:' + androidxMultidexVersion diff --git a/demos/session/src/main/AndroidManifest.xml b/demos/session/src/main/AndroidManifest.xml index 90557fc6c7..d3f9ba1620 100644 --- a/demos/session/src/main/AndroidManifest.xml +++ b/demos/session/src/main/AndroidManifest.xml @@ -40,7 +40,9 @@ + android:exported="true" + android:launchMode="singleTop" + android:theme="@style/Theme.AppCompat.NoActionBar"/> (R.id.open_player_floating_button) .setOnClickListener { - // display the playing media items - val intent = Intent(this, PlayerActivity::class.java) - startActivity(intent) + // Start the session activity that shows the playback activity. The System UI uses the same + // intent in the same way to start the activity from the notification. + browser?.sessionActivity?.send() } onBackPressedDispatcher.addCallback( - object : OnBackPressedCallback(/* enabled= */ true) { + object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { popPathStack() } diff --git a/demos/session/src/main/java/androidx/media3/demo/session/MediaItemTree.kt b/demos/session/src/main/java/androidx/media3/demo/session/MediaItemTree.kt index a1a6c6c187..690cbc11f0 100644 --- a/demos/session/src/main/java/androidx/media3/demo/session/MediaItemTree.kt +++ b/demos/session/src/main/java/androidx/media3/demo/session/MediaItemTree.kt @@ -20,8 +20,8 @@ import android.net.Uri import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem.SubtitleConfiguration import androidx.media3.common.MediaMetadata -import androidx.media3.common.util.Util import com.google.common.collect.ImmutableList +import java.io.BufferedReader import org.json.JSONObject /** @@ -91,10 +91,8 @@ object MediaItemTree { .build() } - private fun loadJSONFromAsset(assets: AssetManager): String { - val buffer = assets.open("catalog.json").use { Util.toByteArray(it) } - return String(buffer, Charsets.UTF_8) - } + private fun loadJSONFromAsset(assets: AssetManager): String = + assets.open("catalog.json").bufferedReader().use(BufferedReader::readText) fun initialize(assets: AssetManager) { if (isInitialized) return diff --git a/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt b/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt index 9c6f3e5b4a..f9c6873e80 100644 --- a/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt +++ b/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt @@ -51,6 +51,7 @@ class PlayableFolderActivity : AppCompatActivity() { companion object { private const val MEDIA_ITEM_ID_KEY = "MEDIA_ITEM_ID_KEY" + fun createIntent(context: Context, mediaItemID: String): Intent { val intent = Intent(context, PlayableFolderActivity::class.java) intent.putExtra(MEDIA_ITEM_ID_KEY, mediaItemID) @@ -77,8 +78,7 @@ class PlayableFolderActivity : AppCompatActivity() { browser.shuffleModeEnabled = false browser.prepare() browser.play() - val intent = Intent(this, PlayerActivity::class.java) - startActivity(intent) + browser.sessionActivity?.send() } } @@ -88,8 +88,7 @@ class PlayableFolderActivity : AppCompatActivity() { browser.shuffleModeEnabled = true browser.prepare() browser.play() - val intent = Intent(this, PlayerActivity::class.java) - startActivity(intent) + browser?.sessionActivity?.send() } findViewById