diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2adbc735eb..46840f23d2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -18,6 +18,8 @@ Release notes ([#10776](https://github.com/google/ExoPlayer/issues/10776)). * Add parameter to `BasePlayer.seekTo` to also indicate the command used for seeking. + * Use theme when loading drawables on API 21+ + ([#220](https://github.com/androidx/media/issues/220)). * Audio: * Use the compressed audio format bitrate to calculate the min buffer size for `AudioTrack` in direct playbacks (passthrough). diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 788b0b5009..43e8ebc5f0 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -48,6 +48,7 @@ import android.content.res.Resources; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; import android.graphics.Point; +import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.media.AudioFormat; import android.media.AudioManager; @@ -68,6 +69,8 @@ import android.util.SparseLongArray; import android.view.Display; import android.view.SurfaceView; import android.view.WindowManager; +import androidx.annotation.DoNotInline; +import androidx.annotation.DrawableRes; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.media3.common.C; @@ -2907,6 +2910,23 @@ public final class Util { return sum; } + /** + * Returns a {@link Drawable} for the given resource or throws a {@link + * Resources.NotFoundException} if not found. + * + * @param context The context to get the theme from starting with API 21. + * @param resources The resources to load the drawable from. + * @param drawableRes The drawable resource int. + * @return The loaded {@link Drawable}. + */ + @UnstableApi + public static Drawable getDrawable( + Context context, Resources resources, @DrawableRes int drawableRes) { + return SDK_INT >= 21 + ? Api21.getDrawable(context, resources, drawableRes) + : resources.getDrawable(drawableRes); + } + @Nullable private static String getSystemProperty(String name) { try { @@ -3143,4 +3163,12 @@ public final class Util { 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 }; + + @RequiresApi(21) + private static final class Api21 { + @DoNotInline + public static Drawable getDrawable(Context context, Resources resources, @DrawableRes int res) { + return resources.getDrawable(res, context.getTheme()); + } + } } diff --git a/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java index 67197ade22..b0be016e63 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java @@ -28,6 +28,7 @@ import static androidx.media3.common.Player.EVENT_POSITION_DISCONTINUITY; import static androidx.media3.common.Player.EVENT_REPEAT_MODE_CHANGED; import static androidx.media3.common.Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED; import static androidx.media3.common.Player.EVENT_TIMELINE_CHANGED; +import static androidx.media3.common.util.Util.getDrawable; import android.annotation.SuppressLint; import android.content.Context; @@ -498,11 +499,16 @@ public class LegacyPlayerControlView extends FrameLayout { buttonAlphaDisabled = (float) resources.getInteger(R.integer.exo_media_button_opacity_percentage_disabled) / 100; - repeatOffButtonDrawable = resources.getDrawable(R.drawable.exo_legacy_controls_repeat_off); - repeatOneButtonDrawable = resources.getDrawable(R.drawable.exo_legacy_controls_repeat_one); - repeatAllButtonDrawable = resources.getDrawable(R.drawable.exo_legacy_controls_repeat_all); - shuffleOnButtonDrawable = resources.getDrawable(R.drawable.exo_legacy_controls_shuffle_on); - shuffleOffButtonDrawable = resources.getDrawable(R.drawable.exo_legacy_controls_shuffle_off); + repeatOffButtonDrawable = + getDrawable(context, resources, R.drawable.exo_legacy_controls_repeat_off); + repeatOneButtonDrawable = + getDrawable(context, resources, R.drawable.exo_legacy_controls_repeat_one); + repeatAllButtonDrawable = + getDrawable(context, resources, R.drawable.exo_legacy_controls_repeat_all); + shuffleOnButtonDrawable = + getDrawable(context, resources, R.drawable.exo_legacy_controls_shuffle_on); + shuffleOffButtonDrawable = + getDrawable(context, resources, R.drawable.exo_legacy_controls_shuffle_off); repeatOffButtonContentDescription = resources.getString(R.string.exo_controls_repeat_off_description); repeatOneButtonContentDescription = diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index 8c56f78298..461dbd2dd0 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -34,6 +34,7 @@ import static androidx.media3.common.Player.EVENT_TIMELINE_CHANGED; import static androidx.media3.common.Player.EVENT_TRACKS_CHANGED; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Util.castNonNull; +import static androidx.media3.common.util.Util.getDrawable; import android.annotation.SuppressLint; import android.content.Context; @@ -53,7 +54,9 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.PopupWindow; import android.widget.TextView; +import androidx.annotation.DrawableRes; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; import androidx.core.content.res.ResourcesCompat; import androidx.media3.common.C; import androidx.media3.common.Format; @@ -529,11 +532,11 @@ public class PlayerControlView extends FrameLayout { settingTexts[SETTINGS_PLAYBACK_SPEED_POSITION] = resources.getString(R.string.exo_controls_playback_speed); settingIcons[SETTINGS_PLAYBACK_SPEED_POSITION] = - resources.getDrawable(R.drawable.exo_styled_controls_speed); + getDrawable(context, resources, R.drawable.exo_styled_controls_speed); settingTexts[SETTINGS_AUDIO_TRACK_SELECTION_POSITION] = resources.getString(R.string.exo_track_selection_title_audio); settingIcons[SETTINGS_AUDIO_TRACK_SELECTION_POSITION] = - resources.getDrawable(R.drawable.exo_styled_controls_audiotrack); + getDrawable(context, resources, R.drawable.exo_styled_controls_audiotrack); settingsAdapter = new SettingsAdapter(settingTexts, settingIcons); settingsWindowMargin = resources.getDimensionPixelSize(R.dimen.exo_settings_offset); settingsView = @@ -553,8 +556,10 @@ public class PlayerControlView extends FrameLayout { needToHideBars = true; trackNameProvider = new DefaultTrackNameProvider(getResources()); - subtitleOnButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_subtitle_on); - subtitleOffButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_subtitle_off); + subtitleOnButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_subtitle_on); + subtitleOffButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_subtitle_off); subtitleOnContentDescription = resources.getString(R.string.exo_controls_cc_enabled_description); subtitleOffContentDescription = @@ -565,14 +570,20 @@ public class PlayerControlView extends FrameLayout { new PlaybackSpeedAdapter( resources.getStringArray(R.array.exo_controls_playback_speeds), PLAYBACK_SPEEDS); - fullScreenExitDrawable = resources.getDrawable(R.drawable.exo_styled_controls_fullscreen_exit); + fullScreenExitDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_fullscreen_exit); fullScreenEnterDrawable = - resources.getDrawable(R.drawable.exo_styled_controls_fullscreen_enter); - repeatOffButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_repeat_off); - repeatOneButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_repeat_one); - repeatAllButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_repeat_all); - shuffleOnButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_shuffle_on); - shuffleOffButtonDrawable = resources.getDrawable(R.drawable.exo_styled_controls_shuffle_off); + getDrawable(context, resources, R.drawable.exo_styled_controls_fullscreen_enter); + repeatOffButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_off); + repeatOneButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_one); + repeatAllButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_all); + shuffleOnButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_shuffle_on); + shuffleOffButtonDrawable = + getDrawable(context, resources, R.drawable.exo_styled_controls_shuffle_off); fullScreenExitContentDescription = resources.getString(R.string.exo_controls_fullscreen_exit_description); fullScreenEnterContentDescription = @@ -955,17 +966,20 @@ public class PlayerControlView extends FrameLayout { return; } if (playPauseButton != null) { - if (shouldShowPauseButton()) { - ((ImageView) playPauseButton) - .setImageDrawable(resources.getDrawable(R.drawable.exo_styled_controls_pause)); - playPauseButton.setContentDescription( - resources.getString(R.string.exo_controls_pause_description)); - } else { - ((ImageView) playPauseButton) - .setImageDrawable(resources.getDrawable(R.drawable.exo_styled_controls_play)); - playPauseButton.setContentDescription( - resources.getString(R.string.exo_controls_play_description)); - } + boolean shouldShowPauseButton = shouldShowPauseButton(); + @DrawableRes + int drawableRes = + shouldShowPauseButton + ? R.drawable.exo_styled_controls_pause + : R.drawable.exo_styled_controls_play; + @StringRes + int stringRes = + shouldShowPauseButton + ? R.string.exo_controls_pause_description + : R.string.exo_controls_play_description; + ((ImageView) playPauseButton) + .setImageDrawable(getDrawable(getContext(), resources, drawableRes)); + playPauseButton.setContentDescription(resources.getString(stringRes)); } } diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerView.java index 998bd845ba..6731d040a3 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerView.java @@ -18,6 +18,7 @@ package androidx.media3.ui; import static androidx.media3.common.Player.COMMAND_GET_TEXT; import static androidx.media3.common.Player.COMMAND_SET_VIDEO_SURFACE; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Util.getDrawable; import static java.lang.annotation.ElementType.TYPE_USE; import android.annotation.SuppressLint; @@ -291,9 +292,9 @@ public class PlayerView extends FrameLayout implements AdViewProvider { overlayFrameLayout = null; ImageView logo = new ImageView(context); if (Util.SDK_INT >= 23) { - configureEditModeLogoV23(getResources(), logo); + configureEditModeLogoV23(context, getResources(), logo); } else { - configureEditModeLogo(getResources(), logo); + configureEditModeLogo(context, getResources(), logo); } addView(logo); return; @@ -1450,13 +1451,14 @@ public class PlayerView extends FrameLayout implements AdViewProvider { } @RequiresApi(23) - private static void configureEditModeLogoV23(Resources resources, ImageView logo) { - logo.setImageDrawable(resources.getDrawable(R.drawable.exo_edit_mode_logo, null)); + private static void configureEditModeLogoV23( + Context context, Resources resources, ImageView logo) { + logo.setImageDrawable(getDrawable(context, resources, R.drawable.exo_edit_mode_logo)); logo.setBackgroundColor(resources.getColor(R.color.exo_edit_mode_background_color, null)); } - private static void configureEditModeLogo(Resources resources, ImageView logo) { - logo.setImageDrawable(resources.getDrawable(R.drawable.exo_edit_mode_logo)); + private static void configureEditModeLogo(Context context, Resources resources, ImageView logo) { + logo.setImageDrawable(getDrawable(context, resources, R.drawable.exo_edit_mode_logo)); logo.setBackgroundColor(resources.getColor(R.color.exo_edit_mode_background_color)); }