From ff91d33a88f9da04949662efa595e55d5efa1544 Mon Sep 17 00:00:00 2001 From: Docile-Alligator <25734209+Docile-Alligator@users.noreply.github.com> Date: Sun, 12 May 2024 22:52:04 -0400 Subject: Migrate to AndroidX Media3. --- app/build.gradle | 10 ++-- .../infinityforreddit/AppModule.java | 12 +++-- .../activities/PostVideoActivity.java | 18 ++++--- .../activities/ViewVideoActivity.java | 58 ++++++++++++--------- .../adapters/HistoryPostRecyclerViewAdapter.java | 44 ++++++++++------ .../adapters/PostDetailRecyclerViewAdapter.java | 28 ++++++---- .../adapters/PostRecyclerViewAdapter.java | 29 +++++------ .../customviews/LoopAvailableExoCreator.java | 5 +- .../fragments/ViewImgurVideoFragment.java | 32 ++++++------ .../ViewImgurVideoFragmentBindingAdapter.java | 5 +- .../fragments/ViewRedditGalleryVideoFragment.java | 34 +++++++------ ...ewRedditGalleryVideoFragmentBindingAdapter.java | 5 +- .../infinityforreddit/videoautoplay/BaseMeter.java | 13 ++--- .../infinityforreddit/videoautoplay/Config.java | 45 ++++++++++++----- .../videoautoplay/DefaultExoCreator.java | 35 ++++++------- .../videoautoplay/ExoCreator.java | 13 +++-- .../videoautoplay/ExoPlayable.java | 33 ++++++------ .../videoautoplay/ExoPlayerViewHelper.java | 18 +++++-- .../videoautoplay/MediaSourceBuilder.java | 37 ++++++++------ .../infinityforreddit/videoautoplay/Playable.java | 59 ++++++++++++---------- .../videoautoplay/PlayableImpl.java | 22 ++++---- .../infinityforreddit/videoautoplay/ToroExo.java | 23 +++++---- .../videoautoplay/ToroExoPlayer.java | 21 ++++---- .../videoautoplay/helper/ToroPlayerHelper.java | 2 +- app/src/main/res/layout/activity_post_video.xml | 2 +- app/src/main/res/layout/activity_view_video.xml | 2 +- .../res/layout/activity_view_video_zoomable.xml | 6 ++- .../layout/exo_autoplay_playback_control_view.xml | 2 +- .../exo_autoplay_playback_control_view_legacy.xml | 2 +- .../main/res/layout/exo_playback_control_view.xml | 2 +- .../main/res/layout/fragment_view_imgur_video.xml | 2 +- .../layout/fragment_view_reddit_gallery_video.xml | 2 +- .../res/layout/item_post_card_2_video_autoplay.xml | 6 +-- ...ost_card_2_video_autoplay_legacy_controller.xml | 6 +-- .../item_post_card_3_video_type_autoplay.xml | 6 +-- ...ard_3_video_type_autoplay_legacy_controller.xml | 6 +-- .../res/layout/item_post_detail_video_autoplay.xml | 6 +-- ...ost_detail_video_autoplay_legacy_controller.xml | 6 +-- .../res/layout/item_post_video_type_autoplay.xml | 6 +-- ..._post_video_type_autoplay_legacy_controller.xml | 6 +-- app/src/main/res/values/styles.xml | 4 +- 41 files changed, 382 insertions(+), 291 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b23a2bb1..becaeb62 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,11 +85,11 @@ dependencies { /** ExoPlayer **/ def exoplayerVersion = "2.19.1" - implementation "com.google.android.exoplayer:exoplayer-core:$exoplayerVersion" - implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayerVersion" - implementation "com.google.android.exoplayer:exoplayer-hls:$exoplayerVersion" - implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayerVersion" - implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:$exoplayerVersion" + implementation "androidx.media3:media3-exoplayer:1.1.1" + implementation "androidx.media3:media3-exoplayer-dash:1.1.1" + implementation "androidx.media3:media3-exoplayer-hls:1.1.1" + implementation "androidx.media3:media3-ui:1.1.1" + implementation "androidx.media3:media3-exoplayer-smoothstreaming:1.1.1" /** Third-party **/ diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java index 44d4486f..a4b1276e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java @@ -4,12 +4,13 @@ import android.app.Application; import android.content.Context; import android.content.SharedPreferences; +import androidx.annotation.OptIn; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.database.StandaloneDatabaseProvider; +import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor; +import androidx.media3.datasource.cache.SimpleCache; import androidx.preference.PreferenceManager; -import com.google.android.exoplayer2.database.StandaloneDatabaseProvider; -import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor; -import com.google.android.exoplayer2.upstream.cache.SimpleCache; - import java.io.File; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -162,11 +163,13 @@ abstract class AppModule { return new File(appCache, "/exoplayer"); } + @OptIn(markerClass = UnstableApi.class) @Provides static StandaloneDatabaseProvider provideExoDatabaseProvider(Application application) { return new StandaloneDatabaseProvider(application); } + @OptIn(markerClass = UnstableApi.class) @Provides @Singleton static SimpleCache provideSimpleCache(StandaloneDatabaseProvider standaloneDatabaseProvider, @@ -176,6 +179,7 @@ abstract class AppModule { standaloneDatabaseProvider); } + @OptIn(markerClass = UnstableApi.class) @Provides static Config providesMediaConfig(Application application, SimpleCache simpleCache) { return new Config.Builder(application) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostVideoActivity.java index 3eb2fc42..692224b8 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostVideoActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/PostVideoActivity.java @@ -16,19 +16,21 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.OptIn; import androidx.core.content.ContextCompat; +import androidx.media3.common.MediaItem; +import androidx.media3.common.Player; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; +import androidx.media3.datasource.DataSource; +import androidx.media3.datasource.DefaultDataSourceFactory; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.source.ProgressiveMediaSource; import androidx.recyclerview.widget.LinearLayoutManager; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; import com.bumptech.glide.request.RequestOptions; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.util.Util; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; @@ -132,6 +134,7 @@ public class PostVideoActivity extends BaseActivity implements FlairBottomSheetF private ExoPlayer player; private ActivityPostVideoBinding binding; + @OptIn(markerClass = UnstableApi.class) @Override protected void onCreate(Bundle savedInstanceState) { ((Infinity) getApplication()).getAppComponent().inject(this); @@ -447,6 +450,7 @@ public class PostVideoActivity extends BaseActivity implements FlairBottomSheetF } } + @OptIn(markerClass = UnstableApi.class) private void loadVideo() { binding.selectVideoConstraintLayoutPostVideoActivity.setVisibility(View.GONE); binding.selectAgainTextViewPostVideoActivity.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java index 882801fa..e6aa4e3f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java @@ -32,6 +32,7 @@ import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.OptIn; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -43,29 +44,30 @@ import androidx.core.graphics.Insets; import androidx.core.view.OnApplyWindowInsetsListener; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import androidx.media3.common.C; +import androidx.media3.common.Format; +import androidx.media3.common.MediaItem; +import androidx.media3.common.MimeTypes; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.PlaybackParameters; +import androidx.media3.common.Player; +import androidx.media3.common.TrackSelectionOverride; +import androidx.media3.common.Tracks; +import androidx.media3.common.VideoSize; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; +import androidx.media3.datasource.DataSource; +import androidx.media3.datasource.DefaultHttpDataSource; +import androidx.media3.datasource.cache.CacheDataSource; +import androidx.media3.datasource.cache.SimpleCache; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.hls.HlsMediaSource; +import androidx.media3.exoplayer.source.ProgressiveMediaSource; +import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; +import androidx.media3.ui.PlayerControlView; +import androidx.media3.ui.PlayerView; +import androidx.media3.ui.TrackSelectionDialogBuilder; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.PlaybackException; -import com.google.android.exoplayer2.PlaybackParameters; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.Tracks; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverride; -import com.google.android.exoplayer2.ui.PlayerControlView; -import com.google.android.exoplayer2.ui.StyledPlayerView; -import com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; -import com.google.android.exoplayer2.upstream.cache.CacheDataSource; -import com.google.android.exoplayer2.upstream.cache.SimpleCache; -import com.google.android.exoplayer2.util.MimeTypes; -import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.VideoSize; import com.google.android.material.button.MaterialButton; import com.google.common.collect.ImmutableList; import com.otaliastudios.zoom.ZoomEngine; @@ -152,6 +154,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe private Uri mVideoUri; private ExoPlayer player; + @UnstableApi private DefaultTrackSelector trackSelector; private DataSource.Factory dataSourceFactory; @@ -202,9 +205,11 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe @Inject Executor mExecutor; + @UnstableApi @Inject SimpleCache mSimpleCache; + @OptIn(markerClass = UnstableApi.class) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -462,9 +467,9 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe } }); } else { - StyledPlayerView videoPlayerView = findViewById(R.id.player_view_view_video_activity); + PlayerView videoPlayerView = findViewById(R.id.player_view_view_video_activity); videoPlayerView.setPlayer(player); - videoPlayerView.setControllerVisibilityListener(new StyledPlayerView.ControllerVisibilityListener() { + videoPlayerView.setControllerVisibilityListener(new PlayerView.ControllerVisibilityListener() { @Override public void onVisibilityChanged(int visibility) { switch (visibility) { @@ -686,6 +691,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe playbackSpeedBottomSheetFragment.show(getSupportFragmentManager(), playbackSpeedBottomSheetFragment.getTag()); } + @OptIn(markerClass = UnstableApi.class) private int inferPrimaryTrackType(Format format) { int trackType = MimeTypes.getTrackType(format.sampleMimeType); if (trackType != C.TRACK_TYPE_UNKNOWN) { @@ -710,6 +716,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe binding.getProgressBar().setVisibility(View.VISIBLE); FetchRedgifsVideoLinks.fetchRedgifsVideoLinks(mExecutor, new Handler(), mRedgifsRetrofit, mCurrentAccountSharedPreferences, redgifsId, new FetchRedgifsVideoLinks.FetchRedgifsVideoLinksListener() { + @OptIn(markerClass = UnstableApi.class) @Override public void success(String webm, String mp4) { binding.getProgressBar().setVisibility(View.GONE); @@ -742,6 +749,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe String postId = segments.get(commentsIndex + 1); FetchPost.fetchPost(mExecutor, new Handler(), mRetrofit, postId, null, Account.ANONYMOUS_ACCOUNT, new FetchPost.FetchPostListener() { + @OptIn(markerClass = UnstableApi.class) @Override public void fetchPostSuccess(Post post) { videoFallbackDirectUrl = post.getVideoFallBackDirectUrl(); @@ -807,6 +815,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe binding.getProgressBar().setVisibility(View.VISIBLE); FetchStreamableVideo.fetchStreamableVideo(mExecutor, new Handler(), mStreamableApiProvider, shortCode, new FetchStreamableVideo.FetchStreamableVideoListener() { + @OptIn(markerClass = UnstableApi.class) @Override public void success(StreamableVideo streamableVideo) { if (streamableVideo.mp4 == null && streamableVideo.mp4Mobile == null) { @@ -831,6 +840,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe }); } + @OptIn(markerClass = UnstableApi.class) private void loadFallbackVideo(Bundle savedInstanceState) { if (videoFallbackDirectUrl != null) { MediaItem mediaItem = player.getCurrentMediaItem(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/HistoryPostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/HistoryPostRecyclerViewAdapter.java index c219c5fa..b9e9b117 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/HistoryPostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/HistoryPostRecyclerViewAdapter.java @@ -25,12 +25,21 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.OptIn; import androidx.appcompat.content.res.AppCompatResources; import androidx.constraintlayout.widget.Barrier; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import androidx.core.content.ContextCompat; -import androidx.core.content.res.ResourcesCompat; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.Player; +import androidx.media3.common.Tracks; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; +import androidx.media3.ui.AspectRatioFrameLayout; +import androidx.media3.ui.DefaultTimeBar; +import androidx.media3.ui.PlayerView; +import androidx.media3.ui.TimeBar; import androidx.paging.PagingDataAdapter; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ItemTouchHelper; @@ -45,14 +54,6 @@ import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.Target; -import com.google.android.exoplayer2.PlaybackException; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.Tracks; -import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; -import com.google.android.exoplayer2.ui.DefaultTimeBar; -import com.google.android.exoplayer2.ui.StyledPlayerView; -import com.google.android.exoplayer2.ui.TimeBar; -import com.google.android.exoplayer2.util.Util; import com.google.android.material.button.MaterialButton; import com.google.common.collect.ImmutableList; import com.libRG.CustomTextView; @@ -491,6 +492,7 @@ public class HistoryPostRecyclerViewAdapter extends PagingDataAdapter fetchRedgifsOrStreamableVideoCall; AspectRatioFrameLayout aspectRatioFrameLayout; - StyledPlayerView playerView; + PlayerView playerView; GifImageView previewImageView; ImageView mErrorLoadingRedgifsImageView; ImageView muteButton; @@ -1628,7 +1634,7 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter { + binding.getPlayerView().setControllerVisibilityListener((PlayerView.ControllerVisibilityListener) visibility -> { switch (visibility) { case View.GONE: activity.getWindow().getDecorView().setSystemUiVisibility( diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragmentBindingAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragmentBindingAdapter.java index e00b6ff2..6132de78 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragmentBindingAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragmentBindingAdapter.java @@ -4,7 +4,8 @@ import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; -import com.google.android.exoplayer2.ui.StyledPlayerView; +import androidx.media3.ui.PlayerView; + import com.google.android.material.bottomappbar.BottomAppBar; import com.google.android.material.button.MaterialButton; @@ -35,7 +36,7 @@ class ViewRedditGalleryVideoFragmentBindingAdapter { return binding.getRoot(); } - StyledPlayerView getPlayerView() { + PlayerView getPlayerView() { return binding.playerViewViewRedditGalleryVideoFragment; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/BaseMeter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/BaseMeter.java index ba8c2974..cef19e03 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/BaseMeter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/BaseMeter.java @@ -20,12 +20,12 @@ import android.os.Handler; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.upstream.BandwidthMeter; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DataSpec; -import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.upstream.TransferListener; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.datasource.DataSource; +import androidx.media3.datasource.DataSpec; +import androidx.media3.datasource.TransferListener; +import androidx.media3.exoplayer.upstream.BandwidthMeter; +import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter; /** * Abstract the {@link DefaultBandwidthMeter}, provide a wider use. @@ -34,6 +34,7 @@ import com.google.android.exoplayer2.upstream.TransferListener; * @since 3.4.0 */ +@UnstableApi @SuppressWarnings("WeakerAccess") // public final class BaseMeter implements BandwidthMeter, TransferListener { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Config.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Config.java index 8513c4bf..361492d9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Config.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Config.java @@ -16,26 +16,27 @@ package ml.docilealligator.infinityforreddit.videoautoplay; -import static com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF; +import static androidx.media3.exoplayer.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF; import static ml.docilealligator.infinityforreddit.videoautoplay.ToroUtil.checkNotNull; import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.OptIn; import androidx.core.util.ObjectsCompat; - -import com.google.android.exoplayer2.DefaultLoadControl; -import com.google.android.exoplayer2.DefaultRenderersFactory.ExtensionRendererMode; -import com.google.android.exoplayer2.LoadControl; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.upstream.cache.Cache; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.datasource.DataSource; +import androidx.media3.datasource.cache.Cache; +import androidx.media3.exoplayer.DefaultLoadControl; +import androidx.media3.exoplayer.DefaultRenderersFactory; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.LoadControl; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter; /** - * Necessary configuration for {@link ExoCreator} to produces {@link SimpleExoPlayer} and + * Necessary configuration for {@link ExoCreator} to produces {@link ExoPlayer} and * {@link MediaSource}. Instance of this class must be construct using {@link Builder}. * * @author eneim (2018/01/23). @@ -49,19 +50,23 @@ public final class Config { private final Context context; // primitive flags - @ExtensionRendererMode final int extensionMode; + @DefaultRenderersFactory.ExtensionRendererMode + final int extensionMode; // NonNull options @NonNull final BaseMeter meter; + @UnstableApi @NonNull final LoadControl loadControl; @NonNull final MediaSourceBuilder mediaSourceBuilder; // Nullable options + @UnstableApi @Nullable final Cache cache; // null by default // If null, ExoCreator must come up with a default one. // This is to help customizing the Data source, for example using OkHttp extension. @Nullable final DataSource.Factory dataSourceFactory; + @OptIn(markerClass = UnstableApi.class) @SuppressWarnings("WeakerAccess") // Config(@Nullable Context context, int extensionMode, @NonNull BaseMeter meter, @NonNull LoadControl loadControl, @@ -77,6 +82,7 @@ public final class Config { this.cache = cache; } + @OptIn(markerClass = UnstableApi.class) @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -91,6 +97,7 @@ public final class Config { return ObjectsCompat.equals(dataSourceFactory, config.dataSourceFactory); } + @OptIn(markerClass = UnstableApi.class) @Override public int hashCode() { int result = extensionMode; result = 31 * result + meter.hashCode(); @@ -101,6 +108,7 @@ public final class Config { return result; } + @OptIn(markerClass = UnstableApi.class) @SuppressWarnings("unused") public Builder newBuilder() { return new Builder(context).setCache(this.cache) .setExtensionMode(this.extensionMode) @@ -124,6 +132,7 @@ public final class Config { this(null); } + @OptIn(markerClass = UnstableApi.class) public Builder(@Nullable Context context) { this.context = context != null ? context.getApplicationContext() : null; DefaultBandwidthMeter bandwidthMeter = @@ -131,14 +140,19 @@ public final class Config { meter = new BaseMeter<>(bandwidthMeter); } - @ExtensionRendererMode private int extensionMode = EXTENSION_RENDERER_MODE_OFF; + @UnstableApi + @DefaultRenderersFactory.ExtensionRendererMode + private int extensionMode = EXTENSION_RENDERER_MODE_OFF; private BaseMeter meter; + @UnstableApi private LoadControl loadControl = new DefaultLoadControl(); private DataSource.Factory dataSourceFactory = null; private MediaSourceBuilder mediaSourceBuilder = MediaSourceBuilder.DEFAULT; + @UnstableApi private Cache cache = null; - public Builder setExtensionMode(@ExtensionRendererMode int extensionMode) { + @OptIn(markerClass = UnstableApi.class) + public Builder setExtensionMode(@DefaultRenderersFactory.ExtensionRendererMode int extensionMode) { this.extensionMode = extensionMode; return this; } @@ -148,6 +162,7 @@ public final class Config { return this; } + @OptIn(markerClass = UnstableApi.class) public Builder setLoadControl(@NonNull LoadControl loadControl) { this.loadControl = checkNotNull(loadControl, "Need non-null LoadControl"); return this; @@ -165,11 +180,13 @@ public final class Config { return this; } + @OptIn(markerClass = UnstableApi.class) public Builder setCache(@Nullable Cache cache) { this.cache = cache; return this; } + @OptIn(markerClass = UnstableApi.class) public Config build() { return new Config(context, extensionMode, meter, loadControl, dataSourceFactory, mediaSourceBuilder, cache); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/DefaultExoCreator.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/DefaultExoCreator.java index 89ebe5eb..b86a67e4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/DefaultExoCreator.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/DefaultExoCreator.java @@ -25,23 +25,23 @@ import android.os.Handler; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.DefaultRenderersFactory; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.LoadControl; -import com.google.android.exoplayer2.RenderersFactory; -import com.google.android.exoplayer2.source.LoadEventInfo; -import com.google.android.exoplayer2.source.MediaLoadData; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.MediaSourceEventListener; -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelector; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.upstream.DefaultDataSource; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; -import com.google.android.exoplayer2.upstream.cache.CacheDataSource; -import com.google.android.exoplayer2.util.Util; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; +import androidx.media3.datasource.DataSource; +import androidx.media3.datasource.DefaultDataSource; +import androidx.media3.datasource.DefaultHttpDataSource; +import androidx.media3.datasource.cache.CacheDataSource; +import androidx.media3.exoplayer.DefaultRenderersFactory; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.LoadControl; +import androidx.media3.exoplayer.RenderersFactory; +import androidx.media3.exoplayer.source.LoadEventInfo; +import androidx.media3.exoplayer.source.MediaLoadData; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.source.MediaSourceEventListener; +import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; +import androidx.media3.exoplayer.trackselection.TrackSelector; +import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter; import java.io.IOException; @@ -54,6 +54,7 @@ import ml.docilealligator.infinityforreddit.utils.APIUtils; * @since 3.4.0 */ +@UnstableApi @SuppressWarnings({"unused", "WeakerAccess"}) // public class DefaultExoCreator implements ExoCreator, MediaSourceEventListener { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoCreator.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoCreator.java index d639c9d3..1067298f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoCreator.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoCreator.java @@ -21,13 +21,12 @@ import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.source.MediaSource; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.source.MediaSource; /** - * A simple interface whose implementation helps Client to easily create {@link SimpleExoPlayer} + * A simple interface whose implementation helps Client to easily create {@link ExoPlayer} * instance, {@link MediaSource} instance or specifically a {@link Playable} instance. * * Most of the time, Client just needs to request for a {@link Playable} for a specific Uri. @@ -47,11 +46,11 @@ public interface ExoCreator { @Nullable Context getContext(); /** - * Create a new {@link SimpleExoPlayer} instance. This method should always create new instance of - * {@link SimpleExoPlayer}, but client should use {@link ExoCreator} indirectly via + * Create a new {@link ExoPlayer} instance. This method should always create new instance of + * {@link ExoPlayer}, but client should use {@link ExoCreator} indirectly via * {@link ToroExo}. * - * @return a new {@link SimpleExoPlayer} instance. + * @return a new {@link ExoPlayer} instance. */ @NonNull ExoPlayer createPlayer(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayable.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayable.java index 33410904..6b67d69f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayable.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayable.java @@ -16,7 +16,7 @@ package ml.docilealligator.infinityforreddit.videoautoplay; -import static com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS; +import static androidx.media3.exoplayer.trackselection.MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS; import static ml.docilealligator.infinityforreddit.videoautoplay.ToroExo.toro; import android.net.Uri; @@ -24,18 +24,20 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.OptIn; +import androidx.media3.common.C; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.Player; +import androidx.media3.common.Tracks; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.ExoPlaybackException; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.source.BehindLiveWindowException; +import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; +import androidx.media3.exoplayer.trackselection.MappingTrackSelector; +import androidx.media3.exoplayer.trackselection.TrackSelector; +import androidx.media3.ui.PlayerView; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; -import com.google.android.exoplayer2.PlaybackException; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.Tracks; -import com.google.android.exoplayer2.source.BehindLiveWindowException; -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; -import com.google.android.exoplayer2.trackselection.TrackSelector; -import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.common.collect.ImmutableList; import ml.docilealligator.infinityforreddit.R; @@ -48,6 +50,7 @@ import ml.docilealligator.infinityforreddit.R; * @since 3.4.0 */ +@OptIn(markerClass = UnstableApi.class) @SuppressWarnings("WeakerAccess") public class ExoPlayable extends PlayableImpl { @@ -62,7 +65,7 @@ public class ExoPlayable extends PlayableImpl { /** * Construct an instance of {@link ExoPlayable} from an {@link ExoCreator} and {@link Uri}. The - * {@link ExoCreator} is used to request {@link SimpleExoPlayer} instance, while {@link Uri} + * {@link ExoCreator} is used to request {@link ExoPlayer} instance, while {@link Uri} * defines the media to play. * * @param creator the {@link ExoCreator} instance. @@ -85,7 +88,7 @@ public class ExoPlayable extends PlayableImpl { } @Override - public void setPlayerView(@Nullable StyledPlayerView playerView) { + public void setPlayerView(@Nullable PlayerView playerView) { // This will also clear these flags if (playerView != this.playerView) { this.lastSeenTrackGroupArray = null; @@ -132,7 +135,7 @@ public class ExoPlayable extends PlayableImpl { if (!(creator instanceof DefaultExoCreator)) return; TrackSelector selector = ((DefaultExoCreator) creator).getTrackSelector(); if (selector instanceof DefaultTrackSelector) { - MappedTrackInfo trackInfo = ((DefaultTrackSelector) selector).getCurrentMappedTrackInfo(); + MappingTrackSelector.MappedTrackInfo trackInfo = ((DefaultTrackSelector) selector).getCurrentMappedTrackInfo(); if (trackInfo != null) { if (trackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO) == RENDERER_SUPPORT_UNSUPPORTED_TRACKS) { onErrorMessage(toro.getString(R.string.error_unsupported_video)); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayerViewHelper.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayerViewHelper.java index 81b2dbbf..478b7b0e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayerViewHelper.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ExoPlayerViewHelper.java @@ -23,9 +23,10 @@ import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.ui.StyledPlayerView; +import androidx.annotation.OptIn; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.ui.PlayerView; import ml.docilealligator.infinityforreddit.videoautoplay.annotations.RemoveIn; import ml.docilealligator.infinityforreddit.videoautoplay.helper.ToroPlayerHelper; @@ -44,6 +45,7 @@ import ml.docilealligator.infinityforreddit.videoautoplay.widget.Container; public class ExoPlayerViewHelper extends ToroPlayerHelper { @NonNull private final ExoPlayable playable; + @UnstableApi @NonNull private final MyEventListeners listeners; private final boolean lazyPrepare; @@ -74,10 +76,11 @@ public class ExoPlayerViewHelper extends ToroPlayerHelper { this(player, new ExoPlayable(creator, uri, fileExt)); } + @OptIn(markerClass = UnstableApi.class) public ExoPlayerViewHelper(@NonNull ToroPlayer player, @NonNull ExoPlayable playable) { super(player); //noinspection ConstantConditions - if (player.getPlayerView() == null || !(player.getPlayerView() instanceof StyledPlayerView)) { + if (player.getPlayerView() == null || !(player.getPlayerView() instanceof PlayerView)) { throw new IllegalArgumentException("Require non-null PlayerView"); } @@ -86,15 +89,17 @@ public class ExoPlayerViewHelper extends ToroPlayerHelper { this.lazyPrepare = true; } + @OptIn(markerClass = UnstableApi.class) @Override protected void initialize(@NonNull PlaybackInfo playbackInfo) { playable.setPlaybackInfo(playbackInfo); playable.addEventListener(listeners); playable.addErrorListener(super.getErrorListeners()); playable.addOnVolumeChangeListener(super.getVolumeChangeListeners()); playable.prepare(!lazyPrepare); - playable.setPlayerView((StyledPlayerView) player.getPlayerView()); + playable.setPlayerView((PlayerView) player.getPlayerView()); } + @OptIn(markerClass = UnstableApi.class) @Override public void release() { super.release(); playable.setPlayerView(null); @@ -140,16 +145,19 @@ public class ExoPlayerViewHelper extends ToroPlayerHelper { this.playable.setPlaybackInfo(playbackInfo); } + @OptIn(markerClass = UnstableApi.class) public void addEventListener(@NonNull Playable.EventListener listener) { //noinspection ConstantConditions if (listener != null) this.listeners.add(listener); } + @OptIn(markerClass = UnstableApi.class) public void removeEventListener(Playable.EventListener listener) { this.listeners.remove(listener); } // A proxy, to also hook into ToroPlayerHelper's state change event. + @UnstableApi private class MyEventListeners extends Playable.EventListeners { MyEventListeners() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/MediaSourceBuilder.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/MediaSourceBuilder.java index d54798cf..a2bcd833 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/MediaSourceBuilder.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/MediaSourceBuilder.java @@ -17,7 +17,8 @@ package ml.docilealligator.infinityforreddit.videoautoplay; import static android.text.TextUtils.isEmpty; -import static com.google.android.exoplayer2.util.Util.inferContentType; + +import static androidx.media3.common.util.Util.inferContentType; import android.content.Context; import android.net.Uri; @@ -25,20 +26,21 @@ import android.os.Handler; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.C.ContentType; -import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.source.LoopingMediaSource; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.MediaSourceEventListener; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; -import com.google.android.exoplayer2.source.dash.DashMediaSource; -import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource; -import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; -import com.google.android.exoplayer2.upstream.DataSource; +import androidx.annotation.OptIn; +import androidx.media3.common.C; +import androidx.media3.common.C.ContentType; +import androidx.media3.common.MediaItem; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.dash.DashMediaSource; +import androidx.media3.exoplayer.dash.DefaultDashChunkSource; +import androidx.media3.exoplayer.hls.HlsMediaSource; +import androidx.media3.exoplayer.smoothstreaming.DefaultSsChunkSource; +import androidx.media3.exoplayer.smoothstreaming.SsMediaSource; +import androidx.media3.exoplayer.source.LoopingMediaSource; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.source.MediaSourceEventListener; +import androidx.media3.exoplayer.source.ProgressiveMediaSource; /** * @author eneim (2018/01/24). @@ -47,6 +49,7 @@ import com.google.android.exoplayer2.upstream.DataSource; public interface MediaSourceBuilder { + @OptIn(markerClass = UnstableApi.class) @NonNull MediaSource buildMediaSource(@NonNull Context context, @NonNull Uri uri, @Nullable String fileExt, @Nullable Handler handler, @@ -55,13 +58,14 @@ public interface MediaSourceBuilder { @Nullable MediaSourceEventListener listener); MediaSourceBuilder DEFAULT = new MediaSourceBuilder() { + @OptIn(markerClass = UnstableApi.class) @NonNull @Override public MediaSource buildMediaSource(@NonNull Context context, @NonNull Uri uri, @Nullable String ext, @Nullable Handler handler, @NonNull DataSource.Factory manifestDataSourceFactory, @NonNull DataSource.Factory mediaDataSourceFactory, MediaSourceEventListener listener) { - @ContentType int type = isEmpty(ext) ? inferContentType(uri) : inferContentType("." + ext); + @ContentType int type = isEmpty(ext) ? inferContentType(uri) : inferContentType(Uri.parse("." + ext)); MediaSource result; switch (type) { case C.CONTENT_TYPE_SS: @@ -93,6 +97,7 @@ public interface MediaSourceBuilder { MediaSourceBuilder LOOPING = new MediaSourceBuilder() { + @OptIn(markerClass = UnstableApi.class) @NonNull @Override public MediaSource buildMediaSource(@NonNull Context context, @NonNull Uri uri, diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Playable.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Playable.java index 035a3b09..384277a3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Playable.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/Playable.java @@ -19,21 +19,21 @@ package ml.docilealligator.infinityforreddit.videoautoplay; import androidx.annotation.FloatRange; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.PlaybackException; -import com.google.android.exoplayer2.PlaybackParameters; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.Tracks; -import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.MetadataOutput; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.text.Cue; -import com.google.android.exoplayer2.text.CueGroup; -import com.google.android.exoplayer2.text.TextOutput; -import com.google.android.exoplayer2.ui.StyledPlayerView; -import com.google.android.exoplayer2.video.VideoSize; +import androidx.media3.common.Metadata; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.PlaybackParameters; +import androidx.media3.common.Player; +import androidx.media3.common.Timeline; +import androidx.media3.common.Tracks; +import androidx.media3.common.VideoSize; +import androidx.media3.common.text.Cue; +import androidx.media3.common.text.CueGroup; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.metadata.MetadataOutput; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.text.TextOutput; +import androidx.media3.ui.PlayerView; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; @@ -43,7 +43,7 @@ import ml.docilealligator.infinityforreddit.videoautoplay.media.PlaybackInfo; import ml.docilealligator.infinityforreddit.videoautoplay.media.VolumeInfo; /** - * Define an interface to control a playback, specific for {@link SimpleExoPlayer} and {@link StyledPlayerView}. + * Define an interface to control a playback, specific for {@link ExoPlayer} and {@link PlayerView}. *

* This interface is designed to be reused across Config change. Implementation must not hold any * strong reference to Activity, and if it supports any kind of that, make sure to implicitly clean @@ -57,13 +57,13 @@ import ml.docilealligator.infinityforreddit.videoautoplay.media.VolumeInfo; public interface Playable { /** - * Prepare the resource for a {@link SimpleExoPlayer}. This method should: - * - Request for new {@link SimpleExoPlayer} instance if there is not a usable one. + * Prepare the resource for a {@link ExoPlayer}. This method should: + * - Request for new {@link ExoPlayer} instance if there is not a usable one. * - Configure {@link EventListener} for it. - * - If there is non-trivial PlaybackInfo, update it to the SimpleExoPlayer. + * - If there is non-trivial PlaybackInfo, update it to the ExoPlayer. * - If client request to prepare MediaSource, then prepare it. *

- * This method must be called before {@link #setPlayerView(com.google.android.exoplayer2.ui.StyledPlayerView)}. + * This method must be called before {@link #setPlayerView(PlayerView)}. * * @param prepareSource if {@code true}, also prepare the MediaSource when preparing the Player, * if {@code false} just do nothing for the MediaSource. @@ -71,24 +71,24 @@ public interface Playable { void prepare(boolean prepareSource); /** - * Set the {@link StyledPlayerView} for this Playable. It is expected that a playback doesn't require a - * UI, so this setup is optional. But it must be called after the SimpleExoPlayer is prepared, + * Set the {@link PlayerView} for this Playable. It is expected that a playback doesn't require a + * UI, so this setup is optional. But it must be called after the ExoPlayer is prepared, * that is after {@link #prepare(boolean)} and before {@link #release()}. *

* Changing the PlayerView during playback is expected, though not always recommended, especially * on old Devices with low Android API. * - * @param playerView the PlayerView to set to the SimpleExoPlayer. + * @param playerView the PlayerView to set to the ExoPlayer. */ - void setPlayerView(@Nullable StyledPlayerView playerView); + void setPlayerView(@Nullable PlayerView playerView); /** - * Get current {@link StyledPlayerView} of this Playable. + * Get current {@link PlayerView} of this Playable. * * @return current PlayerView instance of this Playable. */ @Nullable - StyledPlayerView getPlayerView(); + PlayerView getPlayerView(); /** * Start the playback. If the {@link MediaSource} is not prepared, then also prepare it. @@ -102,13 +102,13 @@ public interface Playable { /** * Reset all resource, so that the playback can start all over again. This is to cleanup the - * playback for reuse. The SimpleExoPlayer instance must be still usable without calling + * playback for reuse. The ExoPlayer instance must be still usable without calling * {@link #prepare(boolean)}. */ void reset(); /** - * Release all resource. After this, the SimpleExoPlayer is released to the Player pool and the + * Release all resource. After this, the ExoPlayer is released to the Player pool and the * Playable must call {@link #prepare(boolean)} again to use it again. */ void release(); @@ -210,6 +210,7 @@ public interface Playable { void removeErrorListener(@Nullable ToroPlayer.OnErrorListener listener); // Combine necessary interfaces. + @UnstableApi interface EventListener extends Player.Listener, TextOutput, MetadataOutput { @Override @@ -231,6 +232,7 @@ public interface Playable { /** * Default empty implementation */ + @UnstableApi class DefaultEventListener implements EventListener { @Override public void onTimelineChanged(@NonNull Timeline timeline, int reason) { @@ -301,6 +303,7 @@ public interface Playable { /** * List of EventListener */ + @UnstableApi class EventListeners extends CopyOnWriteArraySet implements EventListener { EventListeners() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/PlayableImpl.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/PlayableImpl.java index f9f26962..07c50f9a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/PlayableImpl.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/PlayableImpl.java @@ -26,12 +26,13 @@ import android.net.Uri; import androidx.annotation.CallSuper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.PlaybackParameters; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.ui.StyledPlayerView; +import androidx.annotation.OptIn; +import androidx.media3.common.C; +import androidx.media3.common.PlaybackParameters; +import androidx.media3.common.Player; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.ui.PlayerView; import ml.docilealligator.infinityforreddit.videoautoplay.media.PlaybackInfo; import ml.docilealligator.infinityforreddit.videoautoplay.media.VolumeInfo; @@ -47,6 +48,7 @@ import ml.docilealligator.infinityforreddit.videoautoplay.media.VolumeInfo; * @author eneim (2018/02/25). */ @SuppressWarnings("WeakerAccess") // +@OptIn(markerClass = UnstableApi.class) class PlayableImpl implements Playable { private final PlaybackInfo playbackInfo = new PlaybackInfo(); // never expose to outside. @@ -61,7 +63,7 @@ class PlayableImpl implements Playable { protected ToroExoPlayer player; // on-demand, cached protected MediaSource mediaSource; // on-demand, since we do not reuse MediaSource now. - protected StyledPlayerView playerView; // on-demand, not always required. + protected PlayerView playerView; // on-demand, not always required. private boolean sourcePrepared = false; private boolean listenerApplied = false; @@ -83,13 +85,13 @@ class PlayableImpl implements Playable { @CallSuper @Override - public void setPlayerView(@Nullable StyledPlayerView playerView) { + public void setPlayerView(@Nullable PlayerView playerView) { if (this.playerView == playerView) return; if (playerView == null) { this.playerView.setPlayer(null); } else { if (this.player != null) { - StyledPlayerView.switchTargetView(this.player.getPlayer(), this.playerView, playerView); + PlayerView.switchTargetView(this.player.getPlayer(), this.playerView, playerView); } } @@ -97,7 +99,7 @@ class PlayableImpl implements Playable { } @Override - public final StyledPlayerView getPlayerView() { + public final PlayerView getPlayerView() { return this.playerView; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExo.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExo.java index 1682658e..43dbbb1e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExo.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExo.java @@ -25,13 +25,13 @@ import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.OptIn; import androidx.annotation.RestrictTo; import androidx.annotation.StringRes; import androidx.core.util.Pools; - -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.util.Util; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; +import androidx.media3.exoplayer.ExoPlayer; import java.net.CookieHandler; import java.net.CookieManager; @@ -44,8 +44,8 @@ import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.videoautoplay.media.VolumeInfo; /** - * Global helper class to manage {@link ExoCreator} and {@link SimpleExoPlayer} instances. - * In this setup, {@link ExoCreator} and SimpleExoPlayer pools are cached. A {@link Config} + * Global helper class to manage {@link ExoCreator} and {@link ExoPlayer} instances. + * In this setup, {@link ExoCreator} and ExoPlayer pools are cached. A {@link Config} * is a key for each {@link ExoCreator}. *

* A suggested usage is as below: @@ -65,6 +65,7 @@ public final class ToroExo { private static final String TAG = "ToroExo"; // Magic number: Build.VERSION.SDK_INT / 6 --> API 16 ~ 18 will set pool size to 2, etc. + @UnstableApi @SuppressWarnings("WeakerAccess") // static final int MAX_POOL_SIZE = Math.max(Util.SDK_INT / 6, getRuntime().availableProcessors()); @SuppressLint("StaticFieldLeak") // @@ -107,6 +108,7 @@ public final class ToroExo { /** * Utility method to produce {@link ExoCreator} instance from a {@link Config}. */ + @OptIn(markerClass = UnstableApi.class) public ExoCreator getCreator(Config config) { ExoCreator creator = this.creators.get(config); if (creator == null) { @@ -131,14 +133,14 @@ public final class ToroExo { } /** - * Request an instance of {@link SimpleExoPlayer}. It can be an existing instance cached by Pool + * Request an instance of {@link ExoPlayer}. It can be an existing instance cached by Pool * or new one. *

* The creator may or may not be the one created by either {@link #getCreator(Config)} or * {@link #getDefaultCreator()}. * - * @param creator the {@link ExoCreator} that is scoped to the {@link SimpleExoPlayer} config. - * @return an usable {@link SimpleExoPlayer} instance. + * @param creator the {@link ExoCreator} that is scoped to the {@link ExoPlayer} config. + * @return an usable {@link ExoPlayer} instance. */ @NonNull // public ToroExoPlayer requestPlayer(@NonNull ExoCreator creator) { @@ -151,7 +153,7 @@ public final class ToroExo { * Release player to Pool attached to the creator. * * @param creator the {@link ExoCreator} that created the player. - * @param player the {@link SimpleExoPlayer} to be released back to the Pool + * @param player the {@link ExoPlayer} to be released back to the Pool * @return true if player is released to relevant Pool, false otherwise. */ @SuppressWarnings({"WeakerAccess", "UnusedReturnValue"}) // @@ -175,6 +177,7 @@ public final class ToroExo { } /// internal APIs + @OptIn(markerClass = UnstableApi.class) private Pools.Pool getPool(ExoCreator creator) { Pools.Pool pool = playerPools.get(creator); if (pool == null) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExoPlayer.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExoPlayer.java index 39be12c3..c1e4efff 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExoPlayer.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/ToroExoPlayer.java @@ -23,18 +23,18 @@ import android.os.Looper; import androidx.annotation.CallSuper; import androidx.annotation.NonNull; - -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.LoadControl; -import com.google.android.exoplayer2.RenderersFactory; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.trackselection.TrackSelector; -import com.google.android.exoplayer2.upstream.BandwidthMeter; +import androidx.annotation.OptIn; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.LoadControl; +import androidx.media3.exoplayer.RenderersFactory; +import androidx.media3.exoplayer.trackselection.TrackSelector; +import androidx.media3.exoplayer.upstream.BandwidthMeter; import ml.docilealligator.infinityforreddit.videoautoplay.media.VolumeInfo; /** - * A custom {@link SimpleExoPlayer} that also notify the change of Volume. + * A custom {@link ExoPlayer} that also notify the change of Volume. * * @author eneim (2018/03/27). */ @@ -43,9 +43,10 @@ public class ToroExoPlayer { private final ExoPlayer player; + @OptIn(markerClass = UnstableApi.class) public ToroExoPlayer(Context context, RenderersFactory renderersFactory, - TrackSelector trackSelector, LoadControl loadControl, BandwidthMeter bandwidthMeter, - Looper looper) { + TrackSelector trackSelector, LoadControl loadControl, BandwidthMeter bandwidthMeter, + Looper looper) { player = new ExoPlayer.Builder(context).setRenderersFactory(renderersFactory).setTrackSelector(trackSelector).setLoadControl(loadControl).setBandwidthMeter(bandwidthMeter).setLooper(looper).build(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/helper/ToroPlayerHelper.java b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/helper/ToroPlayerHelper.java index 7f2aa825..d44c9147 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/helper/ToroPlayerHelper.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/videoautoplay/helper/ToroPlayerHelper.java @@ -143,7 +143,7 @@ public abstract class ToroPlayerHelper { /** * Initialize the necessary resource for the incoming playback. For example, prepare the - * ExoPlayer instance for SimpleExoPlayerView. The initialization is feed by an initial playback + * ExoPlayer instance for ExoPlayerView. The initialization is feed by an initial playback * info, telling if the playback should start from a specific position or from beginning. * * Normally this info can be obtained from cache if there is cache manager, or {@link PlaybackInfo#SCRAP} diff --git a/app/src/main/res/layout/activity_post_video.xml b/app/src/main/res/layout/activity_post_video.xml index 3dcde6b8..9171b0ec 100644 --- a/app/src/main/res/layout/activity_post_video.xml +++ b/app/src/main/res/layout/activity_post_video.xml @@ -266,7 +266,7 @@ android:fontFamily="?attr/font_family" android:visibility="gone" /> - - - + android:animateLayoutChanges="true" + app:controller_layout_id="@layout/exo_playback_control_view" + app:animation_enabled="false" /> - - diff --git a/app/src/main/res/layout/exo_playback_control_view.xml b/app/src/main/res/layout/exo_playback_control_view.xml index d4b5dba5..3f0fa176 100644 --- a/app/src/main/res/layout/exo_playback_control_view.xml +++ b/app/src/main/res/layout/exo_playback_control_view.xml @@ -128,7 +128,7 @@ android:textColor="#FFFFFF" android:fontFamily="?attr/font_family" /> - - - - - - + diff --git a/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml b/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml index 552e6180..08110054 100644 --- a/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml +++ b/app/src/main/res/layout/item_post_card_2_video_autoplay_legacy_controller.xml @@ -19,14 +19,14 @@ app:cardCornerRadius="8dp" style="?attr/materialCardViewElevatedStyle"> - - - + diff --git a/app/src/main/res/layout/item_post_card_3_video_type_autoplay.xml b/app/src/main/res/layout/item_post_card_3_video_type_autoplay.xml index 472dffda..5001a3ed 100644 --- a/app/src/main/res/layout/item_post_card_3_video_type_autoplay.xml +++ b/app/src/main/res/layout/item_post_card_3_video_type_autoplay.xml @@ -17,14 +17,14 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - + - - - + - - - + - - - + - - - + - - - + -- cgit v1.2.3