ফিচার ফ্ল্যাগ ও Canary মোড

Media3 তার লাইব্রেরি জুড়ে নতুন অপ্টিমাইজেশন, আচরণগত উন্নতি এবং আর্কিটেকচারাল উন্নতি প্রবর্তন করে। এই পরিবর্তনগুলি রিলিজ করার আগে পুঙ্খানুপুঙ্খভাবে পরীক্ষা এবং যাচাই করা হলেও, Media3-তে একটি সেন্ট্রালাইজড ফিচার ফ্ল্যাগ ইনফ্রাস্ট্রাকচার (androidx.media3.common.Flags) অন্তর্ভুক্ত রয়েছে যা Canary মোড-এর চারপাশে কেন্দ্রীভূত, যাতে অ্যাপ্লিকেশনগুলি কীভাবে এবং কখন নতুন আচরণ গ্রহণ করবে তা নিয়ন্ত্রণ করতে পারে।

এই পৃষ্ঠা থেকে জানা যায় যে কীভাবে Canary মোড এবং ফিচার ফ্ল্যাগ কাজ করে এবং কীভাবে আপনি সেগুলি আপনার অ্যাপ্লিকেশনে ব্যবহার করতে পারেন যাতে রিলিজ জুড়ে আপগ্রেড ঝুঁকি কমানো, কন্ট্রোল করা রোলআউট চালানো এবং জরুরি রোলব্যাক কনফিগার করা যায়।

এক নজরে

ক্যানারি মোড, নতুনভাবে চালু করা, যাচাই করা লাইব্রেরি সংক্রান্ত উন্নতিকে একটি ইউনিফায়েড, গ্লোবাল টগলের অধীনে গ্রুপ করে:

  • ডিফল্ট হিসেবে চালু করা থাকে: স্ট্যান্ডার্ড Media3 রিলিজে, ক্যানারি মোড ডিফল্ট হিসেবে চালু করা থাকে (true)। এটি নিশ্চিত করে যে আপনার অ্যাপ অটোমেটিক নিরাপদ পারফর্ম্যান্সের উন্নতি, অপ্টিমাইজেশন এবং নতুন ক্ষমতা থেকে সুবিধা পায়।
  • অপ্ট-আউট ও রোলব্যাক করার ক্ষমতা: অ্যাপ্লিকেশন বিশ্বব্যাপী Canary মোড বন্ধ করতে পারে অথবা রানটাইমে আলাদাভাবে নির্দিষ্ট ফিচার ফ্ল্যাগ ওভাররাইড করতে পারে।
  • ওয়্যারিংয়ের কোনও জটিলতা নেই: common মডিউলের সেন্ট্রাল Flags ক্লাসের মাধ্যমে ফ্ল্যাগ ম্যানেজ করা হয়, যার ফলে বিভিন্ন কম্পোনেন্ট জুড়ে বেস্পোক সেটার বা কনফিগারেশন অবজেক্টের প্রয়োজন হয় না।

আপনার অ্যাপে ফ্ল্যাগ কেন ব্যবহার করবেন?

ডিফল্ট হিসেবে Canary মোড চালু থাকলেও, আপনার অ্যাপের কনফিগারেশন বা এক্সপেরিমেন্টেশন ফ্রেমওয়ার্কের সাথে Flags ইন্টিগ্রেট করলে অনেক সুবিধা পাওয়া যায়:

১. ভার্সন আপগ্রেড করার ঝুঁকি কমানো

প্রোডাকশনে লাইব্রেরির মেজর বা মাইনর ভার্সন আপগ্রেড করলে নির্দিষ্ট OEM ডিভাইস বা কাস্টম মিডিয়া পাইপলাইনে অপ্রত্যাশিত ইন্টার‍্যাকশন হতে পারে। Media3 আপডেট করার সময়, আপনি Canary মোড ও রিমোট কনফিগারেশন ব্যবহার করে রিলিজ জুড়ে আরও নিরাপদ আপগ্রেড ফ্লো পেতে পারেন:

  1. ক্যানারি মোড বন্ধ রেখে আপডেট শিপ করা: ক্যানারি মোড বন্ধ রেখে নতুন Media3 ভার্সন রিলিজ করলে, আগের রিলিজে (ক্যানারি চালু রেখে) যে ফিচার সেট ছিল, তা মোটামুটি একই থাকে। এর ফলে, নতুন আচরণ গ্রহণ করার আগে, প্রোডাকশনে বেসলাইন লাইব্রেরির স্থায়িত্ব এবং সাধারণ সমস্যার সমাধান যাচাই করে নিতে পারবেন।
  2. ধাপে ধাপে ক্যানারি মোড চালু করুন: ব্যবহারকারী কোহর্ট জুড়ে (যেমন, ৫% → ২৫% → ১০০%) ধাপে ধাপে ক্যানারি মোড চালু করতে রিমোট কনফিগারেশন ব্যবহার করুন অথবা মেট্রিক ইমপ্যাক্ট পরিমাপ করতে A/B পরীক্ষা চালান।
  3. প্রয়োজন হলে আগের অবস্থায় ফিরে যান: নির্দিষ্ট ডিভাইসে রিগ্রেশন হলে, জরুরি ভিত্তিতে অ্যাপ রিলিজ করার প্রয়োজন ছাড়াই Canary মোড বা নির্দিষ্ট ফ্ল্যাগ আইডি রিমোটলি বন্ধ করুন।
  4. ডিফল্ট হিসেবে গ্রহণ করুন: যাচাই করা হয়ে গেলে, পরবর্তী ভার্সন আপগ্রেড না হওয়া পর্যন্ত ডিফল্ট হিসেবে Canary মোড চালু রাখুন, যেখানে আগে যাচাই করা Canary ফিচার স্থায়ী হয়ে যায়।

Kotlin

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

জাভা

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

২. নিয়ন্ত্রিত স্টেজড রিলিজ ও A/B টেস্টিং

আপনার ব্যবহারকারীদের ১০০% নতুন লাইব্রেরি আচরণের সাথে একবারে পরিচিত করার পরিবর্তে, আপনি রিমোট কনফিগারেশন বা এক্সপেরিমেন্টেশন সিস্টেমে Flags ওয়্যার করতে পারেন।

আপনি ধাপে ধাপে ক্যানারি মোড চালু করতে পারেন (যেমন, ৫% ব্যবহারকারী → ২৫% → ১০০%) অথবা স্টার্টআপ লেটেন্সি, রিবাফার রেট ও প্লেব্যাক ব্যর্থতার মতো মূল প্লেব্যাক মেট্রিকের উপর নতুন অপ্টিমাইজেশনের প্রভাব পরিমাপ করতে A/B পরীক্ষা চালাতে পারেন।

৩. রিমোট কিল সুইচ ও দ্রুত রোলব্যাক

কোনও নির্দিষ্ট ডিভাইস মডেল বা OS ভার্সনে প্রোডাকশনে রিগ্রেশন হলে, আপনি সার্ভার-সাইড কনফিগারেশন ব্যবহার করে Canary মোড (বা নির্দিষ্ট ফ্ল্যাগ আইডি) রিমোটলি বন্ধ করতে পারবেন। এটি অবিলম্বে লাইব্রেরিকে তার স্থিতিশীল, প্রভাবিত ব্যবহারকারীদের জন্য লিগ্যাসি ফলব্যাক আচরণে ফিরিয়ে দেয় যার জন্য জরুরি অ্যাপ হটফিক্স বা বাইনারি রিলিজের প্রয়োজন হয় না।

Canary মোড ও ফ্ল্যাগ কনফিগার করা হচ্ছে

Flags API গ্লোবাল Canary মোড এবং ব্যক্তিগত ফ্ল্যাগ ওভাররাইড কন্ট্রোল করার পদ্ধতি প্রদান করে।

গ্লোবাল ক্যানারি মোড

Canary মোডের মাধ্যমে কভার করা সব এনহ্যান্সমেন্ট চালু বা বন্ধ করতে:

Kotlin

// 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 মোড সেটিং থেকে স্বাধীনভাবে নির্দিষ্ট ফ্ল্যাগ স্পষ্টভাবে চালু বা বন্ধ করতে পারেন:

Kotlin

// 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 মোড বা কোনও নির্দিষ্ট ফ্ল্যাগ অ্যাক্টিভ আছে কিনা তা চেক করতে:

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)

জাভা

// 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) ইনস্ট্যান্টিয়েট করার আগে ফ্ল্যাগ কনফিগার করুন:

  • আগে সেট-আপ করা: অ্যাপ্লিকেশন স্টার্টআপের সময় (যেমন, Application.onCreate-এর মধ্যে) অথবা আপনার অ্যাপের মিডিয়া লেয়ার শুরু করার আগে Flags কনফিগার করুন।
  • থ্রেড নিরাপত্তা: Media3 কম্পোনেন্ট ইনস্ট্যান্টিয়েশনের সময় ফ্ল্যাগ পড়ে এবং ইন্টার্নাল প্লেব্যাক ও প্রসেসিং থ্রেডে সেইসব ভ্যালু প্রোপাগেট করে। নিশ্চিত করুন যে Media3 কম্পোনেন্ট তৈরি করার আগে ফ্ল্যাগ কনফিগারেশন করা হয়েছে। প্লেয়ার বা ট্রান্সফর্মার অ্যাক্টিভ থাকাকালীন ফ্ল্যাগ পরিবর্তন করা যাবে না।

রিমোট কনফিগারেশনের সাথে ইন্টিগ্রেট করা

আপনার রিমোট কনফিগারেশন প্ল্যাটফর্মে তিনটি প্যারামিটার প্রকাশ করার জন্য একটি আর্কিটেকচার সাজেস্ট করা হয়েছে:

  • media3_canary_mode_enabled (বুলিয়ান): ক্যানারি মোডের জন্য গ্লোবাল টগল (ডিফল্ট হিসেবে 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)
  }
}

জাভা

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

জাভা

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

জাভা

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

ডায়াগনস্টিক ও লগিং

প্লেব্যাক শুরু করার সময় এবং রানটাইমে অ্যাক্টিভ ফ্ল্যাগ এবং Canary মোডের স্ট্যাটাস যাচাই করার জন্য Media3 ডায়াগনস্টিক টুল প্রদান করে।

ইনিশিয়ালাইজেশন লগ

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

প্রোগ্র্যামাটিক পরিদর্শন

আপনি প্রোগ্রাম্যাটিক্যালি ফর্ম্যাট করা ডায়াগনস্টিক স্ট্রিং বা কোয়েরি ওভাররাইড তালিকা উদ্ধার করতে পারবেন (যেমন, আপনার অ্যাপের ক্র্যাশ রিপোর্ট বা অ্যানালিটিক্সে ফ্ল্যাগ স্টেট অন্তর্ভুক্ত করতে):

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

জাভা

// 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. ক্যানারি মোড: যাচাই করা হয়ে গেলে এবং সাধারণ ব্যবহারের জন্য প্রস্তুত হলে, ফিচারটি রিলিজ জুড়ে ক্যানারি মোডের অধীনে অ্যাক্টিভ থাকে।
  3. প্রোমোশন ও ক্লিনআপ: প্রোডাকশনে স্থায়িত্ব প্রমাণ করার জন্য একটি সোক পিরিয়ডের পরে, ফিচারটি লাইব্রেরিতে স্থায়ীভাবে চালু করার জন্য প্রোমোট করা হয় এবং ফ্ল্যাগ কনস্ট্যান্ট, ফলব্যাক কোড পাথ ও কন্ডিশনাল চেক সরিয়ে দেওয়া হয়।

ফিচার ফ্ল্যাগ নিয়ে কোনও সমস্যা হলে, AndroidX Media3 GitHub ইস্যু ট্র্যাকার-এ রিপোর্ট করুন যাতে স্থায়ীভাবে প্রোমোট করার আগে টিম সেটির সমাধান করতে পারে।