Proxy support for Media3.

This commit is contained in:
Docile-Alligator
2025-04-19 10:40:22 -04:00
parent d505e05848
commit 11be143e9d
6 changed files with 74 additions and 7 deletions

View File

@ -92,6 +92,7 @@ dependencies {
implementation "androidx.media3:media3-exoplayer-hls:$media3_version"
implementation "androidx.media3:media3-ui:$media3_version"
implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version"
implementation "androidx.media3:media3-datasource-okhttp:$media3_version"
/** Third-party **/

View File

@ -9,6 +9,7 @@ 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.media3.datasource.okhttp.OkHttpDataSource;
import androidx.preference.PreferenceManager;
import java.io.File;
@ -23,12 +24,14 @@ import dagger.Module;
import dagger.Provides;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LoopAvailableExoCreator;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.CustomThemeSharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.videoautoplay.Config;
import ml.docilealligator.infinityforreddit.videoautoplay.ExoCreator;
import ml.docilealligator.infinityforreddit.videoautoplay.MediaSourceBuilder;
import ml.docilealligator.infinityforreddit.videoautoplay.ToroExo;
import okhttp3.OkHttpClient;
@Module
abstract class AppModule {
@ -188,13 +191,15 @@ abstract class AppModule {
@OptIn(markerClass = UnstableApi.class)
@Provides
static Config providesMediaConfig(Application application, SimpleCache simpleCache) {
static Config providesMediaConfig(Application application, SimpleCache simpleCache, @Named("media3")OkHttpClient okHttpClient) {
return new Config.Builder(application)
.setDataSourceFactory(new OkHttpDataSource.Factory(okHttpClient).setUserAgent(APIUtils.USER_AGENT))
.setMediaSourceBuilder(MediaSourceBuilder.DEFAULT)
.setCache(simpleCache)
.build();
}
@OptIn(markerClass = UnstableApi.class)
@Provides
static ToroExo providesToroExo(Application application) {
return ToroExo.with(application);

View File

@ -2,6 +2,9 @@ package ml.docilealligator.infinityforreddit;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;
@ -19,8 +22,11 @@ import ml.docilealligator.infinityforreddit.network.SortTypeConverterFactory;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import okhttp3.ConnectionPool;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.guava.GuavaCallAdapterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
@ -113,6 +119,48 @@ abstract class NetworkModule {
.build();
}
@Provides
@Named("media3")
@Singleton
static OkHttpClient provideMedia3OkHttpClient(@Named("base") OkHttpClient httpClient,
ConnectionPool connectionPool) {
return httpClient.newBuilder()
.connectionPool(connectionPool)
.followRedirects(false)
.addInterceptor(new Interceptor() {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
int redirectCount = 0;
while (isRedirect(response.code()) && redirectCount < 5) {
String location = response.header("Location");
if (location == null) break;
HttpUrl newUrl = response.request().url().resolve(location);
if (newUrl == null) break;
request = request.newBuilder()
.url(newUrl)
.build();
response.close(); // Close the previous response before continuing
response = chain.proceed(request);
redirectCount++;
}
return response;
}
private boolean isRedirect(int code) {
return code == 301 || code == 302 || code == 303 || code == 307 || code == 308;
}
})
.build();
}
@Provides
@Named("oauth_without_authenticator")
@Singleton

View File

@ -63,9 +63,9 @@ 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.datasource.okhttp.OkHttpDataSource;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.hls.HlsMediaSource;
@ -112,6 +112,7 @@ import ml.docilealligator.infinityforreddit.thing.StreamableVideo;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
public class ViewVideoActivity extends AppCompatActivity implements CustomFontReceiver {
@ -179,6 +180,10 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
private boolean useBottomAppBar;
private ViewVideoActivityBindingAdapter binding;
@Inject
@Named("media3")
OkHttpClient mOkHttpClient;
@Inject
@Named("no_oauth")
Retrofit mRetrofit;
@ -654,7 +659,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
// Produces DataSource instances through which media data is loaded.
dataSourceFactory = new CacheDataSource.Factory().setCache(mSimpleCache)
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true).setUserAgent(APIUtils.USER_AGENT));
.setUpstreamDataSourceFactory(new OkHttpDataSource.Factory(mOkHttpClient).setUserAgent(APIUtils.USER_AGENT));
String redgifsId = null;
if (videoType == VIDEO_TYPE_STREAMABLE) {
if (savedInstanceState != null) {

View File

@ -32,9 +32,9 @@ import androidx.media3.common.Tracks;
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.datasource.okhttp.OkHttpDataSource;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
@ -58,6 +58,7 @@ import ml.docilealligator.infinityforreddit.services.DownloadMediaService;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import okhttp3.OkHttpClient;
public class ViewImgurVideoFragment extends Fragment {
@ -78,6 +79,9 @@ public class ViewImgurVideoFragment extends Fragment {
private boolean isDownloading = false;
private int playbackSpeed = 100;
@Inject
@Named("media3")
OkHttpClient mOkHttpClient;
@Inject
@Named("default")
SharedPreferences mSharedPreferences;
@UnstableApi
@ -153,7 +157,7 @@ public class ViewImgurVideoFragment extends Fragment {
.build();
binding.getRoot().setPlayer(player);
dataSourceFactory = new CacheDataSource.Factory().setCache(mSimpleCache)
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true).setUserAgent(APIUtils.USER_AGENT));
.setUpstreamDataSourceFactory(new OkHttpDataSource.Factory(mOkHttpClient).setUserAgent(APIUtils.USER_AGENT));
player.prepare();
player.setMediaSource(new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(imgurMedia.getLink())));

View File

@ -33,9 +33,9 @@ import androidx.media3.common.Tracks;
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.datasource.okhttp.OkHttpDataSource;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
@ -58,6 +58,7 @@ import ml.docilealligator.infinityforreddit.services.DownloadMediaService;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import okhttp3.OkHttpClient;
public class ViewRedditGalleryVideoFragment extends Fragment {
@ -82,6 +83,9 @@ public class ViewRedditGalleryVideoFragment extends Fragment {
private boolean isDownloading = false;
private int playbackSpeed = 100;
@Inject
@Named("media3")
OkHttpClient mOkHttpClient;
@Inject
@Named("default")
SharedPreferences mSharedPreferences;
@UnstableApi
@ -156,7 +160,7 @@ public class ViewRedditGalleryVideoFragment extends Fragment {
.build();
binding.getPlayerView().setPlayer(player);
dataSourceFactory = new CacheDataSource.Factory().setCache(mSimpleCache)
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true).setUserAgent(APIUtils.USER_AGENT));
.setUpstreamDataSourceFactory(new OkHttpDataSource.Factory(mOkHttpClient).setUserAgent(APIUtils.USER_AGENT));
player.prepare();
player.setMediaSource(new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(galleryVideo.url)));