Crea e configura un DefaultPreloadManager

Questa pagina descrive come creare un DefaultPreloadManager, che precarica i contenuti multimediali per la tua app in base alla strategia che scegli.

I gestori del precaricamento basati sulla classe astratta BasePreloadManager ti consentono di classificare i contenuti in base ai criteri che scegli. Questo documento spiega come utilizzare la classe derivata DefaultPreloadManager, in cui ogni elemento multimediale viene classificato con un numero intero che rappresenta la sua posizione in un elenco (ad esempio, la sua posizione in un carosello di video). Il gestore del precaricamento dà la priorità al caricamento degli elementi in base alla loro vicinanza all'elemento che l'utente sta riproducendo. In questo modo, se un utente passa a un altro elemento, la riproduzione del nuovo elemento può iniziare immediatamente.

Per creare un'istanza di DefaultPreloadManager, segui questi tre passaggi:

  • Definisci un TargetPreloadStatusControl che il gestore del precaricamento può interrogare per scoprire se l'elemento multimediale è pronto per essere caricato e quanto caricare.
  • Crea il builder che utilizzerai per creare il gestore del precaricamento e gli oggetti ExoPlayer della tua app.
  • Utilizza il builder per creare il gestore del precaricamento chiamando il metodo build() del builder.

Crea un controllo dello stato di precaricamento della destinazione

Quando crei DefaultPreloadManager.Builder, gli trasmetti un oggetto controllo dello stato di precaricamento di destinazione che definisci. Questo oggetto implementa l'interfaccia TargetPreloadStatusControl. Quando il gestore del precaricamento si prepara a precaricare i contenuti multimediali, chiama il metodo getTargetPreloadStatus() del controllo dello stato per determinare se preparare, caricare o memorizzare nella cache i contenuti di un elemento multimediale. Il caricamento precarica i dati multimediali direttamente nel buffer in memoria di un player, rendendoli pronti per la riproduzione immediata, mentre la memorizzazione nella cache salva i dati multimediali in una cache del disco permanente per risparmiare memoria del player. Il controllo dello stato può rispondere con uno di questi codici di stato:

  • STAGE_SPECIFIED_RANGE_LOADED: il gestore del precaricamento deve caricare i contenuti dalla posizione iniziale specificata e per la durata specificata (indicata in millisecondi) nel buffer in memoria del player.
  • STAGE_SPECIFIED_RANGE_CACHED: Il gestore del precaricamento deve memorizzare nella cache del disco i contenuti dalla posizione iniziale specificata e per la durata specificata (in millisecondi).
  • STAGE_TRACKS_SELECTED: il gestore del precaricamento deve caricare ed elaborare le informazioni della traccia dei contenuti e selezionare le tracce. Il gestore del precaricamento non deve ancora iniziare a caricare i contenuti.
  • STAGE_SOURCE_PREPARED: Il gestore del precaricamento deve preparare l'origine dei contenuti. Ad esempio, se i metadati dei contenuti si trovano in un file manifest separato, il gestore del precaricamento potrebbe recuperare e analizzare il manifest.
  • null: il gestore del precaricamento non deve caricare contenuti o metadati per quell'elemento multimediale.

Devi avere una strategia per decidere quanti contenuti caricare per ogni elemento multimediale. In questo esempio, vengono caricati più contenuti per gli elementi più vicini all'elemento attualmente in riproduzione. Se l'utente riproduce contenuti con indice n, il controller restituisce i seguenti codici:

  • Indice n+1 (il successivo elemento multimediale): carica 3000 ms (3 secondi) dalla posizione iniziale predefinita
  • Indice n-1 (l'elemento multimediale precedente): carica 1000 ms (1 secondo) dalla posizione iniziale predefinita
  • Altri elementi multimediali nell'intervallo da n-2 a n+2: Return PreloadStatus.TRACKS_SELECTED
  • Altri elementi multimediali nell'intervallo da n-4 a n+4: Return PreloadStatus.SOURCE_PREPARED
  • Per tutti gli altri elementi multimediali, restituisci null

class MyTargetPreloadStatusControl(var currentPlayingIndex: Int = 0) :
  TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> {

  override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus {
    if (index - currentPlayingIndex == 1) { // next track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (index - currentPlayingIndex == -1) { // previous track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (abs(index - currentPlayingIndex) == 2) {
      // return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED
    } else if (abs(index - currentPlayingIndex) <= 4) {
      // return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED
    }
    return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED
  }
}

Punti chiave sul codice

  • Quando crei il generatore del gestore del precaricamento, devi passare un'istanza di MyTargetPreloadStatusControl.
  • currentPlayingIndex contiene l'indice dell'elemento multimediale attualmente in riproduzione. È compito dell'app mantenere aggiornato questo valore.
  • Quando il gestore del precaricamento è pronto per caricare i contenuti, chiama getTargetPreloadStatus e trasmette le informazioni sul ranking specificate per l'elemento multimediale corrispondente. Nel caso di DefaultPreloadManager, queste informazioni sul ranking sono un numero intero che specifica la posizione dell'elemento in un carosello. Il metodo sceglie il codice da restituire confrontando l'indice con l'indice dell'elemento attualmente selezionato.

Crea il gestore del precaricamento

Per creare il gestore del precaricamento, devi disporre di un DefaultPreloadManager.Builder. Questo builder è configurato con il contesto attuale e il controllo dello stato di precaricamento di destinazione dell'app. Puoi creare un gestore del precaricamento con tutte le configurazioni predefinite.

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = preloadManagerBuilder.build()

Il builder fornisce anche metodi setter che puoi utilizzare per impostare i componenti personalizzati del gestore del precaricamento.

Ad esempio, puoi personalizzare il buffer totale target in byte per tutte le origini multimediali di precaricamento in DefaultPreloadManager, in modo che i dati precaricati non superino questo limite. Puoi configurare questo limite utilizzando setPlayerTargetBufferBytes(String, int) su un DefaultLoadControl.Builder personalizzato con il nome del giocatore "preload" e passare questa istanza al builder del gestore di precaricamento:

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)

preloadManagerBuilder.setLoadControl(
  DefaultLoadControl.Builder()
    .setPlayerTargetBufferBytes("preload", 128 * 1024 * 1024) // 128 MiB
    .build()
)
val preloadManager = preloadManagerBuilder.build()

Sebbene i metodi setter del builder siano fondamentalmente facoltativi per la personalizzazione, se vuoi memorizzare nella cache qualsiasi elemento multimediale su disco, devi configurare il builder con un Cache chiamando setCache(). Se non è configurata alcuna cache, il tentativo di memorizzare nella cache gli elementi multimediali comporterà un IllegalStateException.

Crea ExoPlayer per riprodurre l'elemento multimediale precaricato

Oltre a utilizzare lo strumento di creazione per creare il gestore del precaricamento, lo utilizzerai anche per creare gli oggetti ExoPlayer che la tua app utilizza per riprodurre i contenuti, in modo che ExoPlayer condivida correttamente i componenti con il gestore del precaricamento. Puoi comunque impostare le configurazioni specifiche di riproduzione per ExoPlayer passando un'istanza ExoPlayer.Builder con queste configurazioni impostate.

// Direct creation
val exoPlayer = preloadManagerBuilder.buildExoPlayer()

// Creation with custom playback specific configurations
val skipSilenceExoPlayerBuilder = ExoPlayer.Builder(context).setSkipSilenceEnabled(true)
val skipSilenceExoPlayer = preloadManagerBuilder.buildExoPlayer(skipSilenceExoPlayerBuilder)