Media3 представляет новые оптимизации, улучшения поведения и архитектурные улучшения во всех своих библиотеках. Хотя эти изменения тщательно тестируются и проверяются перед выпуском, Media3 включает централизованную инфраструктуру флагов функций (androidx.media3.common.Flags), основанную на режиме Canary, чтобы дать приложениям контроль над тем, как и когда принимаются новые модели поведения.
На этой странице рассказывается, как работают режим Canary и флаги функций и как вы можете использовать их в своем приложении, чтобы снизить риски при обновлении, контролировать развертывание и настраивать экстренные откаты.
Обзор
Режим Canary объединяет новые проверенные улучшения библиотеки под единым глобальным переключателем.
- Включен по умолчанию. В стандартных выпусках Media3 режим Canary включен по умолчанию (
true). Это гарантирует, что ваше приложение автоматически получит преимущества от безопасного повышения производительности, оптимизации и новых возможностей. - Возможность отказа и отката. Приложения могут отключать режим Canary глобально или переопределять отдельные флаги функций во время выполнения.
- Простота подключения. Параметры управляются через центральный класс
Flagsв модулеcommon, поэтому вам не нужно создавать специальные сеттеры или объекты конфигурации для разных компонентов.
Зачем использовать флаги в приложении?
Режим Canary включен по умолчанию, но интеграция Flags с конфигурацией приложения или платформой для экспериментов дает ряд преимуществ:
1. Снижение рисков при обновлении версий
Обновление основных или дополнительных версий библиотек в рабочей среде может привести к неожиданным взаимодействиям на определенных OEM-устройствах или в пользовательских медиаконвейерах. При обновлении Media3 вы можете использовать режим Canary и удаленную конфигурацию, чтобы сделать процесс обновления более безопасным:
- Выпустить обновление с отключенным режимом Canary. Выпуск новой версии Media3 с отключенным режимом Canary примерно сохраняет набор функций предыдущего выпуска (с включенным режимом Canary), позволяя вам проверить базовую стабильность библиотеки и общие исправления ошибок в рабочей среде, прежде чем внедрять новые функции.
- Постепенно включайте режим Canary. Используйте удаленную конфигурацию, чтобы включать режим Canary поэтапно для разных когорт пользователей (например, 5 % → 25 % → 100 %), или проводите A/B-эксперименты, чтобы оценить влияние на показатели.
- Откат при необходимости. Если на определенных устройствах возникает регрессия, вы можете удаленно отключить режим Canary или определенный идентификатор параметра, не выпуская экстренное обновление приложения.
- Принять по умолчанию. После проверки оставьте режим Canary включенным по умолчанию до следующего обновления версии, когда ранее проверенные функции Canary станут постоянными.
Kotlin
// Enable or disable Canary mode globally (defaults to true). Flags.setCanaryModeEnabled(false)
Java
// Enable or disable Canary mode globally (defaults to true). Flags.setCanaryModeEnabled(false);
2. Поэтапный выпуск и A/B-тестирование
Вместо того чтобы сразу предоставлять всем пользователям доступ к новым функциям библиотеки, вы можете подключить Flags к системе удаленной конфигурации или экспериментов.
Вы можете включать режим Canary поэтапно (например, 5 % пользователей → 25 % → 100 %) или проводить A/B-эксперименты, чтобы оценить влияние новых оптимизаций на основные показатели воспроизведения, такие как задержка запуска, частота повторной буферизации и сбои воспроизведения.
3. Удаленное отключение и быстрый откат
Если в рабочей версии на определенной модели устройства или версии ОС возникает регрессия, вы можете удаленно отключить режим Canary (или определенный идентификатор параметра, ответственный за проблему) с помощью конфигурации на стороне сервера. Это немедленно вернет библиотеку к ее стабильному, устаревшему резервному поведению для затронутых пользователей, не требуя экстренного исправления приложения или выпуска двоичного файла.
Настройка режима Canary и флагов
API Flags предоставляет методы для управления глобальным режимом Canary и переопределениями отдельных флагов.
Глобальный режим Canary
Чтобы включить или отключить все улучшения, доступные в режиме Canary:
Kotlin
// Enable or disable Canary mode globally (defaults to true). Flags.setCanaryModeEnabled(false)
Java
// Enable or disable Canary mode globally (defaults to true). Flags.setCanaryModeEnabled(false);
Переопределение отдельных флагов
Вы также можете явно включить или отключить определенные флаги независимо от глобальной настройки режима Canary:
Kotlin
// Explicitly enable an experimental flag. Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION) // Explicitly disable a flag. Flags.disableFlag(Flags.FLAG_DYNAMIC_SCHEDULING)
Java
// Explicitly enable an experimental flag. Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION); // Explicitly disable a flag. Flags.disableFlag(Flags.FLAG_DYNAMIC_SCHEDULING);
Явные переопределения всегда имеют приоритет над глобальным режимом Canary по умолчанию.
Проверка статуса жалобы
Чтобы проверить, активен ли в вашем коде режим Canary или определенный флаг, выполните следующие действия:
Kotlin
// Query whether Canary mode is active globally. val isCanaryActive = Flags.isCanaryModeEnabled() // Query whether a specific flag is active. val isFeatureActive = Flags.isEnabled(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION)
Java
// Query whether Canary mode is active globally. boolean isCanaryActive = Flags.isCanaryModeEnabled(); // Query whether a specific flag is active. boolean isFeatureActive = Flags.isEnabled(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION);
Порядок разрешения жалоб
Когда Media3 проверяет, включена ли функция во время выполнения, он разрешает состояние в следующем порядке:
- Явное переопределение во время выполнения. Если для идентификатора параметра был вызван метод
enableFlagилиdisableFlag, возвращается значение переопределения. - Статическое состояние библиотеки. Если параметр статически отключен (например, функция на ранней стадии разработки, которая ещё не готова для режима Canary) или статически включен (функция, которая уже прошла режим Canary, но для нее сохранена возможность временного отключения), возвращается статическое значение.
- Состояние режима Canary. В противном случае параметр будет соответствовать глобальной настройке режима Canary (включен, если режим Canary –
true, отключен, еслиfalse).
Требования к инициализации
Настройте параметры до создания экземпляров компонентов Media3 (например, ExoPlayer, Transformer или MediaSession):
- Ранняя настройка. Настройте
Flagsво время запуска приложения (например, вApplication.onCreate) или до инициализации медиаслоя приложения. - Потокобезопасность. Компоненты Media3 считывают флаги во время создания экземпляра и передают эти значения внутренним потокам воспроизведения и обработки. Убедитесь, что настройка флагов происходит до создания компонентов Media3. Изменение флагов во время работы проигрывателей или преобразователей не поддерживается.
Интеграция с удаленной конфигурацией
Рекомендуемая архитектура предполагает использование трех параметров на платформе удаленной конфигурации:
media3_canary_mode_enabled(логическое значение) – глобальный переключатель для режима Canary (по умолчаниюtrue).media3_force_enable_flags(список целых чисел) – идентификаторы определенных флагов, которые нужно принудительно включить для целевых экспериментов.media3_force_disable_flags(список целых чисел) – идентификаторы флагов, которые нужно принудительно отключить при обнаружении проблемы.
Примените эти значения во время запуска, прежде чем создавать экземпляры проигрывателя:
Kotlin
fun initializeMedia3Flags( canaryModeEnabled: Boolean, forceEnabledFlags: List<Int>, forceDisabledFlags: List<Int>, ) { // 1. Set global Canary mode state. Flags.setCanaryModeEnabled(canaryModeEnabled) // 2. Apply explicit force-enable overrides. for (flagId in forceEnabledFlags) { Flags.enableFlag(flagId) } // 3. Apply explicit force-disable overrides (remote kill switch). for (flagId in forceDisabledFlags) { Flags.disableFlag(flagId) } }
Java
public static void initializeMedia3Flags( boolean canaryModeEnabled, List<Integer> forceEnabledFlags, List<Integer> forceDisabledFlags) { // 1. Set global Canary mode state. Flags.setCanaryModeEnabled(canaryModeEnabled); // 2. Apply explicit force-enable overrides. for (int flagId : forceEnabledFlags) { Flags.enableFlag(flagId); } // 3. Apply explicit force-disable overrides (remote kill switch). for (int flagId : forceDisabledFlags) { Flags.disableFlag(flagId); } }
Тестирование с помощью флагов
При написании модульных тестов или тестов Robolectric для путей выполнения, на которые влияют флаги функций, используйте androidx.media3.test.utils.Media3FlagsRule (доступно в модуле media3-test-utils), чтобы тесты не влияли на статическое состояние друг друга.
Автоматическая очистка с помощью Media3FlagsRule
Добавление Media3FlagsRule гарантирует, что все переопределения флагов и изменения режима Canary будут автоматически сбрасываться после каждого теста:
Kotlin
class MyPlayerTest { @get:Rule val flagsRule = Media3FlagsRule(this) @Test fun playback_withFeatureFlagEnabled() { Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION) // Run test with the flag enabled... } }
Java
public static class MyPlayerTest { @Rule public final Media3FlagsRule flagsRule = new Media3FlagsRule(this); @Test public void playback_withFeatureFlagEnabled() { Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION); // Run test with the flag enabled... } }
Параметризованное тестирование
Вы можете комбинировать аннотации Media3FlagsRule с @BindFlag и @BindCanaryMode, чтобы запускать параметризованные тесты для разных состояний флагов:
Kotlin
class MyParameterizedPlayerTest { @BindCanaryMode var canaryMode: Boolean = false @BindFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION) var perStreamProgression: Boolean = false @get:Rule val flagsRule = Media3FlagsRule(this) @Test fun playback() { // Flags are automatically set for each test parameter combination. } }
Java
public static class MyParameterizedPlayerTest { @BindCanaryMode public boolean canaryMode; @BindFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION) public boolean perStreamProgression; @Rule public final Media3FlagsRule flagsRule = new Media3FlagsRule(this); @Test public void playback() { // Flags are automatically set for each test parameter combination. } }
Диагностика и ведение журналов
В Media3 есть инструменты диагностики, которые позволяют проверять активные флаги и состояния режима Canary во время инициализации воспроизведения и выполнения.
Журналы инициализации
При инициализации экземпляра ExoPlayer в logcat выводится активное состояние Canary и все явные переопределения, а также версия библиотеки:
ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.10.1] [flame, Pixel 4, Google, 33] [Canary:ON]
Если переопределения активны, в списке будут только отклонения от состояния по умолчанию:
ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.10.1] [flame, Pixel 4, Google, 33] [Canary:ON, Overrides: enabled=[1], disabled=[3]]
Проверка алгоритмических продаж
Вы можете программно получить отформатированную строку диагностики или списки переопределения запросов (например, чтобы включить состояние флага в отчеты о сбоях или аналитику вашего приложения):
Kotlin
// Get formatted string representing active Canary state and overrides. val flagLogString = Flags.getLogString() // Query explicit override IDs if needed. val enabledFlags = Flags.getEnabledOverrides() val disabledFlags = Flags.getDisabledOverrides()
Java
// Get formatted string representing active Canary state and overrides. String flagLogString = Flags.getLogString(); // Query explicit override IDs if needed. int[] enabledFlags = Flags.getEnabledOverrides(); int[] disabledFlags = Flags.getDisabledOverrides();
Жизненный цикл пометки
Флаги в Media3 временные.
- Разработка. Новая оптимизация или функция добавляется за идентификатором флага в
Flags.java. - Режим Canary. После проверки и подготовки к общему использованию функция активируется в режиме Canary во всех выпусках.
- Продвижение и очистка. После периода тестирования, подтверждающего стабильность в рабочей среде, функция продвигается до постоянно включенной в библиотеке, а константа флага, резервные пути выполнения и условные проверки удаляются.
Если вы столкнулись с проблемой, связанной с флагом функции, сообщите о ней в системе отслеживания ошибок AndroidX Media3 на GitHub, чтобы команда могла устранить ее до того, как функция станет доступна всем.