The two codes are very similar in their structure and logic, but there are several notable differences:
1. Difference in the RenderersFactory
-
First code:
renderFactory = new DefaultRenderersFactory(context);
- It directly uses
DefaultRenderersFactory
from ExoPlayer.
- It directly uses
-
Second code:
renderFactory = prefs.getBoolean( context.getString( R.string.always_use_exoplayer_set_output_surface_workaround_key), false) ? new CustomRenderersFactory(context) : new DefaultRenderersFactory(context);
- It introduces conditional logic: if a user preference (
always_use_exoplayer_set_output_surface_workaround_key
) is enabled, it usesCustomRenderersFactory
instead ofDefaultRenderersFactory
. - It also enables an additional option:
This option allows ExoPlayer to use a different decoder if the one initially planned fails.renderFactory.setEnableDecoderFallback( prefs.getBoolean( context.getString( R.string.use_exoplayer_decoder_fallback_key), false));
- It introduces conditional logic: if a user preference (
2. Handling ExoPlayer Events
- Present only in the second code:
@Override public void onEvents(@NonNull final com.google.android.exoplayer2.Player player, @NonNull final com.google.android.exoplayer2.Player.Events events) { Listener.super.onEvents(player, events); MediaItemTag.from(player.getCurrentMediaItem()).ifPresent(tag -> { if (tag == currentMetadata) { return; } final StreamInfo previousInfo = Optional.ofNullable(currentMetadata) .flatMap(MediaItemTag::getMaybeStreamInfo).orElse(null); final MediaItemTag.AudioTrack previousAudioTrack = Optional.ofNullable(currentMetadata) .flatMap(MediaItemTag::getMaybeAudioTrack).orElse(null); currentMetadata = tag; if (!currentMetadata.getErrors().isEmpty()) { final ErrorInfo errorInfo = new ErrorInfo( currentMetadata.getErrors(), UserAction.PLAY_STREAM, "Loading failed for [" + currentMetadata.getTitle() + "]: " + currentMetadata.getStreamUrl(), currentMetadata.getServiceId()); ErrorUtil.createNotification(context, errorInfo); } currentMetadata.getMaybeStreamInfo().ifPresent(info -> { if (DEBUG) { Log.d(TAG, "ExoPlayer - onEvents() update stream info: " + info.getName()); } if (previousInfo == null || !previousInfo.getUrl().equals(info.getUrl())) { updateMetadataWith(info); } else if (previousAudioTrack == null || tag.getMaybeAudioTrack() .map(t -> t.getSelectedAudioStreamIndex() != previousAudioTrack.getSelectedAudioStreamIndex()) .orElse(false)) { notifyAudioTrackUpdateToListeners(); } }); }); }
- It implements
onEvents()
to listen for ExoPlayer events. - It updates
currentMetadata
with each event and triggers updates if necessary. - It handles errors and sends a notification if a playback issue occurs.
- It implements
3. Handling Audio Tracks
- Present only in the second code:
public Optional<AudioStream> getSelectedAudioStream() { return Optional.ofNullable(currentMetadata) .flatMap(MediaItemTag::getMaybeAudioTrack) .map(MediaItemTag.AudioTrack::getSelectedAudioStream); } private void notifyAudioTrackUpdateToListeners() { if (fragmentListener != null) { fragmentListener.onAudioTrackUpdate(); } if (activityListener != null) { activityListener.onAudioTrackUpdate(); } }
- This section allows retrieving the selected audio track and sends updates to the listeners (
fragmentListener
andactivityListener
). - It is absent in the first code.
- This section allows retrieving the selected audio track and sends updates to the listeners (
4. Handling Video Quality and Audio Tracks
-
In the first code:
if (intent.hasExtra(PLAYBACK_QUALITY)) { setPlaybackQuality(intent.getStringExtra(PLAYBACK_QUALITY)); }
-
In the second code:
if (intent.hasExtra(PLAYBACK_QUALITY)) { videoResolver.setPlaybackQuality(intent.getStringExtra(PLAYBACK_QUALITY)); }
- The second code uses
videoResolver.setPlaybackQuality()
, suggesting that it employs a more centralized method to manage playback quality.
- The second code uses
-
Added in the second code:
public void setAudioTrack(@Nullable final String audioTrackId) { saveStreamProgressState(); setRecovery(); videoResolver.setAudioTrack(audioTrackId); audioResolver.setAudioTrack(audioTrackId); reloadPlayQueueManager(); }
- It allows setting the audio track, a feature absent in the first code.
Summary of Key Differences:
-
Advanced handling of
RenderersFactory
in the second code- It introduces
CustomRenderersFactory
based on a user preference and enablessetEnableDecoderFallback
.
- It introduces
-
Handling ExoPlayer events in the second code
- It implements
onEvents()
to detect stream changes and handle errors.
- It implements
-
Addition of audio track management in the second code
- It allows retrieving and changing the currently playing audio track.
-
Improved video quality and audio track management in the second code
- It uses
videoResolver
to modify playback quality and allows changing the audio track.
- It uses
Les deux codes sont très similaires dans leur structure et leur logique, mais il y a plusieurs différences notables :
1. Différence au niveau de la RenderersFactory
-
Premier code :
renderFactory = new DefaultRenderersFactory(context);
- Il utilise directement
DefaultRenderersFactory
de ExoPlayer.
- Il utilise directement
-
Deuxième code :
renderFactory = prefs.getBoolean( context.getString( R.string.always_use_exoplayer_set_output_surface_workaround_key), false) ? new CustomRenderersFactory(context) : new DefaultRenderersFactory(context);
- Il introduit une logique conditionnelle : si une préférence utilisateur (
always_use_exoplayer_set_output_surface_workaround_key
) est activée, il utiliseCustomRenderersFactory
au lieu deDefaultRenderersFactory
. - Il active également une option supplémentaire :
Cette option permet à ExoPlayer d’utiliser un autre décodeur si celui prévu initialement échoue.renderFactory.setEnableDecoderFallback( prefs.getBoolean( context.getString( R.string.use_exoplayer_decoder_fallback_key), false));
- Il introduit une logique conditionnelle : si une préférence utilisateur (
2. Gestion des événements ExoPlayer
- Présent uniquement dans le deuxième code :
@Override public void onEvents(@NonNull final com.google.android.exoplayer2.Player player, @NonNull final com.google.android.exoplayer2.Player.Events events) { Listener.super.onEvents(player, events); MediaItemTag.from(player.getCurrentMediaItem()).ifPresent(tag -> { if (tag == currentMetadata) { return; } final StreamInfo previousInfo = Optional.ofNullable(currentMetadata) .flatMap(MediaItemTag::getMaybeStreamInfo).orElse(null); final MediaItemTag.AudioTrack previousAudioTrack = Optional.ofNullable(currentMetadata) .flatMap(MediaItemTag::getMaybeAudioTrack).orElse(null); currentMetadata = tag; if (!currentMetadata.getErrors().isEmpty()) { final ErrorInfo errorInfo = new ErrorInfo( currentMetadata.getErrors(), UserAction.PLAY_STREAM, "Loading failed for [" + currentMetadata.getTitle() + "]: " + currentMetadata.getStreamUrl(), currentMetadata.getServiceId()); ErrorUtil.createNotification(context, errorInfo); } currentMetadata.getMaybeStreamInfo().ifPresent(info -> { if (DEBUG) { Log.d(TAG, "ExoPlayer - onEvents() update stream info: " + info.getName()); } if (previousInfo == null || !previousInfo.getUrl().equals(info.getUrl())) { updateMetadataWith(info); } else if (previousAudioTrack == null || tag.getMaybeAudioTrack() .map(t -> t.getSelectedAudioStreamIndex() != previousAudioTrack.getSelectedAudioStreamIndex()) .orElse(false)) { notifyAudioTrackUpdateToListeners(); } }); }); }
- Il implémente
onEvents()
pour écouter les événements d’ExoPlayer. - Il met à jour
currentMetadata
à chaque événement et déclenche des mises à jour si nécessaire. - Il gère les erreurs et envoie une notification si un problème de lecture survient.
- Il implémente
3. Gestion des pistes audio
- Présent uniquement dans le deuxième code :
public Optional<AudioStream> getSelectedAudioStream() { return Optional.ofNullable(currentMetadata) .flatMap(MediaItemTag::getMaybeAudioTrack) .map(MediaItemTag.AudioTrack::getSelectedAudioStream); } private void notifyAudioTrackUpdateToListeners() { if (fragmentListener != null) { fragmentListener.onAudioTrackUpdate(); } if (activityListener != null) { activityListener.onAudioTrackUpdate(); } }
- Cette partie permet de récupérer la piste audio sélectionnée et d’envoyer des mises à jour aux listeners (
fragmentListener
etactivityListener
). - Elle est absente dans le premier code.
- Cette partie permet de récupérer la piste audio sélectionnée et d’envoyer des mises à jour aux listeners (
4. Gestion de la qualité vidéo et des pistes audio
-
Dans le premier code :
if (intent.hasExtra(PLAYBACK_QUALITY)) { setPlaybackQuality(intent.getStringExtra(PLAYBACK_QUALITY)); }
-
Dans le deuxième code :
if (intent.hasExtra(PLAYBACK_QUALITY)) { videoResolver.setPlaybackQuality(intent.getStringExtra(PLAYBACK_QUALITY)); }
- Le deuxième code passe par
videoResolver.setPlaybackQuality()
, ce qui suggère qu’il utilise une méthode plus centralisée pour gérer la qualité de lecture.
- Le deuxième code passe par
-
Ajout dans le deuxième code :
public void setAudioTrack(@Nullable final String audioTrackId) { saveStreamProgressState(); setRecovery(); videoResolver.setAudioTrack(audioTrackId); audioResolver.setAudioTrack(audioTrackId); reloadPlayQueueManager(); }
- Il permet de définir la piste audio, fonctionnalité absente du premier code.
Résumé des différences principales :
-
Gestion avancée de
RenderersFactory
dans le deuxième code- Il introduit
CustomRenderersFactory
en fonction d'une préférence utilisateur et activesetEnableDecoderFallback
.
- Il introduit
-
Gestion des événements ExoPlayer dans le deuxième code
- Il implémente
onEvents()
pour détecter les changements de flux et gérer les erreurs.
- Il implémente
-
Ajout de la gestion des pistes audio dans le deuxième code
- Il permet de récupérer et changer la piste audio en cours de lecture.
-
Gestion améliorée de la qualité vidéo et des pistes audio dans le deuxième code
- Il passe par
videoResolver
pour modifier la qualité de lecture et permet de changer la piste audio.
- Il passe par