Media3 memperkenalkan pengoptimalan baru, peningkatan perilaku, dan peningkatan
arsitektur di seluruh library-nya. Meskipun perubahan ini diuji dan
diverifikasi secara menyeluruh sebelum dirilis, Media3 menyertakan infrastruktur tombol fitur
terpusat (androidx.media3.common.Flags) yang berpusat pada mode Canary
untuk memberi aplikasi kontrol atas cara dan waktu perilaku baru diterapkan.
Halaman ini menjelaskan cara kerja mode Canary dan tombol fitur, serta cara menggunakannya dalam aplikasi untuk mengurangi risiko upgrade di seluruh rilis, menjalankan peluncuran terkontrol, dan mengonfigurasi rollback darurat.
Ringkasan
Mode Canary mengelompokkan peningkatan library yang baru diperkenalkan dan diverifikasi di bawah tombol global terpadu:
- Diaktifkan secara default: Dalam rilis Media3 standar, mode Canary diaktifkan
secara default (
true). Hal ini memastikan aplikasi Anda otomatis mendapatkan manfaat dari peningkatan performa, pengoptimalan, dan kemampuan baru yang aman. - Kemampuan memilih tidak ikut dan melakukan rollback: Aplikasi dapat menonaktifkan mode Canary secara global atau mengganti tombol fitur tertentu satu per satu saat runtime.
- Tanpa kompleksitas pengaitan: Flag dikelola melalui class
Flagspusat dalam modulcommon, sehingga tidak memerlukan setter atau objek konfigurasi khusus di berbagai komponen.
Mengapa menggunakan Flag di aplikasi Anda?
Meskipun mode Canary aktif secara default, mengintegrasikan Flags dengan
framework konfigurasi atau eksperimen aplikasi Anda memberikan beberapa
manfaat:
1. Memitigasi risiko upgrade versi
Mengupgrade versi library utama atau minor dalam produksi dapat menyebabkan interaksi yang tidak terduga pada perangkat OEM tertentu atau pipeline media kustom. Saat mengupdate Media3, Anda dapat menggunakan mode Canary dan konfigurasi jarak jauh untuk alur upgrade yang lebih aman di seluruh rilis:
- Mengirimkan update dengan mode Canary dinonaktifkan: Merilis versi Media3 baru dengan mode Canary dinonaktifkan akan mempertahankan set fitur rilis sebelumnya (dengan Canary diaktifkan), sehingga Anda dapat memverifikasi stabilitas library dasar dan perbaikan bug umum dalam produksi sebelum mengadopsi perilaku baru.
- Aktifkan mode Canary secara progresif: Gunakan konfigurasi jarak jauh untuk mengaktifkan mode Canary secara bertahap di seluruh kelompok pengguna (misalnya, 5% → 25% → 100%) atau jalankan eksperimen A/B untuk mengukur dampak metrik.
- Roll back jika diperlukan: Jika terjadi regresi pada perangkat tertentu, nonaktifkan mode Canary atau ID tanda tertentu dari jarak jauh tanpa memerlukan rilis aplikasi darurat.
- Adopsi sebagai default: Setelah diverifikasi, biarkan mode Canary diaktifkan secara default hingga upgrade versi berikutnya, saat fitur Canary yang diverifikasi sebelumnya menjadi permanen.
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. Rilis bertahap yang terkontrol dan pengujian A/B
Daripada mengekspos 100% pengguna Anda ke perilaku library baru sekaligus, Anda
dapat menghubungkan Flags ke konfigurasi jarak jauh atau sistem
eksperimen.
Anda dapat mengaktifkan mode Canary secara bertahap (misalnya, 5% pengguna → 25% → 100%) atau menjalankan eksperimen A/B untuk mengukur dampak pengoptimalan baru pada metrik pemutaran inti seperti latensi startup, rasio buffering ulang, dan kegagalan pemutaran.
3. Tombol penghentian jarak jauh dan rollback cepat
Jika regresi terjadi dalam produksi pada model perangkat atau versi OS tertentu, Anda dapat menonaktifkan mode Canary dari jarak jauh (atau ID tanda tertentu yang bertanggung jawab) menggunakan konfigurasi sisi server. Tindakan ini akan langsung mengembalikan library ke perilaku penggantian lama yang stabil untuk pengguna yang terpengaruh tanpa memerlukan hotfix aplikasi darurat atau rilis biner.
Mengonfigurasi mode dan flag Canary
Flags API menyediakan metode untuk mengontrol mode Canary global dan
penggantian tanda individual.
Mode Canary Global
Untuk mengaktifkan atau menonaktifkan semua peningkatan yang tercakup dalam mode 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);
Mengganti flag satu per satu
Anda juga dapat secara eksplisit mengaktifkan atau menonaktifkan flag tertentu secara terpisah dari setelan mode Canary global:
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);
Penggantian eksplisit selalu lebih diutamakan daripada setelan default mode Canary global.
Memeriksa status tanda
Untuk memeriksa apakah mode Canary atau flag tertentu aktif dalam kode Anda:
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);
Urutan resolusi flag
Saat Media3 memeriksa apakah suatu fitur diaktifkan saat runtime, Media3 akan me-resolve status dalam urutan berikut:
- Penggantian runtime eksplisit: Jika
enableFlagataudisableFlagdipanggil untuk ID flag, nilai penggantian tersebut akan ditampilkan. - Status library statis: Jika flag dinonaktifkan secara statis (misalnya, fitur pengembangan awal yang belum siap untuk mode Canary) atau diaktifkan secara statis (fitur yang lulus dari mode Canary yang mempertahankan penggantian penonaktifan sementara), nilai statis tersebut akan ditampilkan.
- Status mode Canary: Jika tidak, tanda akan mengikuti setelan mode Canary global (diaktifkan jika mode Canary adalah
true, dinonaktifkan jikafalse).
Persyaratan inisialisasi
Konfigurasikan flag sebelum membuat instance komponen Media3 apa pun (seperti
ExoPlayer, Transformer, atau MediaSession):
- Penyiapan awal: Konfigurasikan
Flagsselama startup aplikasi (misalnya, di dalamApplication.onCreate) atau sebelum melakukan inisialisasi lapisan media aplikasi Anda. - Keamanan thread: Komponen Media3 membaca flag selama pembuatan instance dan menyebarkan nilai tersebut ke thread pemutaran dan pemrosesan internal. Pastikan konfigurasi flag terjadi sebelum membuat komponen Media3. Mengubah flag saat pemutar atau transformer berjalan secara aktif tidak didukung.
Mengintegrasikan dengan konfigurasi jarak jauh
Arsitektur yang direkomendasikan adalah mengekspos tiga parameter di platform konfigurasi jarak jauh Anda:
media3_canary_mode_enabled(Boolean): Tombol global untuk mode Canary (defaultnya adalahtrue).media3_force_enable_flags(Daftar Bilangan Bulat): ID flag tertentu yang akan diaktifkan secara paksa untuk uji coba yang ditargetkan.media3_force_disable_flags(Daftar Bilangan Bulat): ID tanda tertentu yang akan dinonaktifkan secara paksa jika ditemukan masalah.
Terapkan nilai ini selama startup sebelum membuat instance pemutar:
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); } }
Menguji dengan flag
Saat menulis pengujian unit atau pengujian Robolectric untuk jalur kode yang terpengaruh oleh tombol
fitur, gunakan androidx.media3.test.utils.Media3FlagsRule (tersedia dalam
modul media3-test-utils) untuk memastikan pengujian tidak mengganggu status statis
satu sama lain.
Pembersihan otomatis dengan Media3FlagsRule
Menambahkan Media3FlagsRule akan memastikan bahwa semua penggantian tanda dan modifikasi mode Canary
otomatis direset setelah setiap pengujian:
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... } }
Pengujian berparameter
Anda dapat menggabungkan Media3FlagsRule dengan anotasi @BindFlag dan @BindCanaryMode
untuk menjalankan pengujian berparameter di seluruh status flag:
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. } }
Diagnostik dan logging
Media3 menyediakan alat diagnostik untuk memverifikasi flag aktif dan status mode Canary selama inisialisasi pemutaran dan saat runtime.
Log inisialisasi
Saat diinisialisasi, instance ExoPlayer akan mencetak status Canary yang aktif
dan penggantian eksplisit apa pun ke logcat bersama dengan versi library:
ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.10.1] [flame, Pixel 4, Google, 33] [Canary:ON]
Jika penggantian aktif, hanya penyimpangan dari status default yang akan dicantumkan:
ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.10.1] [flame, Pixel 4, Google, 33] [Canary:ON, Overrides: enabled=[1], disabled=[3]]
Pemeriksaan terprogram
Anda dapat mengambil string diagnostik yang diformat atau daftar penggantian kueri secara terprogram (misalnya, untuk menyertakan status flag dalam laporan error atau analisis aplikasi):
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();
Siklus proses flag
Flag di Media3 dirancang agar bersifat sementara:
- Pengembangan: Pengoptimalan atau fitur baru ditambahkan di balik ID tanda di
Flags.java. - Mode Canary: Setelah diverifikasi dan siap untuk penggunaan umum, fitur ini akan aktif dalam mode Canary di seluruh rilis.
- Promosi & Pembersihan: Setelah periode pengujian yang membuktikan stabilitas dalam produksi, fitur ini dipromosikan untuk diaktifkan secara permanen di library, dan konstanta flag, jalur kode penggantian, dan pemeriksaan bersyarat akan dihapus.
Jika Anda mengalami masalah dengan tombol fitur, laporkan di Issue Tracker GitHub AndroidX Media3 agar tim dapat mengatasinya sebelum promosi permanen.