Commit 953db789 by tonihei Committed by Oliver Woodman

Make dependency on AndroidX appcompat optional for dialog builder.

The dependency is only used to create a dialog in
TrackSelectionDialogBuilder that is compatible with newer styling
options.

This dependendy adds over 500Kb to the apk (even if unused) and we
shoudn't force this on an app. Instead make the dependency optional by
automatically falling back to the platform version if the AndroidX one
doesn't exist.

Issue: #7357
PiperOrigin-RevId: 322143005
parent ee222f70
...@@ -19,7 +19,6 @@ dependencies { ...@@ -19,7 +19,6 @@ dependencies {
implementation project(modulePrefix + 'library-core') implementation project(modulePrefix + 'library-core')
api 'androidx.media:media:' + androidxMediaVersion api 'androidx.media:media:' + androidxMediaVersion
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion
implementation 'androidx.recyclerview:recyclerview:' + androidxRecyclerViewVersion implementation 'androidx.recyclerview:recyclerview:' + androidxRecyclerViewVersion
implementation 'com.google.guava:guava:' + guavaVersion implementation 'com.google.guava:guava:' + guavaVersion
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
......
# Proguard rules specific to the UI module.
# Constructor method accessed via reflection in TrackSelectionDialogBuilder
-dontnote androidx.appcompat.app.AlertDialog.Builder
-keepclassmembers class androidx.appcompat.app.AlertDialog$Builder {
<init>(android.content.Context);
public android.content.Context getContext();
public androidx.appcompat.app.AlertDialog$Builder setTitle(java.lang.CharSequence);
public androidx.appcompat.app.AlertDialog$Builder setView(android.view.View);
public androidx.appcompat.app.AlertDialog$Builder setPositiveButton(int, android.content.DialogInterface$OnClickListener);
public androidx.appcompat.app.AlertDialog$Builder setNegativeButton(int, android.content.DialogInterface$OnClickListener);
public androidx.appcompat.app.AlertDialog create();
}
# Don't warn about checkerframework and Kotlin annotations
-dontwarn org.checkerframework.**
-dontwarn kotlin.annotations.jvm.**
-dontwarn javax.annotation.**
...@@ -15,18 +15,21 @@ ...@@ -15,18 +15,21 @@
*/ */
package com.google.android.exoplayer2.ui; package com.google.android.exoplayer2.ui;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil; import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
import com.google.android.exoplayer2.util.Assertions; import java.lang.reflect.Constructor;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
...@@ -97,7 +100,7 @@ public final class TrackSelectionDialogBuilder { ...@@ -97,7 +100,7 @@ public final class TrackSelectionDialogBuilder {
Context context, CharSequence title, DefaultTrackSelector trackSelector, int rendererIndex) { Context context, CharSequence title, DefaultTrackSelector trackSelector, int rendererIndex) {
this.context = context; this.context = context;
this.title = title; this.title = title;
this.mappedTrackInfo = Assertions.checkNotNull(trackSelector.getCurrentMappedTrackInfo()); this.mappedTrackInfo = checkNotNull(trackSelector.getCurrentMappedTrackInfo());
this.rendererIndex = rendererIndex; this.rendererIndex = rendererIndex;
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex); TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
...@@ -205,13 +208,65 @@ public final class TrackSelectionDialogBuilder { ...@@ -205,13 +208,65 @@ public final class TrackSelectionDialogBuilder {
} }
/** Builds the dialog. */ /** Builds the dialog. */
public AlertDialog build() { public Dialog build() {
@Nullable Dialog dialog = buildForAndroidX();
return dialog == null ? buildForPlatform() : dialog;
}
private Dialog buildForPlatform() {
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
// Inflate with the builder's context to ensure the correct style is used. // Inflate with the builder's context to ensure the correct style is used.
LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
View dialogView = dialogInflater.inflate(R.layout.exo_track_selection_dialog, /* root= */ null); View dialogView = dialogInflater.inflate(R.layout.exo_track_selection_dialog, /* root= */ null);
Dialog.OnClickListener okClickListener = setUpDialogView(dialogView);
return builder
.setTitle(title)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, okClickListener)
.setNegativeButton(android.R.string.cancel, null)
.create();
}
// Reflection calls can't verify null safety of return values or parameters.
@SuppressWarnings("nullness:argument.type.incompatible")
@Nullable
private Dialog buildForAndroidX() {
try {
// This method uses reflection to avoid a dependency on AndroidX appcompat that adds 800KB to
// the APK size even with shrinking. See https://issuetracker.google.com/161514204.
// LINT.IfChange
Class<?> builderClazz = Class.forName("androidx.appcompat.app.AlertDialog$Builder");
Constructor<?> builderConstructor = builderClazz.getConstructor(Context.class);
Object builder = builderConstructor.newInstance(context);
// Inflate with the builder's context to ensure the correct style is used.
Context builderContext = (Context) builderClazz.getMethod("getContext").invoke(builder);
LayoutInflater dialogInflater = LayoutInflater.from(builderContext);
View dialogView =
dialogInflater.inflate(R.layout.exo_track_selection_dialog, /* root= */ null);
Dialog.OnClickListener okClickListener = setUpDialogView(dialogView);
builderClazz.getMethod("setTitle", CharSequence.class).invoke(builder, title);
builderClazz.getMethod("setView", View.class).invoke(builder, dialogView);
builderClazz
.getMethod("setPositiveButton", int.class, DialogInterface.OnClickListener.class)
.invoke(builder, android.R.string.ok, okClickListener);
builderClazz
.getMethod("setNegativeButton", int.class, DialogInterface.OnClickListener.class)
.invoke(builder, android.R.string.cancel, null);
return (Dialog) builderClazz.getMethod("create").invoke(builder);
// LINT.ThenChange(../../../../../../../../proguard-rules.txt)
} catch (ClassNotFoundException e) {
// Expected if the AndroidX compat library is not available.
return null;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
private Dialog.OnClickListener setUpDialogView(View dialogView) {
TrackSelectionView selectionView = dialogView.findViewById(R.id.exo_track_selection_view); TrackSelectionView selectionView = dialogView.findViewById(R.id.exo_track_selection_view);
selectionView.setAllowMultipleOverrides(allowMultipleOverrides); selectionView.setAllowMultipleOverrides(allowMultipleOverrides);
selectionView.setAllowAdaptiveSelections(allowAdaptiveSelections); selectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
...@@ -220,15 +275,7 @@ public final class TrackSelectionDialogBuilder { ...@@ -220,15 +275,7 @@ public final class TrackSelectionDialogBuilder {
selectionView.setTrackNameProvider(trackNameProvider); selectionView.setTrackNameProvider(trackNameProvider);
} }
selectionView.init(mappedTrackInfo, rendererIndex, isDisabled, overrides, /* listener= */ null); selectionView.init(mappedTrackInfo, rendererIndex, isDisabled, overrides, /* listener= */ null);
Dialog.OnClickListener okClickListener = return (dialog, which) ->
(dialog, which) -> callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
return builder
.setTitle(title)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, okClickListener)
.setNegativeButton(android.R.string.cancel, null)
.create();
} }
} }
../../proguard-rules.txt
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment