Skip to content

Commit 46d4066

Browse files
icbakercopybara-github
authored andcommitted
Add preload DAC snippets
This file is copied from https://github.com/android/snippets/blob/main/misc/src/main/java/com/example/snippets/PreloadManagerKotlinSnippets.kt I had to make the following changes to make it compile against the tip of the `main` branch (and these will need to be undone when cherrypicking this change to the `release` branch): 1. Rename `DefaultPreloadManager.PreloadStatus.TRACKS_SELECTED/SOURCE_PREPARED` to `PRELOAD_STATUS_TRACKS_SELECTED/_SOURCE_PREPARED`. 2. Change `getTargetPreloadStatus` to return a non-null `PreloadStatus` and `PRELOAD_STATUS_NOT_PRELOADED` instead of `null`. PiperOrigin-RevId: 797259358
1 parent b6be579 commit 46d4066

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

docsamples/build.gradle

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2023 The Android Open Source Project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle"
15+
16+
apply plugin: 'kotlin-android'
17+
18+
android {
19+
namespace 'androidx.media3.docsamples'
20+
21+
kotlinOptions {
22+
jvmTarget = '1.8'
23+
}
24+
25+
defaultConfig {
26+
minSdkVersion 23
27+
}
28+
}
29+
30+
dependencies {
31+
implementation project(modulePrefix + 'lib-datasource-cronet')
32+
implementation project(modulePrefix + 'lib-exoplayer')
33+
implementation project(modulePrefix + 'lib-exoplayer-dash')
34+
implementation project(modulePrefix + 'lib-exoplayer-hls')
35+
implementation project(modulePrefix + 'lib-exoplayer-ima')
36+
implementation project(modulePrefix + 'lib-exoplayer-rtsp')
37+
implementation project(modulePrefix + 'lib-exoplayer-smoothstreaming')
38+
implementation project(modulePrefix + 'lib-transformer')
39+
implementation project(modulePrefix + 'lib-effect')
40+
implementation project(modulePrefix + 'lib-muxer')
41+
implementation project(modulePrefix + 'lib-container')
42+
implementation project(modulePrefix + 'lib-session')
43+
implementation project(modulePrefix + 'lib-ui')
44+
implementation project(modulePrefix + 'lib-ui-compose')
45+
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
46+
implementation 'androidx.activity:activity-compose:1.9.0'
47+
implementation 'androidx.compose.material:material'
48+
implementation 'androidx.compose.material3:material3'
49+
implementation 'androidx.compose.material:material-icons-extended'
50+
implementation 'com.github.bumptech.glide:glide:' + glideVersion
51+
implementation 'com.github.bumptech.glide:concurrent-integration:' + glideVersion
52+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android' + kotlinxCoroutinesVersion
53+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:' + kotlinxCoroutinesVersion
54+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright 2023 The Android Open Source Project
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<manifest package="androidx.media3.docsamples">
17+
<uses-sdk />
18+
</manifest>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package androidx.media3.docsamples
18+
19+
import android.os.Bundle
20+
import androidx.annotation.OptIn
21+
import androidx.appcompat.app.AppCompatActivity
22+
import androidx.media3.common.C
23+
import androidx.media3.common.MediaItem
24+
import androidx.media3.common.util.UnstableApi
25+
import androidx.media3.exoplayer.ExoPlayer
26+
import androidx.media3.exoplayer.source.preload.DefaultPreloadManager
27+
import androidx.media3.exoplayer.source.preload.TargetPreloadStatusControl
28+
import java.lang.Math.abs
29+
30+
// constants to make the code snippets work
31+
const val currentPlayingIndex = 10
32+
33+
@UnstableApi
34+
// [START android_defaultpreloadmanager_MyTargetPreloadStatusControl]
35+
class MyTargetPreloadStatusControl(currentPlayingIndex: Int = C.INDEX_UNSET) :
36+
TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> {
37+
38+
override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus {
39+
if (index - currentPlayingIndex == 1) { // next track
40+
// return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
41+
// suggest loading 3000ms from the default start position
42+
return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
43+
} else if (index - currentPlayingIndex == -1) { // previous track
44+
// return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
45+
// suggest loading 3000ms from the default start position
46+
return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
47+
} else if (abs(index - currentPlayingIndex) == 2) {
48+
// return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
49+
return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED
50+
} else if (abs(index - currentPlayingIndex) <= 4) {
51+
// return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
52+
return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED
53+
}
54+
return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED
55+
}
56+
}
57+
58+
// [END android_defaultpreloadmanager_MyTargetPreloadStatusControl]
59+
60+
class PreloadManagerSnippetsKotlin {
61+
62+
class PreloadSnippetsActivity : AppCompatActivity() {
63+
private val context = this
64+
65+
@OptIn(UnstableApi::class)
66+
override fun onCreate(savedInstanceState: Bundle?) {
67+
super.onCreate(savedInstanceState)
68+
69+
// [START android_defaultpreloadmanager_createPLM]
70+
val targetPreloadStatusControl = MyTargetPreloadStatusControl()
71+
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
72+
val preloadManager = preloadManagerBuilder.build()
73+
// [END android_defaultpreloadmanager_createPLM]
74+
75+
val player = preloadManagerBuilder.buildExoPlayer()
76+
77+
// [START android_defaultpreloadmanager_addMedia]
78+
val initialMediaItems = pullMediaItemsFromService(count = 20)
79+
for (index in 0 until initialMediaItems.size) {
80+
preloadManager.add(initialMediaItems.get(index), /* rankingData= */ index)
81+
}
82+
// items aren't actually loaded yet! need to call invalidate() after this
83+
// [END android_defaultpreloadmanager_addMedia]
84+
85+
// [START android_defaultpreloadmanager_invalidate]
86+
preloadManager.invalidate()
87+
// [END android_defaultpreloadmanager_invalidate]
88+
}
89+
90+
@OptIn(UnstableApi::class)
91+
private fun fetchMedia(
92+
preloadManager: DefaultPreloadManager,
93+
mediaItem: MediaItem,
94+
player: ExoPlayer,
95+
currentIndex: Int,
96+
) {
97+
// [START android_defaultpreloadmanager_getAndPlayMedia]
98+
// When a media item is about to display on the screen
99+
val mediaSource = preloadManager.getMediaSource(mediaItem)
100+
if (mediaSource != null) {
101+
player.setMediaSource(mediaSource)
102+
} else {
103+
// If mediaSource is null, that mediaItem hasn't been added to the preload manager
104+
// yet. So, send it directly to the player when it's about to play
105+
player.setMediaItem(mediaItem)
106+
}
107+
player.prepare()
108+
109+
// When the media item is displaying at the center of the screen
110+
player.play()
111+
preloadManager.setCurrentPlayingIndex(currentIndex)
112+
113+
// Need to call invalidate() to update the priorities
114+
preloadManager.invalidate()
115+
// [END android_defaultpreloadmanager_getAndPlayMedia]
116+
}
117+
118+
@OptIn(UnstableApi::class)
119+
private fun removeMedia(mediaItem: MediaItem, preloadManager: DefaultPreloadManager) {
120+
// [START android_defaultpreloadmanager_removeItem]
121+
preloadManager.remove(mediaItem)
122+
// [END android_defaultpreloadmanager_removeItem]
123+
}
124+
125+
@OptIn(UnstableApi::class)
126+
private fun releasePLM(preloadManager: DefaultPreloadManager) {
127+
// [START android_defaultpreloadmanager_releasePLM]
128+
preloadManager.release()
129+
// [END android_defaultpreloadmanager_releasePLM]
130+
}
131+
132+
// no-op methods to support the code snippets
133+
private fun pullMediaItemsFromService(count: Int): List<MediaItem> {
134+
return listOf()
135+
}
136+
}
137+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
@NonNullApi
17+
package androidx.media3.docsamples;
18+
19+
import androidx.media3.common.util.NonNullApi;

0 commit comments

Comments
 (0)