ExoPlayer udostępnia funkcję pobierania multimediów do odtwarzania offline. Najwięcej
zaleca się, aby pobieranie było możliwe nawet wtedy, gdy aplikacja znajduje się
w tle. W tych przypadkach aplikacja powinna podklasa: DownloadService i
wysyłania do usługi poleceń w celu dodania, usunięcia i kontrolowania pobranych plików.
na diagramie poniżej widać główne klasy, które są z nim związane.
DownloadService: zawija obiektDownloadManageri przekazuje do niego polecenia. umożliwia działanie aplikacjiDownloadManagernawet wtedy, gdy jest ona uruchomiona w tle.DownloadManager: zarządza wieloma pobieraniem, wczytuje (i zapisuje) ich pliki od (i do)DownloadIndex, rozpoczynając i zatrzymując pobieranie na podstawie dotyczące wymagań dotyczących m.in. połączenia sieciowego. Aby pobrać treści, menedżer zazwyczaj odczytuje dane pobierane zHttpDataSourcei wpisz go wCache.DownloadIndex: zachowuje stan pobierania.
Tworzenie usługi DownloadService
Aby utworzyć klasę DownloadService, należy ją podklasyować i zaimplementować
metody abstrakcyjne:
getDownloadManager(): zwraca wartośćDownloadManager, która ma zostać użyta.getScheduler(): zwraca opcjonalny elementScheduler, który może ponownie uruchomić usługi, gdy są spełnione wymagania dotyczące oczekujących pobrań. ExoPlayer udostępnia te implementacje:PlatformScheduler, które używa JobScheduler (minimum to 21). Zobacz zapoznaj się z wymaganiami dotyczącymi uprawnień aplikacji w dokumentacji javadocs PlatformScheduler.WorkManagerScheduler, który korzysta z WorkManagera.
getForegroundNotification(): zwraca powiadomienie, które wyświetla się, gdy usługa jest uruchomiona na pierwszym planie. Za pomocąDownloadNotificationHelper.buildProgressNotification, aby utworzyć powiadomienie w domyślnym stylu.
Na koniec zdefiniuj usługę w pliku AndroidManifest.xml:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<application>
<service android:name="com.myapp.MyDownloadService"
android:exported="false"
android:foregroundServiceType="dataSync">
<!-- This is needed for Scheduler -->
<intent-filter>
<action android:name="androidx.media3.exoplayer.downloadService.action.RESTART"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
Zobacz DemoDownloadService i AndroidManifest.xml w ExoPlayer
z konkretnym przykładem.
Tworzenie Menedżera pobierania
Ten fragment kodu pokazuje, jak utworzyć instancję DownloadManager,
które może zwrócić getDownloadManager() w DownloadService:
Kotlin
// Note: This should be a singleton in your app. val databaseProvider = StandaloneDatabaseProvider(context) // A download cache should not evict media, so should use a NoopCacheEvictor. val downloadCache = SimpleCache(downloadDirectory, NoOpCacheEvictor(), databaseProvider) // Create a factory for reading the data from the network. val dataSourceFactory = DefaultHttpDataSource.Factory() // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up // download tasks that can be split into smaller parts for parallel execution. Applications that // already have an executor for background downloads may wish to reuse their existing executor. val downloadExecutor = Executor(Runnable::run) // Create the download manager. val downloadManager = DownloadManager(context, databaseProvider, downloadCache, dataSourceFactory, downloadExecutor) // Optionally, properties can be assigned to configure the download manager. downloadManager.requirements = requirements downloadManager.maxParallelDownloads = 3
Java
// Note: This should be a singleton in your app. databaseProvider = new StandaloneDatabaseProvider(context); // A download cache should not evict media, so should use a NoopCacheEvictor. downloadCache = new SimpleCache(downloadDirectory, new NoOpCacheEvictor(), databaseProvider); // Create a factory for reading the data from the network. dataSourceFactory = new DefaultHttpDataSource.Factory(); // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up // download tasks that can be split into smaller parts for parallel execution. Applications that // already have an executor for background downloads may wish to reuse their existing executor. Executor downloadExecutor = Runnable::run; // Create the download manager. downloadManager = new DownloadManager( context, databaseProvider, downloadCache, dataSourceFactory, downloadExecutor); // Optionally, setters can be called to configure the download manager. downloadManager.setRequirements(requirements); downloadManager.setMaxParallelDownloads(3);
Konkretny przykład znajdziesz w sekcji DemoUtil w aplikacji w wersji demonstracyjnej.
Dodaję pobrany plik
Aby dodać pobrany plik, utwórz DownloadRequest i wyślij go na
DownloadService W przypadku strumieni adaptacyjnych użyj DownloadHelper.
utwórz DownloadRequest. Poniżej
pokazuje, jak utworzyć żądanie pobrania:
Kotlin
val downloadRequest = DownloadRequest.Builder(contentId, contentUri).build()
Java
DownloadRequest downloadRequest = new DownloadRequest.Builder(contentId, contentUri).build();
W tym przykładzie contentId jest unikalnym identyfikatorem treści. W prostych przypadkach
contentUri może często służyć jako contentId, ale aplikacje są bezpłatne.
do każdego schematu identyfikatora, który najlepiej sprawdzi się w danym przypadku. DownloadRequest.Builder ma też
kilku opcjonalnych ustawień. Na przykład można użyć setKeySetId i setData, aby:
ustawić DRM i dane niestandardowe, które aplikacja ma powiązać z pobranym plikiem;
. Typ MIME treści można też określić w polu setMimeType,
jako wskazówkę w przypadkach, w których nie można wywnioskować typu treści na podstawie contentUri.
Po utworzeniu prośbę można wysłać do DownloadService, aby dodać
pobieranie:
Kotlin
DownloadService.sendAddDownload( context, MyDownloadService::class.java, downloadRequest, /* foreground= */ false )
Java
DownloadService.sendAddDownload( context, MyDownloadService.class, downloadRequest, /* foreground= */ false);
W tym przykładzie MyDownloadService to podklasa aplikacji DownloadService, a klasa
Parametr foreground określa, czy usługa zostanie uruchomiona w
na pierwszym planie. Jeśli aplikacja jest już na pierwszym planie, parametr foreground
powinien być ustawiony na false, bo DownloadService będzie
umieścić się na pierwszym planie, jeśli stwierdzi, że ma do wykonania zadanie.
Usuwam pobrane
Aby usunąć pobrany plik, wyślij do DownloadService polecenie usunięcia.
gdzie contentId wskazuje pobrany plik:
Kotlin
DownloadService.sendRemoveDownload( context, MyDownloadService::class.java, contentId, /* foreground= */ false )
Java
DownloadService.sendRemoveDownload( context, MyDownloadService.class, contentId, /* foreground= */ false);
Możesz też usunąć wszystkie pobrane dane za pomocą
DownloadService.sendRemoveAllDownloads
Rozpoczynanie i zatrzymywanie pobierania
Pobieranie będzie kontynuowane tylko wtedy, gdy zostaną spełnione 4 warunki:
- Pobieranie nie ma powodu zatrzymania.
- Pobieranie nie jest wstrzymywane.
- Spełniono wymagania dotyczące pobierania plików. Wymagania mogą obejmować dotyczące dozwolonych typów sieci oraz tego, czy urządzenie być nieaktywne lub podłączone do ładowarki.
- Maksymalna liczba równoległych pobrań nie została przekroczona.
Wszystkie te warunki można kontrolować, wysyłając polecenia do
DownloadService
Ustawianie i usuwanie przyczyn zatrzymania pobierania
Możesz ustawić przyczynę zatrzymania pobierania jednego lub wszystkich plików:
Kotlin
// Set the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService::class.java, contentId, stopReason, /* foreground= */ false ) // Clear the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService::class.java, contentId, Download.STOP_REASON_NONE, /* foreground= */ false )
Java
// Set the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService.class, contentId, stopReason, /* foreground= */ false); // Clear the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService.class, contentId, Download.STOP_REASON_NONE, /* foreground= */ false);
stopReason może mieć dowolną wartość inną niż 0 (Download.STOP_REASON_NONE = 0 to
specjalną wartość, która oznacza, że pobieranie nie zostało zatrzymane). Aplikacje, które zawierają
Różne przyczyny zatrzymania pobierania mogą mieć różne wartości, aby śledzić
przyczyny zatrzymania pobierania. Ustawianie i usuwanie przyczyny zatrzymania dla wszystkich
pobierania działa tak samo jak ustawianie i usuwanie przyczyny zatrzymania
jednorazowe pobranie, z tym że parametr contentId powinien mieć wartość null.
Jeśli przyczyna zatrzymania pobierania jest inna niż zero, zostanie on umieszczony w sekcji
Download.STATE_STOPPED stan. Przyczyny zatrzymania są zachowywane w
DownloadIndex, a także są przechowywane w przypadku zakończenia procesu zgłaszania, a także
później.
Wstrzymywanie i wznawianie pobierania wszystkich plików
Pobieranie można wstrzymywać i wznawiać w następujący sposób:
Kotlin
// Pause all downloads. DownloadService.sendPauseDownloads( context, MyDownloadService::class.java, /* foreground= */ false ) // Resume all downloads. DownloadService.sendResumeDownloads( context, MyDownloadService::class.java, /* foreground= */ false )
Java
// Pause all downloads. DownloadService.sendPauseDownloads(context, MyDownloadService.class, /* foreground= */ false); // Resume all downloads. DownloadService.sendResumeDownloads(context, MyDownloadService.class, /* foreground= */ false);
Po wstrzymaniu pobierania ich stan zmieni się na Download.STATE_QUEUED.
W przeciwieństwie do ustawionych przyczyn zatrzymania ta metoda nie zachowuje żadnego stanu
zmian. Ma to wpływ tylko na stan środowiska wykonawczego DownloadManager.
Konfigurowanie wymagań dotyczących postępu pobierania
Requirements może służyć do określania ograniczeń, które muszą być spełnione w przypadku
pobrane pliki, aby kontynuować. Wymagania można określić, wywołując
DownloadManager.setRequirements() podczas tworzenia DownloadManager, na przykład
przykład powyżej. Można je również dynamicznie zmieniać, wysyłając polecenie
do DownloadService:
Kotlin
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService::class.java, requirements, /* foreground= */ false)
Java
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService.class, requirements, /* foreground= */ false);
Jeśli nie można kontynuować pobierania z powodu niespełniania wymagań,
będzie mieć stan Download.STATE_QUEUED. Możesz przesłać zapytanie o niespełnione
DownloadManager.getNotMetRequirements().
Ustawianie maksymalnej liczby równoległego pobierania
Maksymalna liczba równoległych pobrań można ustawić, wywołując
DownloadManager.setMaxParallelDownloads() Zwykle ma to miejsce, gdy
tworząc DownloadManager, jak widać w przykładzie powyżej.
Gdy nie można kontynuować pobierania ze względu na maksymalną liczbę równoległych pobrań
są już w toku, będą w stanie Download.STATE_QUEUED.
Pytanie dotyczące pobierania
Zapytanie DownloadIndex elementu DownloadManager może być wysyłane w przypadku stanu wszystkich
pobierania, w tym tych, które zakończyły się lub zakończyły się niepowodzeniem. DownloadIndex
można uzyskać, wywołując DownloadManager.getDownloadIndex(). Kursor,
powtórzenia we wszystkich pobranych plikach można następnie uzyskać przez wywołanie
DownloadIndex.getDownloads() Stan pojedynczego pobrania
można wysyłać zapytania, wywołując DownloadIndex.getDownload().
DownloadManager udostępnia również DownloadManager.getCurrentDownloads(), które
zwraca tylko stan bieżących (tj. nieukończonych lub nieudanych) pobrań. Ten
jest przydatna przy aktualizowaniu powiadomień i innych komponentów interfejsu, które wyświetlają
postęp i stan pobierania.
Słucham pobranych treści
Możesz dodać detektor do aplikacji DownloadManager, aby otrzymywać informacje o bieżącej
zmiany stanu pobierania:
Kotlin
downloadManager.addListener( object : DownloadManager.Listener { // Override methods of interest here. } )
Java
downloadManager.addListener( new DownloadManager.Listener() { // Override methods of interest here. });
Zobacz temat DownloadManagerListener w zajęciach DownloadTracker w aplikacji w wersji demonstracyjnej
z konkretnego przykładu.
Odtwarzam pobrane treści
Odtwarzanie pobranych treści przypomina odtwarzanie treści online, z tą różnicą, że
dane są odczytywane z pobranego pliku Cache, a nie przez sieć.
Aby odtworzyć pobrane treści, utwórz CacheDataSource.Factory, używając tego samego elementu
Cache instancję, która została użyta do pobrania i wstrzyknij ją do
DefaultMediaSourceFactory podczas tworzenia odtwarzacza:
Kotlin
// Create a read-only cache data source factory using the download cache. val cacheDataSourceFactory: DataSource.Factory = CacheDataSource.Factory() .setCache(downloadCache) .setUpstreamDataSourceFactory(httpDataSourceFactory) .setCacheWriteDataSinkFactory(null) // Disable writing. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory) ) .build()
Java
// Create a read-only cache data source factory using the download cache. DataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory() .setCache(downloadCache) .setUpstreamDataSourceFactory(httpDataSourceFactory) .setCacheWriteDataSinkFactory(null); // Disable writing. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build();
Czy ta sama instancja odtwarzacza będzie także używana do odtwarzania niepobranych treści
interfejs CacheDataSource.Factory powinien być skonfigurowany jako tylko do odczytu, aby uniknąć
pobieranie tych treści również podczas odtwarzania.
Po skonfigurowaniu odtwarzacza CacheDataSource.Factory będzie on
mają dostęp do pobranych treści w celu ich odtwarzania. Odtworzenie pobranego pliku jest wtedy
Wystarczy przekazać odpowiednie MediaItem do odtwarzacza. MediaItem
można uzyskać z Download przy użyciu Download.request.toMediaItem lub
bezpośrednio z usługi DownloadRequest przy użyciu DownloadRequest.toMediaItem.
Konfiguracja MediaSource
Poprzedni przykład udostępnia pamięć podręczną pobierania do odtwarzania wszystkich plików
MediaItem Możesz też udostępnić pamięć podręczną pobierania dla
pojedyncze instancje MediaSource, które mogą być przekazywane bezpośrednio do odtwarzacza:
Kotlin
val mediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)) player.setMediaSource(mediaSource) player.prepare()
Java
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)); player.setMediaSource(mediaSource); player.prepare();
Pobieranie i odtwarzanie strumieni adaptacyjnych
Strumienie adaptacyjne (np. DASH, SmoothStreaming i HLS) zwykle zawierają wiele ścieżek multimedialnych. Często istnieje wiele ścieżek zawierających te same treści w różnych jakości (np. ścieżki wideo SD, HD i 4K). Może być też wiele ścieżek tego samego typu zawierających różne treści (np. wiele ścieżek audio w różnych językach).
W przypadku odtwarzania strumieniowego można skorzystać z selektora ścieżki, aby wybrać
odtwarzanych utworów. Podobnie DownloadHelper może służyć do:
wybrać utwory do pobrania. Typowe użycie: DownloadHelper
wykonaj te czynności:
- Utwórz
DownloadHelper, korzystając z jednego zDownloadHelper.forMediaItem. Przygotuj pomocnik i zaczekaj na oddzwonienie.Kotlin
val downloadHelper = DownloadHelper.forMediaItem( context, MediaItem.fromUri(contentUri), DefaultRenderersFactory(context), dataSourceFactory ) downloadHelper.prepare(callback)
Java
DownloadHelper downloadHelper = DownloadHelper.forMediaItem( context, MediaItem.fromUri(contentUri), new DefaultRenderersFactory(context), dataSourceFactory); downloadHelper.prepare(callback);
- Opcjonalnie sprawdź domyślnie wybrane ścieżki za pomocą narzędzia
getMappedTrackInfoigetTrackSelectionsoraz wprowadź korekty za pomocąclearTrackSelections,replaceTrackSelectionsiaddTrackSelection. - Utwórz
DownloadRequestdla wybranych utworów, dzwoniąc pod numergetDownloadRequestProśba może zostać przekazana doDownloadServicew celu dodaj pobrany plik w sposób opisany powyżej. - Zwolnij pomocnik, używając polecenia
release().
Odtwarzanie pobranych treści adaptacyjnych wymaga skonfigurowania odtwarzacza i
przekazując odpowiednią wartość MediaItem zgodnie z opisem powyżej.
Podczas tworzenia obiektu MediaItem MediaItem.localConfiguration.streamKeys musi być:
jest ustawione na dopasowanie do tych w DownloadRequest, tak by odtwarzacz próbował tylko
odtworzyć podzbiór pobranych utworów. Zastosowanie
Download.request.toMediaItem i DownloadRequest.toMediaItem, aby utworzyć
MediaItem zajmie się tym za Ciebie.