پرچم‌های ویژه و حالت Canary

Media3 بهینه‌سازی‌های جدید، بهبودهای رفتاری، و بهبودهای معماری را در سراسر کتابخانه‌های خود معرفی می‌کند. درحالی‌که این تغییرات قبل‌از انتشار به‌طور کامل آزمایش و تأیید می‌شوند، Media3 شامل زیرساخت پرچم‌های ویژگی متمرکز (androidx.media3.common.Flags) است که حول حالت Canary متمرکز شده است تا به برنامه‌ها کنترل دهد که چگونه و چه زمانی رفتارهای جدید را اتخاذ کنند.

این صفحه نحوه عملکرد حالت Canary و پرچم‌های ویژگی را توضیح می‌دهد و اینکه چگونه می‌توانید از آن‌ها در برنامه‌تان برای کاهش خطرات ارتقا در نسخه‌های پخش، اجرای عرضه کنترل‌شده، و پیکربندی بازگشت اضطراری استفاده کنید.

نمای کلی

حالت Canary بهبودهای کتابخانه درستی‌سنجی‌شده جدید را تحت یک کلید روشن/خاموش جهانی و یکپارچه گروه‌بندی می‌کند:

  • به‌طور پیش‌فرض فعال است: در نسخه‌های پخش استاندارد Media3، حالت Canary به‌طور پیش‌فرض فعال است (true). این امر تضمین می‌کند که برنامه شما به‌طور خودکار از بهبودهای عملکرد ایمن، بهینه‌سازی‌ها، و قابلیت‌های جدید بهره‌مند شود.
  • قابلیت انصراف و بازگشت به نسخه قبلی: برنامه‌ها می‌توانند حالت Canary را به‌طور سراسری غیرفعال کنند یا پرچم‌های ویژگی خاص را به‌طور جداگانه در زمان اجرا لغو کنند.
  • پیچیدگی سیم‌کشی صفر: پرچم‌ها ازطریق کلاس مرکزی Flags در ماژول common مدیریت می‌شوند، که نیاز به تنظیم‌کننده‌های سفارشی یا اشیای پیکربندی در مؤلفه‌های مختلف را ازبین می‌برد.

چرا باید از «پرچم‌ها» در برنامه‌تان استفاده کنید؟

درحالی‌که حالت «قناری» به‌طور پیش‌فرض فعال است، ادغام کردن Flags با چارچوب پیکربندی یا آزمایش برنامه شما چندین مزیت دارد:

۱. کاهش خطر ارتقای نسخه

ارتقا دادن نسخه‌های اصلی یا فرعی کتابخانه در مرحله تولید می‌تواند باعث ایجاد تعاملات غیرمنتظره در دستگاه‌های OEM خاص یا خطوط لوله رسانه سفارشی شود. هنگام به‌روزرسانی Media3، می‌توانید از حالت Canary و پیکربندی از راه دور برای جریان ارتقای ایمن‌تر در نسخه‌های پخش استفاده کنید:

  1. ارسال به‌روزرسانی با غیرفعال کردن حالت Canary: انتشار نسخه جدید Media3 با خاموش کردن حالت Canary تقریباً مجموعه ویژگی‌های نسخه قبلی (با فعال بودن Canary) را حفظ می‌کند و به شما امکان می‌دهد پایداری کتابخانه پایه و رفع اشکالات عمومی را در تولید قبل‌از اتخاذ رفتارهای جدید تأیید کنید.
  2. فعال کردن تدریجی حالت Canary: از پیکربندی از راه دور برای فعال کردن حالت Canary به‌صورت مرحله‌ای در گروه‌های کاربری (برای مثال، ۵٪ ← ۲۵٪ ← ۱۰۰٪) استفاده کنید یا آزمایش‌های A/B را برای اندازه‌گیری تأثیر سنجه اجرا کنید.
  3. درصورت نیاز، به نسخه قبلی برگردید: اگر در دستگاه‌های خاصی پس‌رفت رخ دهد، حالت «آزمایشی» یا شناسه پرچم خاص را از راه دور غیرفعال کنید، بدون اینکه نیاز باشد نسخه اضطراری برنامه را منتشر کنید.
  4. پذیرفتن به‌عنوان پیش‌فرض: پس‌از درستی‌سنجی، حالت Canary را به‌طور پیش‌فرض فعال نگه دارید تا ارتقای نسخه بعدی، که در آن ویژگی‌های Canary که قبلاً درستی‌سنجی شده‌اند دائمی می‌شوند.

کاتلین

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false)

جاوا

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false);

۲. انتشارهای گام‌به‌گام کنترل‌شده و آزمایش آ/ب

به‌جای اینکه ۱۰۰٪ کاربران را به‌طور هم‌زمان درمعرض رفتارهای کتابخانه جدید قرار دهید، می‌توانید Flags را به پیکربندی از راه دور یا سیستم آزمایشی متصل کنید.

می‌توانید حالت «قناری» را به‌صورت مرحله‌ای فعال کنید (برای مثال، ۵٪ از کاربران ← ۲۵٪ ← ۱۰۰٪) یا آزمایش‌های A/B را اجرا کنید تا تأثیر بهینه‌سازی‌های جدید را بر سنجه‌های اصلی بازپخش مانند تأخیر راه‌اندازی، نرخ میان‌گیر کردن مجدد، و خطاهای بازپخش بسنجید.

۳. کلید قطع اضطراری از راه دور و بازگشت سریع

اگر رگرسیونی در تولید روی مدل دستگاه یا نسخه سیستم‌عامل خاصی رخ دهد، می‌توانید حالت Canary (یا شناسه پرچم خاص مسئول) را از راه دور بااستفاده از پیکربندی سمت سرور غیرفعال کنید. این کار بلافاصله کتابخانه را به رفتار بازگشت قدیمی و پایدار خود برای کاربران تحت‌تأثیر قرارگرفته برمی‌گرداند، بدون اینکه نیاز به وصله اضطراری برنامه یا انتشار باینری باشد.

پیکربندی حالت Canary و پرچم‌ها

Flags API روش‌هایی برای کنترل حالت Canary جهانی و لغو پرچم‌های فردی ارائه می‌دهد.

حالت Global Canary

برای فعال یا غیرفعال کردن همه بهبودهای تحت پوشش حالت Canary:

کاتلین

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false)

جاوا

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false);

لغو پرچم‌های فردی

همچنین می‌توانید پرچم‌های خاصی را به‌طور صریح و مستقل از تنظیمات سراسری حالت Canary فعال یا غیرفعال کنید:

کاتلین

// Explicitly enable an experimental flag.
Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION)

// Explicitly disable a flag.
Flags.disableFlag(Flags.FLAG_DYNAMIC_SCHEDULING)

جاوا

// 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 یا پرچم خاصی در کد شما فعال است یا نه:

کاتلین

// 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)

جاوا

// 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 بررسی می‌کند که آیا ویژگی‌ای در زمان اجرا فعال است یا نه، وضعیت را به‌ترتیب زیر حل‌وفصل می‌کند:

  1. لغو صریح زمان اجرا: اگر enableFlag یا disableFlag برای شناسه پرچم فراخوانی شده باشد، آن مقدار لغو برگردانده می‌شود.
  2. وضعیت کتابخانه ایستا: اگر پرچم به‌صورت ایستا غیرفعال باشد (برای مثال، ویژگی توسعه اولیه که هنوز برای حالت Canary آماده نیست) یا به‌صورت ایستا فعال باشد (ویژگی‌ای که از حالت Canary فارغ‌التحصیل شده و یک گزینه انصراف موقت را حفظ کرده است)، آن مقدار ایستا برگردانده می‌شود.
  3. وضعیت حالت 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 (فهرست اعداد صحیح): شناسه‌های پرچم خاص برای غیرفعال کردن اجباری درصورت کشف مشکل.

این مقادیر را درطول راه‌اندازی قبل‌از ایجاد نمونه‌های پخش‌کننده اعمال کنید:

کاتلین

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)
  }
}

جاوا

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 به‌طور خودکار پس‌از هر آزمایش بازنشانی می‌شوند:

کاتلین

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...
  }
}

جاوا

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 ترکیب کنید تا آزمایش‌های پارامتری‌شده را در حالت‌های پرچم اجرا کنید:

کاتلین

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.
  }
}

جاوا

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 مقداردهی اولیه می‌شود، وضعیت فعال Canary و هرگونه لغو صریح را در logcat در کنار نسخه کتابخانه چاپ می‌کند:

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]]

بازرسی برنامه‌ریزی‌شده

می‌توانید رشته عیب‌یابی قالب‌بندی‌شده یا فهرست‌های لغو پُرسمان را به‌صورت برنامه‌نویسی‌شده بازیابی کنید (برای مثال، برای گنجاندن وضعیت پرچم در گزارش‌های خرابی یا تجزیه‌وتحلیل برنامه):

کاتلین

// 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()

جاوا

// 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 به‌صورت موقت طراحی شده‌اند:

  1. توسعه: بهینه‌سازی یا ویژگی جدیدی در پشت شناسه پرچم در Flags.java اضافه می‌شود.
  2. حالت Canary: پس‌از درستی‌سنجی و آماده شدن برای استفاده عمومی، این ویژگی در حالت Canary در همه نسخه‌های پخش فعال می‌شود.
  3. ارتقا و پاک‌سازی: پس‌از یک دوره آزمایشی که پایداری در تولید را اثبات می‌کند، ویژگی به حالت فعال دائمی در کتابخانه ارتقا می‌یابد و ثابت پرچم، مسیرهای کد بازگشتی، و بررسی‌های شرطی برداشته می‌شوند.

اگر با مشکلی در پرچم ویژگی مواجه شدید، لطفاً گزارشی در ردیاب مشکل AndroidX Media3 GitHub ثبت کنید تا تیم بتواند قبل‌از ارتقای دائمی به آن رسیدگی کند.