চাহিদা অনুযায়ী ডেলিভারি কনফিগার করুন

ফিচার মডিউল আপনাকে অ্যাপের বেস মডিউল থেকে নির্দিষ্ট ফিচার ও রিসোর্স আলাদা করতে এবং অ্যাপ বান্ডেলে সেগুলি অন্তর্ভুক্ত করতে দেয়। Play ফিচার ডেলিভারির মাধ্যমে, ব্যবহারকারীরা, উদাহরণস্বরূপ, আপনার অ্যাপের বেস APK আগে থেকেই ইনস্টল করার পরে, চাহিদা অনুযায়ী পরে সেইসব কম্পোনেন্ট ডাউনলোড ও ইনস্টল করতে পারবেন।

যেমন, এমন একটি টেক্সট মেসেজিং অ্যাপের কথা ভাবুন যাতে ছবি ক্যাপচার করা ও ছবি সহ মেসেজ পাঠানোর ফাংশন আছে, কিন্তু খুব কম সংখ্যক ব্যবহারকারীই ছবি সহ মেসেজ পাঠান। ডাউনলোড করা যাবে এমন ফিচার মডিউল হিসেবে ছবি সহ মেসেজ পাঠানোর সুবিধা যোগ করা উপযুক্ত হতে পারে। এর ফলে, সব ব্যবহারকারীর জন্য অ্যাপের প্রাথমিক ডাউনলোড সাইজ ছোট হয় এবং শুধুমাত্র যেসব ব্যবহারকারী ছবির মেসেজ পাঠান তাদেরই অতিরিক্ত কম্পোনেন্ট ডাউনলোড করতে হয়।

মনে রাখবেন, এই ধরনের মডিউলারাইজেশনের জন্য আরও বেশি পরিশ্রম করতে হয় এবং আপনার অ্যাপের বর্তমান কোড রিফ্যাক্টর করতে হতে পারে, তাই আপনার অ্যাপের কোন ফিচার ব্যবহারকারীদের চাহিদা অনুযায়ী উপলভ্য হলে সবচেয়ে বেশি সুবিধা হবে তা ভালভাবে বিবেচনা করুন। অন-ডিমান্ড ফিচারের জন্য সর্বোত্তম ব্যবহারের কেস এবং নির্দেশিকা আরও ভালোভাবে বুঝতে, অন-ডিমান্ড ডেলিভারির জন্য UX পেশাদার পদ্ধতি পড়ুন।

আপনি যদি সময়ের সাথে সাথে ধীরে ধীরে অ্যাপের ফিচার মডিউলারাইজ করতে চান, তাহলে উন্নত ডেলিভারি বিকল্প চালু না করে, যেমন অন-ডিমান্ড ডেলিভারি, তার পরিবর্তে ইনস্টল-টাইম ডেলিভারি কনফিগার করুন।

এই পৃষ্ঠা আপনাকে অ্যাপ প্রোজেক্টে ফিচার মডিউল যোগ করতে এবং চাহিদা অনুযায়ী ডেলিভারির জন্য এটি কনফিগার করতে সাহায্য করে। শুরু করার আগে, আপনি Android Studio 3.5 বা তার পরবর্তী কোনও ভার্সন এবং Android Gradle Plugin 3.5.0 বা তার পরবর্তী কোনও ভার্সন ব্যবহার করছেন কিনা তা নিশ্চিত করুন।

অন-ডিমান্ড ডেলিভারির জন্য নতুন মডিউল কনফিগার করুন

Android Studio 3.5 বা তার পরবর্তী যেকোনও ভার্সন ব্যবহার করে নতুন ফিচার মডিউল তৈরি করা সবচেয়ে সহজ। ফিচার মডিউলগুলি বেস অ্যাপ মডিউলের উপর সহজাতভাবে নির্ভরশীল, তাই আপনি শুধুমাত্র বিদ্যমান অ্যাপ প্রোজেক্টে সেগুলি যোগ করতে পারবেন।

Android Studio ব্যবহার করে আপনার অ্যাপ প্রোজেক্টে ফিচার মডিউল যোগ করতে, এইভাবে এগিয়ে যান:

  1. আপনি আগে থেকে এটি না করে থাকলে, IDE-তে আপনার অ্যাপ প্রোজেক্ট খুলুন।
  2. মেনু বার থেকে ফাইল > নতুন > নতুন মডিউল বিকল্প বেছে নিন।
  3. নতুন মডিউল তৈরি করুন ডায়ালগে, ডায়নামিক ফিচার মডিউল বেছে নিয়ে পরবর্তী বিকল্পে ক্লিক করুন।
  4. আপনার নতুন মডিউল কনফিগার করুন বিভাগে, নিম্নলিখিত ধাপগুলি সম্পূর্ণ করুন:
    1. ড্রপডাউন মেনু থেকে আপনার অ্যাপ প্রোজেক্টের জন্য বেস অ্যাপ্লিকেশন মডিউল বেছে নিন।
    2. মডিউলের নাম উল্লেখ করুন। আপনার Gradle সেটিংস ফাইলে মডিউলটিকে Gradle সাবপ্রোজেক্ট হিসেবে শনাক্ত করতে IDE এই নামটি ব্যবহার করে। আপনি যখন অ্যাপ বান্ডেল তৈরি করেন, তখন Gradle সাবপ্রোজেক্টের নামের শেষ এলিমেন্ট ব্যবহার করে <manifest split> অ্যাট্রিবিউট ফিচার মডিউলের ম্যানিফেস্টে ইনজেক্ট করে।
    3. মডিউলের প্যাকেজের নাম উল্লেখ করুন। ডিফল্ট হিসেবে, Android Studio এমন একটি প্যাকেজের নাম সাজেস্ট করে যা বেস মডিউলের রুট প্যাকেজের নাম এবং আগের ধাপে আপনার উল্লেখ করা মডিউলের নামকে একত্রিত করে।
    4. আপনি যে ন্যূনতম API লেভেল-এ মডিউলটি চালাতে চান সেটি বেছে নিন। এই ভ্যালু বেস মডিউলের ভ্যালুর সাথে ম্যাচ করতে হবে।
  5. পরবর্তী বিকল্পে ক্লিক করুন।
  6. মডিউল ডাউনলোড করার বিকল্প বিভাগে, নিম্নলিখিত ধাপগুলি সম্পূর্ণ করুন:

    1. সর্বাধিক ৫০টি অক্ষর ব্যবহার করে মডিউলের শীর্ষক নির্দিষ্ট করুন। ব্যবহারকারী মডিউলটি ডাউনলোড করতে চান কিনা তা কনফার্ম করার মতো পরিস্থিতিতে, ব্যবহারকারীদের কাছে মডিউলটি শনাক্ত করতে প্ল্যাটফর্ম এই শীর্ষকটি ব্যবহার করে। এই কারণে, আপনার অ্যাপের বেস মডিউলে অবশ্যই মডিউলের নাম স্ট্রিং রিসোর্স হিসেবে অন্তর্ভুক্ত করতে হবে, যা আপনি অনুবাদ করতে পারবেন। Android Studio ব্যবহার করে মডিউল তৈরি করার সময়, IDE আপনার জন্য বেস মডিউলে স্ট্রিং রিসোর্স যোগ করে এবং ফিচার মডিউলের ম্যানিফেস্টে নিম্নলিখিত এন্ট্রি ইনজেক্ট করে:

      <dist:module
          ...
          dist:title="@string/feature_title">
      </dist:module>
      
    2. ইনস্টল করার সময় অন্তর্ভুক্ত করা বিকল্পের অধীনে ড্রপডাউন মেনু থেকে, ইনস্টল করার সময় মডিউল অন্তর্ভুক্ত করবেন না বিকল্প বেছে নিন। আপনার পছন্দ অনুযায়ী Android Studio মডিউলের ম্যানিফেস্টে নিম্নলিখিত কোড ইনজেক্ট করে:

      <dist:module ... >
        <dist:delivery>
            <dist:on-demand/>
        </dist:delivery>
      </dist:module>
      
    3. আপনি যদি চান যে এই মডিউলটি Android 4.4 (API লেভেল 20) এবং তার নিচের যেকোনও ভার্সনে চলা ডিভাইসে উপলভ্য হোক এবং মাল্টি-APK-তে অন্তর্ভুক্ত হোক, তাহলে ফিউজিং-এর ঠিক পাশে থাকা বক্সে টিকচিহ্ন দিন। এর অর্থ হল, আপনি এই মডিউলের জন্য অন-ডিমান্ড আচরণ চালু করতে পারবেন এবং স্প্লিট APK ডাউনলোড ও ইনস্টল করা যায় না এমন ডিভাইস থেকে এটি বাদ দিতে ফিউজিং বন্ধ করতে পারবেন। আপনার পছন্দ অনুযায়ী Android Studio মডিউলের ম্যানিফেস্টে নিম্নলিখিতগুলি যোগ করে:

      <dist:module ...>
          <dist:fusing dist:include="true | false" />
      </dist:module>
      
  7. সম্পূর্ণ করুন বিকল্পে ক্লিক করুন।

Android Studio আপনার মডিউল তৈরি করা শেষ করার পরে, প্রোজেক্ট প্যানেল থেকে নিজেই এর কন্টেন্ট পরীক্ষা করুন (মেনু বার থেকে দেখুন > টুল উইন্ডো > প্রোজেক্ট বেছে নিন)। ডিফল্ট কোড, রিসোর্স ও অর্গানাইজেশন, স্ট্যান্ডার্ড অ্যাপ মডিউলের মতোই হতে হবে।

এরপর, আপনাকে Play ফিচার ডেলিভারি লাইব্রেরি ব্যবহার করে চাহিদা অনুযায়ী ইনস্টল করার কার্যকারিতা প্রয়োগ করতে হবে।

আপনার প্রোজেক্টে Play ফিচার ডেলিভারি লাইব্রেরি অন্তর্ভুক্ত করা

শুরু করার আগে, আপনাকে প্রথমে আপনার প্রোজেক্টে Play ফিচার ডেলিভারি লাইব্রেরি যোগ করতে হবে।

অন-ডিমান্ড মডিউলের জন্য অনুরোধ করুন

আপনার অ্যাপকে কোনও ফিচার মডিউল ব্যবহার করতে হলে, এটি ফোরগ্রাউন্ডে থাকাকালীন SplitInstallManager ক্লাসের মাধ্যমে অনুরোধ করতে পারে। অনুরোধ করার সময়, আপনার অ্যাপকে টার্গেট মডিউলের ম্যানিফেস্টে split এলিমেন্ট দ্বারা সংজ্ঞায়িত মডিউলের নাম উল্লেখ করতে হবে। Android Studio ব্যবহার করে আপনি যখন ফিচার মডিউল তৈরি করেন, তখন কম্পাইল করার সময় মডিউলের ম্যানিফেস্টে এই প্রপার্টি যোগ করার জন্য, আপনার দেওয়া মডিউলের নাম বিল্ড সিস্টেম ব্যবহার করে। আরও তথ্যের জন্য, ফিচার মডিউল ম্যানিফেস্ট সম্পর্কে পড়ুন।

যেমন, এমন একটি অ্যাপের কথা ভাবুন যার ডিভাইসের ক্যামেরা ব্যবহার করে ছবি সহ মেসেজ ক্যাপচার ও পাঠানোর জন্য অন-ডিমান্ড মডিউল আছে এবং এই অন-ডিমান্ড মডিউল তার ম্যানিফেস্টে split="pictureMessages" উল্লেখ করে। নিম্নলিখিত স্যাম্পেল pictureMessages মডিউলের (কিছু প্রোমোশনাল ফিল্টারের জন্য অতিরিক্ত মডিউল সহ) অনুরোধ করতে SplitInstallManager ব্যবহার করে:

Kotlin

// Creates an instance of SplitInstallManager.
val splitInstallManager = SplitInstallManagerFactory.create(context)

// Creates a request to install a module.
val request =
    SplitInstallRequest
        .newBuilder()
        // You can download multiple on demand modules per
        // request by invoking the following method for each
        // module you want to install.
        .addModule("pictureMessages")
        .addModule("promotionalFilters")
        .build()

splitInstallManager
    // Submits the request to install the module through the
    // asynchronous startInstall() task. Your app needs to be
    // in the foreground to submit the request.
    .startInstall(request)
    // You should also be able to gracefully handle
    // request state changes and errors. To learn more, go to
    // the section about how to Monitor the request state.
    .addOnSuccessListener { sessionId -> ... }
    .addOnFailureListener { exception ->  ... }

জাভা

// Creates an instance of SplitInstallManager.
SplitInstallManager splitInstallManager =
    SplitInstallManagerFactory.create(context);

// Creates a request to install a module.
SplitInstallRequest request =
    SplitInstallRequest
        .newBuilder()
        // You can download multiple on demand modules per
        // request by invoking the following method for each
        // module you want to install.
        .addModule("pictureMessages")
        .addModule("promotionalFilters")
        .build();

splitInstallManager
    // Submits the request to install the module through the
    // asynchronous startInstall() task. Your app needs to be
    // in the foreground to submit the request.
    .startInstall(request)
    // You should also be able to gracefully handle
    // request state changes and errors. To learn more, go to
    // the section about how to Monitor the request state.
    .addOnSuccessListener(sessionId -> { ... })
    .addOnFailureListener(exception -> { ... });

আপনার অ্যাপ কোনও অন-ডিমান্ড মডিউলের জন্য অনুরোধ করলে, Play ফিচার ডেলিভারি লাইব্রেরি “ফায়ার-অ্যান্ড-ফরগেট” স্ট্র্যাটেজি প্রয়োগ করে। অর্থাৎ, এটি প্ল্যাটফর্মে মডিউল ডাউনলোড করার অনুরোধ পাঠায়, কিন্তু ইনস্টলেশন সফল হয়েছে কিনা তা মনিটর করে না। ইনস্টল করার পরে ব্যবহারকারীর অভিজ্ঞতা এগিয়ে নিয়ে যেতে অথবা সমস্যাগুলি সুন্দরভাবে সমাধান করতে, আপনি অনুরোধের স্ট্যাটাস মনিটর করছেন কিনা তা নিশ্চিত করুন।

মনে রাখবেন: ডিভাইসে আগে থেকেই ইনস্টল করা আছে এমন ফিচার মডিউলের জন্য অনুরোধ করা যেতে পারে। API যদি শনাক্ত করে যে মডিউলটি আগে থেকেই ইনস্টল করা আছে, তাহলে এটি সাথে সাথে অনুরোধটিকে সম্পূর্ণ বলে বিবেচনা করে। এছাড়াও, কোনও মডিউল ইনস্টল করার পরে, Google Play সেটি অটোমেটিক আপডেট করে। অর্থাৎ, আপনি যখন আপনার অ্যাপ বান্ডেলের একটি নতুন ভার্সন আপলোড করেন, তখন প্ল্যাটফর্মটি আপনার অ্যাপের অন্তর্গত সমস্ত ইনস্টল করা APK আপডেট করে। আরও তথ্যের জন্য, অ্যাপ আপডেট ম্যানেজ করুন নিবন্ধটি পড়ুন।

মডিউলের কোড ও রিসোর্স অ্যাক্সেস করতে, আপনার অ্যাপকে SplitCompat চালু করতে হবে। মনে রাখবেন, Android Instant Apps-এর জন্য SplitCompat-এর প্রয়োজন নেই।

চাহিদা অনুযায়ী মডিউল ইনস্টল করা পিছিয়ে দিন

আপনার অ্যাপের যদি অবিলম্বে অন-ডিমান্ড মডিউল ডাউনলোড এবং ইনস্টল করার প্রয়োজন না হয়, তাহলে অ্যাপটি ব্যাকগ্রাউন্ডে থাকাকালীন আপনি ইনস্টলেশন স্থগিত করতে পারেন। যেমন, আপনার অ্যাপ পরে লঞ্চ করার জন্য আপনি যদি কিছু প্রোমোশনাল মেটেরিয়াল প্রিলোড করতে চান।

আপনি পরে ডাউনলোড করার জন্য কোনও মডিউল নির্দিষ্ট করতে পারেন, deferredInstall() পদ্ধতি ব্যবহার করে, যেমন নিচে দেখানো হয়েছে। এবং, SplitInstallManager.startInstall()-এর মতো নয়, আপনার অ্যাপকে স্থগিত ইনস্টলেশনের জন্য অনুরোধ শুরু করতে ফোরগ্রাউন্ডে থাকতে হবে না।

Kotlin

// Requests an on demand module to be downloaded when the app enters
// the background. You can specify more than one module at a time.
splitInstallManager.deferredInstall(listOf("promotionalFilters"))

জাভা

// Requests an on demand module to be downloaded when the app enters
// the background. You can specify more than one module at a time.
splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));

বিলম্বিত ইনস্টলের অনুরোধগুলি যথাসাধ্য চেষ্টা করা হয় এবং আপনি সেগুলির অগ্রগতি ট্র্যাক করতে পারবেন না। তাই, আপনি যে মডিউলটি পরে ইনস্টল করার জন্য নির্দিষ্ট করেছেন সেটি অ্যাক্সেস করার চেষ্টা করার আগে, আপনাকে মডিউলটি ইনস্টল করা হয়েছে কিনা তা চেক করতে হবে। আপনার যদি মডিউলটি অবিলম্বে উপলভ্য হওয়ার প্রয়োজন হয়, তাহলে এর পরিবর্তে SplitInstallManager.startInstall() ব্যবহার করে এটির জন্য অনুরোধ করুন, যেমনটি আগের বিভাগে দেখানো হয়েছে।

অনুরোধের স্ট্যাটাস মনিটর করা

প্রোগ্রেস বার আপডেট করতে, ইনস্টলেশনের পরে ইনটেন্ট ফায়ার করতে অথবা অনুরোধের সমস্যা সুন্দরভাবে ম্যানেজ করতে, আপনাকে অ্যাসিঙ্ক্রোনাস SplitInstallManager.startInstall() টাস্ক থেকে স্টেট আপডেট শুনতে হবে। আপনার ইনস্টল করার অনুরোধের জন্য আপডেট পাওয়া শুরু করার আগে, নিচে দেখানো পদ্ধতি অনুযায়ী, লিসেনার রেজিস্টার করুন এবং অনুরোধের জন্য সেশন আইডি পান।

Kotlin

// Initializes a variable to later track the session ID for a given request.
var mySessionId = 0

// Creates a listener for request status updates.
val listener = SplitInstallStateUpdatedListener { state ->
    if (state.sessionId() == mySessionId) {
      // Read the status of the request to handle the state update.
    }
}

// Registers the listener.
splitInstallManager.registerListener(listener)

...

splitInstallManager
    .startInstall(request)
    // When the platform accepts your request to download
    // an on demand module, it binds it to the following session ID.
    // You use this ID to track further status updates for the request.
    .addOnSuccessListener { sessionId -> mySessionId = sessionId }
    // You should also add the following listener to handle any errors
    // processing the request.
    .addOnFailureListener { exception ->
        // Handle request errors.
    }

// When your app no longer requires further updates, unregister the listener.
splitInstallManager.unregisterListener(listener)

জাভা

// Initializes a variable to later track the session ID for a given request.
int mySessionId = 0;

// Creates a listener for request status updates.
SplitInstallStateUpdatedListener listener = state -> {
    if (state.sessionId() == mySessionId) {
      // Read the status of the request to handle the state update.
    }
};

// Registers the listener.
splitInstallManager.registerListener(listener);

...

splitInstallManager
    .startInstall(request)
    // When the platform accepts your request to download
    // an on demand module, it binds it to the following session ID.
    // You use this ID to track further status updates for the request.
    .addOnSuccessListener(sessionId -> { mySessionId = sessionId; })
    // You should also add the following listener to handle any errors
    // processing the request.
    .addOnFailureListener(exception -> {
        // Handle request errors.
    });

// When your app no longer requires further updates, unregister the listener.
splitInstallManager.unregisterListener(listener);

অনুরোধ সংক্রান্ত সমস্যার সমাধান করা

মনে রাখবেন যে চাহিদা অনুযায়ী ফিচার মডিউল ইনস্টল করার প্রক্রিয়া কখনও কখনও ব্যর্থ হতে পারে, ঠিক যেমন অ্যাপ ইনস্টল করার প্রক্রিয়া সবসময় সফল হয় না। ডিভাইসে স্টোরেজ কম থাকা, নেটওয়ার্ক কানেক্টিভিটি না থাকা অথবা ব্যবহারকারী Google Play Store-এ সাইন-ইন না করার মতো সমস্যার কারণে ইনস্টল করা নাও যেতে পারে। ব্যবহারকারীর দৃষ্টিকোণ থেকে এইসব পরিস্থিতি কীভাবে সুন্দরভাবে সামলানো যায় সেই বিষয়ে সাজেশন পেতে, আমাদের অন-ডিমান্ড ডেলিভারির জন্য UX নির্দেশিকা চেক করুন।

কোড-ভিত্তিক, আপনি addOnFailureListener() ব্যবহার করে মডিউল ডাউনলোড বা ইনস্টল করার ব্যর্থতাগুলি পরিচালনা করতে পারেন, যেমন নিচে দেখানো হয়েছে:

Kotlin

splitInstallManager
    .startInstall(request)
    .addOnFailureListener { exception ->
        when ((exception as SplitInstallException).errorCode) {
            SplitInstallErrorCode.NETWORK_ERROR -> {
                // Display a message that requests the user to establish a
                // network connection.
            }
            SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads()
            ...
        }
    }

fun checkForActiveDownloads() {
    splitInstallManager
        // Returns a SplitInstallSessionState object for each active session as a List.
        .sessionStates
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                // Check for active sessions.
                for (state in task.result) {
                    if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                        // Cancel the request, or request a deferred installation.
                    }
                }
            }
        }
}

জাভা

splitInstallManager
    .startInstall(request)
    .addOnFailureListener(exception -> {
        switch (((SplitInstallException) exception).getErrorCode()) {
            case SplitInstallErrorCode.NETWORK_ERROR:
                // Display a message that requests the user to establish a
                // network connection.
                break;
            case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED:
                checkForActiveDownloads();
            ...
    });

void checkForActiveDownloads() {
    splitInstallManager
        // Returns a SplitInstallSessionState object for each active session as a List.
        .getSessionStates()
        .addOnCompleteListener( task -> {
            if (task.isSuccessful()) {
                // Check for active sessions.
                for (SplitInstallSessionState state : task.getResult()) {
                    if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                        // Cancel the request, or request a deferred installation.
                    }
                }
            }
        });
}

আপনার অ্যাপকে যেসব সমস্যা সংক্রান্ত স্ট্যাটাস ম্যানেজ করতে হতে পারে, সেগুলি নিচের সারণীতে বর্ণনা করা হয়েছে:

সমস্যার কোড বর্ণনা সাজেস্ট করা অ্যাকশন
ACTIVE_SESSIONS_LIMIT_EXCEEDED অনুরোধটি বাতিল করা হয়েছে কারণ বর্তমানে অন্তত একটি অনুরোধ ডাউনলোড করা হচ্ছে। উপরে দেখানো স্যাম্পেলের মতো এখনও ডাউনলোড হচ্ছে এমন কোনও অনুরোধ আছে কিনা তা চেক করুন।
MODULE_UNAVAILABLE অ্যাপের বর্তমানে ইনস্টল করা ভার্সন, ডিভাইস এবং ব্যবহারকারীর Google Play অ্যাকাউন্টের উপর ভিত্তি করে Google Play অনুরোধ করা মডিউল খুঁজে পাচ্ছে না। ব্যবহারকারীর কাছে মডিউলের অ্যাক্সেস না থাকলে, তাকে বিজ্ঞপ্তি পাঠান।
INVALID_REQUEST Google Play অনুরোধটি পেয়েছে, কিন্তু অনুরোধটি সঠিক নয়। অনুরোধে অন্তর্ভুক্ত তথ্য সম্পূর্ণ এবং সঠিক কিনা তা যাচাই করুন।
SESSION_NOT_FOUND প্রদত্ত সেশন আইডির জন্য কোনও সেশন খুঁজে পাওয়া যায়নি। আপনি যদি সেশন আইডি দিয়ে কোনও অনুরোধের স্ট্যাটাস মনিটর করার চেষ্টা করেন, তাহলে সেশন আইডি সঠিক কিনা তা নিশ্চিত করুন।
API_NOT_AVAILABLE বর্তমান ডিভাইসে Play ফিচার ডেলিভারি লাইব্রেরি কাজ করে না। অর্থাৎ, ডিভাইসটি চাহিদা অনুযায়ী ফিচার ডাউনলোড ও ইনস্টল করতে পারছে না। Android 4.4 (API লেভেল ২০) বা তার আগের ভার্সনে রান করা ডিভাইসের ক্ষেত্রে, আপনাকে ইনস্টল করার সময় dist:fusing ম্যানিফেস্ট প্রপার্টি ব্যবহার করে ফিচার মডিউল অন্তর্ভুক্ত করতে হবে। আরও জানতে, ফিচার মডিউল ম্যানিফেস্ট সম্পর্কে পড়ুন।
NETWORK_ERROR নেটওয়ার্কের সমস্যা থাকার কারণে অনুরোধটি সম্পূর্ণ করা যায়নি। ব্যবহারকারীকে নেটওয়ার্ক কানেকশন তৈরি করতে অথবা অন্য নেটওয়ার্কে পরিবর্তন করতে প্রম্পট করুন।
ACCESS_DENIED প্রয়োজনীয় অনুমতি না থাকার কারণে অ্যাপটি অনুরোধ রেজিস্টার করতে পারছে না। অ্যাপ ব্যাকগ্রাউন্ডে থাকলে সাধারণত এটি ঘটে। অ্যাপটি ফোরগ্রাউন্ডে ফিরে এলে অনুরোধ করার চেষ্টা করুন।
INCOMPATIBLE_WITH_EXISTING_SESSION অনুরোধে এক বা একাধিক মডিউল আছে যেগুলির জন্য আগেই অনুরোধ করা হয়েছে কিন্তু এখনও ইনস্টল করা হয়নি। এমন একটি নতুন অনুরোধ তৈরি করুন যাতে আপনার অ্যাপের আগে থেকে অনুরোধ করা মডিউলগুলি অন্তর্ভুক্ত নেই, অথবা অনুরোধটি আবার চেষ্টা করার আগে বর্তমানে অনুরোধ করা সমস্ত মডিউল ইনস্টল করা শেষ হওয়ার জন্য অপেক্ষা করুন।

মনে রাখবেন, আগে থেকে ইনস্টল করা মডিউলের জন্য অনুরোধ করলে কোনও সমস্যা হয় না।

SERVICE_DIED অনুরোধ ম্যানেজ করার জন্য দায়ী পরিষেবাটি বন্ধ হয়ে গেছে। অনুরোধটি আবার করুন।

আপনার SplitInstallStateUpdatedListener এই ত্রুটি কোড, স্ট্যাটাস FAILED এবং সেশন আইডি -1 সহ SplitInstallSessionState পায়।

INSUFFICIENT_STORAGE ফিচার মডিউল ইনস্টল করার জন্য ডিভাইসে পর্যাপ্ত ফ্রি স্টোরেজ নেই। এই ফিচার ইনস্টল করার জন্য ব্যবহারকারীর কাছে পর্যাপ্ত স্টোরেজ নেই বলে তাকে বিজ্ঞপ্তি পাঠান।
SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR SplitCompat ফিচার মডিউল লোড করতে পারেনি। অ্যাপটি আবার চালু করার পরে এই সমস্যাগুলি অটোমেটিক সমাধান হয়ে যাবে।
PLAY_STORE_NOT_FOUND ডিভাইসে Play Store অ্যাপ ইনস্টল করা নেই। ব্যবহারকারীকে জানান যে এই ফিচার ডাউনলোড করতে Play Store অ্যাপ প্রয়োজন।
APP_NOT_OWNED অ্যাপটি Google Play থেকে ইনস্টল করা হয়নি এবং ফিচারটি ডাউনলোড করা যাবে না। এই সমস্যা শুধুমাত্র পরে ইনস্টল করার ক্ষেত্রে হতে পারে। আপনি যদি চান যে ব্যবহারকারী Google Play থেকে অ্যাপটি পান, তাহলে startInstall() ব্যবহার করুন যা প্রয়োজনীয় ব্যবহারকারীর কনফার্মেশন পেতে পারে।
INTERNAL_ERROR Play Store-এ একটি ইন্টার্নাল সমস্যা হয়েছে। অনুরোধটি আবার করুন।

কোনও ব্যবহারকারী অন-ডিমান্ড মডিউল ডাউনলোড করার অনুরোধ করলে এবং কোনও সমস্যা হলে, ব্যবহারকারীকে দুটি বিকল্প সহ একটি ডায়ালগ দেখানোর কথা বিবেচনা করুন: আবার চেষ্টা করুন (যা আবার অনুরোধ করার চেষ্টা করে) এবং বাতিল করুন (যা অনুরোধ বাতিল করে)। অতিরিক্ত সহায়তার জন্য, আপনাকে সহায়তা লিঙ্কও প্রদান করতে হবে যা ব্যবহারকারীদের Google Play সহায়তা কেন্দ্রে নিয়ে যায়।

স্টেট আপডেট ম্যানেজ করা

আপনি লিসেনার রেজিস্টার করার পরে এবং আপনার অনুরোধের জন্য সেশন আইডি রেকর্ড করার পরে, StateUpdatedListener.onStateUpdate() ব্যবহার করুন যাতে নিচে দেখানো পদ্ধতি অনুযায়ী স্ট্যাটাস পরিবর্তন ম্যানেজ করা যায়।

Kotlin

override fun onStateUpdate(state : SplitInstallSessionState) {
    if (state.status() == SplitInstallSessionStatus.FAILED
        && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) {
       // Retry the request.
       return
    }
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            SplitInstallSessionStatus.DOWNLOADING -> {
              val totalBytes = state.totalBytesToDownload()
              val progress = state.bytesDownloaded()
              // Update progress bar.
            }
            SplitInstallSessionStatus.INSTALLED -> {

              // After a module is installed, you can start accessing its content or
              // fire an intent to start an activity in the installed module.
              // For other use cases, see access code and resources from installed modules.

              // If the request is an on demand module for an Android Instant App
              // running on Android 8.0 (API level 26) or higher, you need to
              // update the app context using the SplitInstallHelper API.
            }
        }
    }
}

জাভা

@Override
public void onStateUpdate(SplitInstallSessionState state) {
    if (state.status() == SplitInstallSessionStatus.FAILED
        && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) {
       // Retry the request.
       return;
    }
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            case SplitInstallSessionStatus.DOWNLOADING:
              int totalBytes = state.totalBytesToDownload();
              int progress = state.bytesDownloaded();
              // Update progress bar.
              break;

            case SplitInstallSessionStatus.INSTALLED:

              // After a module is installed, you can start accessing its content or
              // fire an intent to start an activity in the installed module.
              // For other use cases, see access code and resources from installed modules.

              // If the request is an on demand module for an Android Instant App
              // running on Android 8.0 (API level 26) or higher, you need to
              // update the app context using the SplitInstallHelper API.
        }
    }
}

আপনার ইনস্টল করার অনুরোধের সম্ভাব্য স্ট্যাটাস নিচের সারণীতে বর্ণনা করা হয়েছে।

অনুরোধের স্ট্যাটাস বর্ণনা সাজেস্ট করা অ্যাকশন
বাকি আছে অনুরোধটি গ্রহণ করা হয়েছে এবং ডাউনলোড শীঘ্রই শুরু হবে। ডাউনলোড সম্পর্কে ব্যবহারকারীকে মতামত দিতে, প্রোগ্রেস বারের মতো UI কম্পোনেন্ট শুরু করুন।
REQUIRES_USER_CONFIRMATION ডাউনলোড করার জন্য ব্যবহারকারীর কনফার্মেশন প্রয়োজন। সাধারণত, Google Play-এর মাধ্যমে অ্যাপ ইনস্টল করা না হলে এই স্ট্যাটাস দেখা যায়। Google Play-এর মাধ্যমে ফিচার ডাউনলোড করার জন্য ব্যবহারকারীকে প্রম্পট করুন। আরও জানতে, কীভাবে ব্যবহারকারীর কনফার্মেশন পাওয়া যায় সেই সংক্রান্ত বিভাগে যান।
ডাউনলোড হচ্ছে ডাউনলোড করা হচ্ছে। ডাউনলোডের জন্য প্রোগ্রেস বার দেখালে, UI আপডেট করতে SplitInstallSessionState.bytesDownloaded() এবং SplitInstallSessionState.totalBytesToDownload() মেথড ব্যবহার করুন (এই টেবিলের উপরে কোড স্যাম্পেল দেখুন)।
ডাউনলোড করা হয়েছে ডিভাইস মডিউল ডাউনলোড করেছে কিন্তু ইনস্টলেশন এখনও শুরু হয়নি। ডাউনলোড করা মডিউল অ্যাক্সেস করতে এবং এই স্ট্যাটাস এড়াতে অ্যাপগুলিকে SplitCompat চালু করতে হবে। ফিচার মডিউলের কোড ও রিসোর্স অ্যাক্সেস করার জন্য এটি প্রয়োজন।
ইনস্টল করা হচ্ছে ডিভাইসটি বর্তমানে মডিউল ইনস্টল করছে। প্রোগ্রেস বার আপডেট করুন। এই অবস্থা সাধারণত অল্প সময়ের জন্য থাকে।
ইনস্টল করা আছে ডিভাইসে মডিউল ইনস্টল করা আছে। ব্যবহারকারীর অভিজ্ঞতা চালিয়ে যেতে মডিউলে অ্যাক্সেস কোড ও রিসোর্স।

Android 8.0 (API লেভেল ২৬) বা তার পরবর্তী যেকোনও ভার্সনে চলা Android Instant App-এর জন্য মডিউল হলে, নতুন মডিউলের সাথে অ্যাপ কম্পোনেন্ট আপডেট করতে আপনাকে splitInstallHelper ব্যবহার করতে হবে।

ব্যর্থ হয়েছে ডিভাইসে মডিউল ইনস্টল করার আগেই অনুরোধটি ব্যর্থ হয়েছে। ব্যবহারকারীকে অনুরোধটি আবার চেষ্টা করতে বা বাতিল করতে প্রম্পট করুন।
বাতিল করা হচ্ছে ডিভাইসটি অনুরোধ বাতিল করার প্রসেসে রয়েছে। আরও জানতে, কীভাবে ইনস্টল করার অনুরোধ বাতিল করবেন সেই সংক্রান্ত বিভাগে যান।
বাতিল করা হয়েছে অনুরোধ বাতিল করা হয়েছে।

ব্যবহারকারীর কনফার্মেশন পাওয়া

কিছু ক্ষেত্রে, ডাউনলোডের অনুরোধ পূরণ করার আগে Google Play-এর ব্যবহারকারীর কনফার্মেশনের প্রয়োজন হতে পারে। যেমন, আপনার অ্যাপ Google Play থেকে ইনস্টল করা না হলে অথবা মোবাইল ডেটা ব্যবহার করে বড় সাইজের ফাইল ডাউনলোড করার চেষ্টা করলে। এই ধরনের ক্ষেত্রে, অনুরোধের স্ট্যাটাস REQUIRES_USER_CONFIRMATION দেখায় এবং ডিভাইসে অনুরোধ করা মডিউল ডাউনলোড ও ইনস্টল করার আগে আপনার অ্যাপকে ব্যবহারকারীর থেকে কনফার্মেশন নিতে হয়। কনফার্মেশন পেতে, আপনার অ্যাপকে ব্যবহারকারীকে এইভাবে প্রম্পট করতে হবে:

Kotlin

override fun onSessionStateUpdate(state: SplitInstallSessionState) {
    if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
        // Displays a confirmation for the user to confirm the request.
        splitInstallManager.startConfirmationDialogForResult(
          state,
          // an activity result launcher registered via registerForActivityResult
          activityResultLauncher)
    }
    ...
 }

জাভা

@Override void onSessionStateUpdate(SplitInstallSessionState state) {
    if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
        // Displays a confirmation for the user to confirm the request.
        splitInstallManager.startConfirmationDialogForResult(
          state,
          // an activity result launcher registered via registerForActivityResult
          activityResultLauncher);
    }
    ...
 }

আপনি বিল্ট-ইন ActivityResultContracts.StartIntentSenderForResult কন্ট্র্যাক্ট ব্যবহার করে অ্যাক্টিভিটি রেজাল্ট লঞ্চার রেজিস্টার করতে পারবেন। অ্যাক্টিভিটি ফলাফল API দেখুন।

ব্যবহারকারীর উত্তরের উপর নির্ভর করে অনুরোধের স্ট্যাটাস আপডেট করা হয়:

  • ব্যবহারকারী কনফার্মেশন গ্রহণ করলে, অনুরোধের স্ট্যাটাস পরিবর্তন হয়ে PENDING হয়ে যায় এবং ডাউনলোড শুরু হয়।
  • ব্যবহারকারী কনফার্মেশন বাতিল করলে, অনুরোধের স্ট্যাটাস পরিবর্তন হয়ে CANCELED হয়ে যায়।
  • ডায়ালগ ধ্বংস হওয়ার আগে ব্যবহারকারী কোনও বিকল্প বেছে না নিলে, অনুরোধের স্ট্যাটাস REQUIRES_USER_CONFIRMATION হিসেবেই থেকে যায়। অনুরোধ সম্পূর্ণ করার জন্য আপনার অ্যাপ ব্যবহারকারীকে আবার প্রম্পট করতে পারে।

ব্যবহারকারীর উত্তর সহ কলব্যাক পেতে, আপনি নিচে দেখানো ActivityResultCallback ওভাররাইড করতে পারেন।

Kotlin

registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> {
        // Handle the user's decision. For example, if the user selects "Cancel",
        // you may want to disable certain functionality that depends on the module.
    }
}

জাভা

registerForActivityResult(
    new ActivityResultContracts.StartIntentSenderForResult(),
    new ActivityResultCallback<ActivityResult>() {
        @Override
        public void onActivityResult(ActivityResult result) {
            // Handle the user's decision. For example, if the user selects "Cancel",
            // you may want to disable certain functionality that depends on the module.
        }
    });

ইনস্টল করার অনুরোধ বাতিল করা

আপনার অ্যাপ ইনস্টল হওয়ার আগে কোনও অনুরোধ বাতিল করতে হলে, এটি অনুরোধের সেশন আইডি ব্যবহার করে cancelInstall() পদ্ধতি চালু করতে পারে, যেমন নিচে দেখানো হয়েছে।

Kotlin

splitInstallManager
    // Cancels the request for the given session ID.
    .cancelInstall(mySessionId)

জাভা

splitInstallManager
    // Cancels the request for the given session ID.
    .cancelInstall(mySessionId);

অ্যাক্সেস মডিউল

ডাউনলোড করা মডিউল থেকে কোড ও রিসোর্স অ্যাক্সেস করতে, আপনার অ্যাপকে SplitCompat লাইব্রেরি চালু করতে হবে। এটি আপনার অ্যাপ এবং আপনার অ্যাপের ডাউনলোড করা ফিচার মডিউলের প্রতিটি অ্যাক্টিভিটির জন্য করতে হবে।

তবে, আপনাকে মনে রাখতে হবে যে, মডিউল ডাউনলোড করার পরে কিছু সময়ের জন্য (কিছু ক্ষেত্রে কয়েক দিন) মডিউলের কন্টেন্ট অ্যাক্সেস করার ক্ষেত্রে প্ল্যাটফর্ম নিম্নলিখিত বিধিনিষেধের সম্মুখীন হয়:

  • মডিউলের মাধ্যমে নিয়ে আসা কোনও নতুন ম্যানিফেস্ট এন্ট্রি প্ল্যাটফর্ম প্রয়োগ করতে পারবে না।
  • সিস্টেম UI কম্পোনেন্টের জন্য প্ল্যাটফর্মটি মডিউলের রিসোর্স অ্যাক্সেস করতে পারে না, যেমন বিজ্ঞপ্তি। এই ধরনের রিসোর্স অবিলম্বে ব্যবহার করার প্রয়োজন হলে, আপনার অ্যাপের বেস মডিউলে সেইসব রিসোর্স অন্তর্ভুক্ত করার কথা বিবেচনা করুন।

SplitCompat চালু করুন

ডাউনলোড করা মডিউল থেকে আপনার অ্যাপ যাতে কোড ও রিসোর্স অ্যাক্সেস করতে পারে, তার জন্য আপনাকে SplitCompat চালু করতে হবে। এটি করার জন্য নিম্নলিখিত বিভাগে বর্ণিত পদ্ধতিগুলির মধ্যে যেকোনও একটি ব্যবহার করুন।

আপনার অ্যাপের জন্য SplitCompat চালু করার পরে, আপনি অ্যাপকে যে ফিচার মডিউল অ্যাক্সেস করার অনুমতি দিতে চান, সেটির প্রতিটি অ্যাক্টিভিটির জন্য SplitCompat চালু করতে হবে।

ম্যানিফেস্টে SplitCompatApplication ঘোষণা করুন

SplitCompat চালু করার সবচেয়ে সহজ উপায় হল, আপনার অ্যাপের ম্যানিফেস্টে SplitCompatApplication-কে Application সাবক্লাস হিসেবে ঘোষণা করা, যেমন নিচে দেখানো হয়েছে:

<application
    ...
    android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
</application>

কোনও ডিভাইসে অ্যাপ ইনস্টল করার পরে, আপনি ডাউনলোড করা ফিচার মডিউল থেকে অটোমেটিক কোড ও রিসোর্স অ্যাক্সেস করতে পারবেন।

রানটাইমে SplitCompat চালু করুন

এছাড়াও, রানটাইমে নির্দিষ্ট অ্যাক্টিভিটি বা পরিষেবায় SplitCompat চালু করতে পারবেন। ফিচার মডিউলে অন্তর্ভুক্ত অ্যাক্টিভিটি লঞ্চ করার জন্য এইভাবে SplitCompat চালু করা প্রয়োজন। এটি করতে, নিচে দেখানো attachBaseContext ওভাররাইড করুন।

আপনার যদি কাস্টম Application ক্লাস থাকে, তাহলে আপনার অ্যাপের জন্য SplitCompat চালু করতে, নিচে দেখানো কোডের মতো করে SplitCompatApplication এক্সটেন্ড করুন:

Kotlin

class MyApplication : SplitCompatApplication() {
    ...
}

জাভা

public class MyApplication extends SplitCompatApplication {
    ...
}

SplitCompatApplication, ContextWrapper.attachBaseContext()-কে ওভাররাইড করে SplitCompat.install(Context applicationContext)-কে অন্তর্ভুক্ত করে। আপনি যদি Application ক্লাসকে SplitCompatApplication-এ এক্সটেন্ড করতে না চান, তাহলে attachBaseContext() পদ্ধতি ম্যানুয়ালি ওভাররাইড করতে পারবেন, যেমন:

Kotlin

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    // Emulates installation of future on demand modules using SplitCompat.
    SplitCompat.install(this)
}

জাভা

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of future on demand modules using SplitCompat.
    SplitCompat.install(this);
}

আপনার অন-ডিমান্ড মডিউল ইনস্ট্যান্ট অ্যাপ ও ইনস্টল করা অ্যাপ, উভয়ের সাথেই মানানসই হলে, আপনি SplitCompat-কে নিম্নলিখিতভাবে শর্তসাপেক্ষে কল করতে পারবেন:

Kotlin

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    if (!InstantApps.isInstantApp(this)) {
        SplitCompat.install(this)
    }
}

জাভা

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    if (!InstantApps.isInstantApp(this)) {
        SplitCompat.install(this);
    }
}

মডিউল অ্যাক্টিভিটির জন্য SplitCompat চালু করুন

আপনার বেস অ্যাপের জন্য SplitCompat চালু করার পরে, আপনার অ্যাপ ফিচার মডিউলে ডাউনলোড করে এমন প্রতিটি অ্যাক্টিভিটির জন্য আপনাকে SplitCompat চালু করতে হবে। এটি করতে, SplitCompat.installActivity() পদ্ধতি ব্যবহার করুন, যেমন:

Kotlin

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    // Emulates installation of on demand modules using SplitCompat.
    SplitCompat.installActivity(this)
}

জাভা

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of on demand modules using SplitCompat.
    SplitCompat.installActivity(this);
}

ফিচার মডিউলে উল্লেখ করা কম্পোনেন্ট অ্যাক্সেস করা

ফিচার মডিউলে উল্লেখ করা অ্যাক্টিভিটি শুরু করা

SplitCompat চালু করার পরে আপনি startActivity() ব্যবহার করে ফিচার মডিউলে উল্লেখ করা অ্যাক্টিভিটি চালু করতে পারবেন।

Kotlin

startActivity(Intent()
  .setClassName("com.package", "com.package.module.MyActivity")
  .setFlags(...))

জাভা

startActivity(new Intent()
  .setClassName("com.package", "com.package.module.MyActivity")
  .setFlags(...));

setClassName-এর প্রথম প্যারামিটার হল অ্যাপের প্যাকেজের নাম এবং দ্বিতীয় প্যারামিটার হল অ্যাক্টিভিটির সম্পূর্ণ ক্লাস নাম।

আপনার চাহিদা অনুযায়ী ডাউনলোড করা ফিচার মডিউলে কোনও অ্যাক্টিভিটি থাকলে, আপনাকে অবশ্যই অ্যাক্টিভিটিতে SplitCompat চালু করতে হবে।

ফিচার মডিউলে উল্লেখ করা কোনও পরিষেবা চালু করা

SplitCompat চালু করার পরে startService() ব্যবহার করে আপনি ফিচার মডিউলে নির্দিষ্ট করা পরিষেবা চালু করতে পারবেন।

Kotlin

startService(Intent()
  .setClassName("com.package", "com.package.module.MyService")
  .setFlags(...))

জাভা

startService(new Intent()
  .setClassName("com.package", "com.package.module.MyService")
  .setFlags(...));

ফিচার মডিউলে উল্লেখ করা কম্পোনেন্ট এক্সপোর্ট করুন

ঐচ্ছিক মডিউলের মধ্যে এক্সপোর্ট করা Android কম্পোনেন্ট অন্তর্ভুক্ত করা উচিত নয়।

বিল্ড সিস্টেম সব মডিউলের জন্য ম্যানিফেস্ট এন্ট্রি বেস মডিউলে মার্জ করে; যদি কোনও ঐচ্ছিক মডিউলে এক্সপোর্ট করা কম্পোনেন্ট থাকে, তাহলে মডিউল ইনস্টল করার আগেই সেটি অ্যাক্সেস করা যাবে এবং অন্য অ্যাপ থেকে কল করার সময় কোড না থাকার কারণে ক্র্যাশ করতে পারে।

এটি ইন্টার্নাল কম্পোনেন্টের ক্ষেত্রে কোনও সমস্যা নয়; সেগুলি শুধুমাত্র অ্যাপের মাধ্যমেই অ্যাক্সেস করা হয়, তাই কম্পোনেন্ট অ্যাক্সেস করার আগে অ্যাপটি মডিউল ইনস্টল করা আছে কিনা তা চেক করতে পারে।

আপনার যদি কোনও এক্সপোর্ট করা কম্পোনেন্ট প্রয়োজন হয় এবং আপনি চান যে এর কন্টেন্ট একটি ঐচ্ছিক মডিউলে থাকুক, তাহলে একটি প্রক্সি প্যাটার্ন প্রয়োগ করার কথা বিবেচনা করুন। আপনি বেসে একটি প্রক্সি এক্সপোর্ট করা কম্পোনেন্ট যোগ করে এটি করতে পারেন; অ্যাক্সেস করা হলে, প্রক্সি কম্পোনেন্টটি কন্টেন্ট থাকা মডিউলের উপস্থিতি চেক করতে পারে। মডিউলটি থাকলে, প্রক্সি কম্পোনেন্ট Intent-এর মাধ্যমে মডিউল থেকে ইন্টার্নাল কম্পোনেন্ট শুরু করতে পারে, কলার অ্যাপ থেকে ইনটেন্ট রিলে করে। মডিউলটি না থাকলে, কম্পোনেন্ট মডিউলটি ডাউনলোড করতে পারে বা কলার অ্যাপে উপযুক্ত ত্রুটি মেসেজ ফেরত পাঠাতে পারে।

ইনস্টল করা মডিউল থেকে কোড ও রিসোর্স অ্যাক্সেস করা

আপনার বেস অ্যাপ্লিকেশন কনটেক্সট এবং ফিচার মডিউলের অ্যাক্টিভিটির জন্য SplitCompat চালু করলে, ঐচ্ছিক মডিউল ইনস্টল করার পরে, আপনি ফিচার মডিউলের কোড এবং রিসোর্স এমনভাবে ব্যবহার করতে পারবেন যেন এটি বেস APK-এর অংশ।

অন্য মডিউল থেকে অ্যাক্সেস কোড

মডিউল থেকে বেস কোড অ্যাক্সেস করা

আপনার বেস মডিউলের মধ্যে থাকা কোড সরাসরি অন্যান্য মডিউল ব্যবহার করতে পারে। আপনাকে বিশেষ কিছু করতে হবে না; শুধু আপনার প্রয়োজনীয় ক্লাস ইমপোর্ট করে ব্যবহার করুন।

অন্য মডিউল থেকে মডিউল কোড অ্যাক্সেস করুন

একটি মডিউলের মধ্যে থাকা অবজেক্ট বা ক্লাস অন্য মডিউল থেকে সরাসরি স্ট্যাটিক্যালি অ্যাক্সেস করা যায় না, তবে রিফ্লেকশন ব্যবহার করে তা পরোক্ষভাবে অ্যাক্সেস করা যায়।

রিফ্লেকশনের পারফর্ম্যান্স সংক্রান্ত খরচের কারণে, এটি কত ঘন ঘন ঘটে সে সম্পর্কে আপনার সতর্ক থাকা উচিত। জটিল ব্যবহারের ক্ষেত্রে, Dagger 2-এর মতো ডিপেন্ডেন্সি ইনজেকশন ফ্রেমওয়ার্ক ব্যবহার করুন যাতে প্রতিটি অ্যাপ্লিকেশনের লাইফটাইমে একটিই রিফ্লেকশন কল করা হয়।

ইনস্ট্যান্টিয়েশনের পরে অবজেক্টের সাথে ইন্টার‍্যাকশন আরও সহজ করতে, বেস মডিউলে ইন্টারফেস এবং ফিচার মডিউলে সেটির প্রয়োগের সংজ্ঞা নির্ধারণ করার সাজেশন দেওয়া হয়। যেমন:

Kotlin

// In the base module
interface MyInterface {
  fun hello(): String
}

// In the feature module
object MyInterfaceImpl : MyInterface {
  override fun hello() = "Hello"
}

// In the base module, where we want to access the feature module code
val stringFromModule = (Class.forName("com.package.module.MyInterfaceImpl")
    .kotlin.objectInstance as MyInterface).hello();

জাভা

// In the base module
public interface MyInterface {
  String hello();
}

// In the feature module
public class MyInterfaceImpl implements MyInterface {
  @Override
  public String hello() {
    return "Hello";
  }
}

// In the base module, where we want to access the feature module code
String stringFromModule =
   ((MyInterface) Class.forName("com.package.module.MyInterfaceImpl").getConstructor().newInstance()).hello();

অন্য মডিউল থেকে রিসোর্স ও অ্যাসেট অ্যাক্সেস করা

কোনও মডিউল ইনস্টল করা হয়ে গেলে, আপনি স্ট্যান্ডার্ড উপায়ে মডিউলের মধ্যে রিসোর্স ও অ্যাসেট অ্যাক্সেস করতে পারবেন, তবে দুটি সতর্কতা মনে রাখতে হবে:

  • আপনি অন্য কোনও মডিউল থেকে রিসোর্স অ্যাক্সেস করলে, মডিউলটি রিসোর্স আইডেন্টিফায়ার অ্যাক্সেস করতে পারবে না, তবে রিসোর্সটি এখনও নাম দ্বারা অ্যাক্সেস করা যেতে পারে। মনে রাখবেন যে রিসোর্স রেফারেন্স করার জন্য যে প্যাকেজ ব্যবহার করা হয় সেটি হল মডিউলের প্যাকেজ যেখানে রিসোর্স সংজ্ঞায়িত করা হয়।
  • আপনার অ্যাপের অন্য একটি ইনস্টল করা মডিউল থেকে নতুন ইনস্টল করা মডিউলে থাকা অ্যাসেট বা রিসোর্স অ্যাক্সেস করতে চাইলে, আপনাকে অবশ্যই অ্যাপ্লিকেশন কনটেক্সট ব্যবহার করে তা করতে হবে। যে কম্পোনেন্ট রিসোর্স অ্যাক্সেস করার চেষ্টা করছে সেটির প্রসঙ্গ এখনও আপডেট করা হবে না। বিকল্প হিসেবে, আপনি সেই কম্পোনেন্ট আবার তৈরি করতে পারেন (যেমন, Activity.recreate() কল করা) অথবা ফিচার মডিউল ইনস্টল করার পরে সেটিতে SplitCompat আবার ইনস্টল করতে পারেন।

অন-ডিমান্ড ডেলিভারি ব্যবহার করে কোনও অ্যাপে নেটিভ কোড লোড করা

ফিচার মডিউলের অন-ডিমান্ড ডেলিভারি ব্যবহার করার সময় আপনার সব নেটিভ লাইব্রেরি লোড করতে আমরা ReLinker ব্যবহার করার সাজেশন দিই। ফিচার মডিউল ইনস্টল করার পরে নেটিভ লাইব্রেরি লোড করার সময় হওয়া সমস্যা ReLinker সমাধান করে। আপনি ReLinker সম্পর্কে আরও জানতে পারবেন Android JNI পরামর্শ থেকে।

ঐচ্ছিক মডিউল থেকে নেটিভ কোড লোড করা

স্প্লিট ইনস্টল করা হয়ে গেলে, আমরা ReLinker-এর মাধ্যমে এর নেটিভ কোড লোড করার সাজেশন দিই। ইনস্ট্যান্ট অ্যাপের জন্য আপনাকে এই বিশেষ পদ্ধতি ব্যবহার করতে হবে।

আপনি যদি নেটিভ কোড লোড করার জন্য System.loadLibrary() ব্যবহার করেন এবং আপনার নেটিভ লাইব্রেরি মডিউলের অন্য লাইব্রেরির উপর নির্ভর করে, তাহলে আপনাকে প্রথমে ম্যানুয়ালি অন্য লাইব্রেরি লোড করতে হবে। আপনি ReLinker ব্যবহার করলে, সমতুল্য অপারেশন হল Relinker.recursively().loadLibrary()।

আপনি যদি ঐচ্ছিক মডিউলে সংজ্ঞায়িত একটি লাইব্রেরি লোড করতে নেটিভ কোডে dlopen() ব্যবহার করেন, তাহলে এটি আপেক্ষিক লাইব্রেরি পাথের সাথে কাজ করবে না। সবচেয়ে ভালো সমাধান হল ClassLoader.findLibrary()-এর মাধ্যমে জাভা কোড থেকে লাইব্রেরির অ্যাবসোলিউট পাথ ফিরিয়ে আনা এবং তারপরে আপনার dlopen() কলে এটি ব্যবহার করা। নেটিভ কোড লেখার আগে এটি করুন অথবা আপনার নেটিভ কোড থেকে জাভাতে JNI কল ব্যবহার করুন।

ইনস্টল করা Android Instant Apps অ্যাক্সেস করুন

Android Instant App মডিউল INSTALLED হিসেবে রিপোর্ট করার পরে, আপনি রিফ্রেশ করা অ্যাপ Context ব্যবহার করে এর কোড ও রিসোর্স অ্যাক্সেস করতে পারবেন। কোনও মডিউল ইনস্টল করার আগে আপনার অ্যাপ যে কনটেক্সট তৈরি করে (যেমন, যেটি আগে থেকেই কোনও ভেরিয়েবলে স্টোর করা আছে) তাতে নতুন মডিউলের কন্টেন্ট থাকে না। তবে, নতুন প্রসঙ্গ তা করে—এটি পাওয়া যেতে পারে, যেমন, createPackageContext ব্যবহার করে।

Kotlin

// Generate a new context as soon as a request for a new module
// reports as INSTALLED.
override fun onStateUpdate(state: SplitInstallSessionState ) {
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            ...
            SplitInstallSessionStatus.INSTALLED -> {
                val newContext = context.createPackageContext(context.packageName, 0)
                // If you use AssetManager to access your app’s raw asset files, you’ll need
                // to generate a new AssetManager instance from the updated context.
                val am = newContext.assets
            }
        }
    }
}

জাভা

// Generate a new context as soon as a request for a new module
// reports as INSTALLED.
@Override
public void onStateUpdate(SplitInstallSessionState state) {
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            ...
            case SplitInstallSessionStatus.INSTALLED:
                Context newContext = context.createPackageContext(context.getPackageName(), 0);
                // If you use AssetManager to access your app’s raw asset files, you’ll need
                // to generate a new AssetManager instance from the updated context.
                AssetManager am = newContext.getAssets();
        }
    }
}

Android 8.0 এবং তার পরবর্তী যেকোনও ভার্সনে Android Instant Apps

Android 8.0 (API লেভেল ২৬) এবং তার পরবর্তী ভার্সনে Android Instant App-এর জন্য অন-ডিমান্ড মডিউলের অনুরোধ করার সময়, ইনস্টল করার অনুরোধ INSTALLED হিসেবে রিপোর্ট করার পরে, আপনাকে SplitInstallHelper.updateAppInfo(Context context)-এ কল করার মাধ্যমে নতুন মডিউলের প্রসঙ্গে অ্যাপটি আপডেট করতে হবে। অন্যথায়, অ্যাপটি এখনও মডিউলের কোড এবং রিসোর্স সম্পর্কে অবগত নয়। অ্যাপের মেটাডেটা আপডেট করার পরে, পরবর্তী মূল থ্রেড ইভেন্টের সময় নতুন Handler কল করে আপনার মডিউলের কন্টেন্ট লোড করা উচিত, যেমন নিচে দেখানো হয়েছে:

Kotlin

override fun onStateUpdate(state: SplitInstallSessionState ) {
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            ...
            SplitInstallSessionStatus.INSTALLED -> {
                // You need to perform the following only for Android Instant Apps
                // running on Android 8.0 (API level 26) and higher.
                if (BuildCompat.isAtLeastO()) {
                    // Updates the app’s context with the code and resources of the
                    // installed module.
                    SplitInstallHelper.updateAppInfo(context)
                    Handler().post {
                        // Loads contents from the module using AssetManager
                        val am = context.assets
                        ...
                    }
                }
            }
        }
    }
}

জাভা

@Override
public void onStateUpdate(SplitInstallSessionState state) {
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            ...
            case SplitInstallSessionStatus.INSTALLED:
            // You need to perform the following only for Android Instant Apps
            // running on Android 8.0 (API level 26) and higher.
            if (BuildCompat.isAtLeastO()) {
                // Updates the app’s context with the code and resources of the
                // installed module.
                SplitInstallHelper.updateAppInfo(context);
                new Handler().post(new Runnable() {
                    @Override public void run() {
                        // Loads contents from the module using AssetManager
                        AssetManager am = context.getAssets();
                        ...
                    }
                });
            }
        }
    }
}

C/C++ লাইব্রেরি লোড করুন

ডিভাইস আগে থেকেই ইনস্ট্যান্ট অ্যাপে ডাউনলোড করেছে এমন কোনও মডিউল থেকে আপনি C/C++ লাইব্রেরি লোড করতে চাইলে, SplitInstallHelper.loadLibrary(Context context, String libName) ব্যবহার করুন, যেমন নিচে দেখানো হয়েছে:

Kotlin

override fun onStateUpdate(state: SplitInstallSessionState) {
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            SplitInstallSessionStatus.INSTALLED -> {
                // Updates the app’s context as soon as a module is installed.
                val newContext = context.createPackageContext(context.packageName, 0)
                // To load C/C++ libraries from an installed module, use the following API
                // instead of System.load().
                SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”)
                ...
            }
        }
    }
}

জাভা

public void onStateUpdate(SplitInstallSessionState state) {
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            case SplitInstallSessionStatus.INSTALLED:
                // Updates the app’s context as soon as a module is installed.
                Context newContext = context.createPackageContext(context.getPackageName(), 0);
                // To load C/C++ libraries from an installed module, use the following API
                // instead of System.load().
                SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”);
                ...
        }
    }
}

পরিচিত সীমাবদ্ধতা

  • কোনও অ্যাক্টিভিটিতে Android WebView ব্যবহার করা সম্ভব নয় যা ঐচ্ছিক মডিউল থেকে রিসোর্স বা অ্যাসেট অ্যাক্সেস করে। Android API লেভেল ২৮ এবং তার নিচের ভার্সনে WebView এবং SplitCompat-এর মধ্যে অসঙ্গতির কারণে এটি হয়।
  • আপনি Android ApplicationInfo অবজেক্ট, সেগুলির কন্টেন্ট বা আপনার অ্যাপের মধ্যে সেগুলি আছে এমন অবজেক্ট ক্যাশে করতে পারবেন না। অ্যাপের প্রসঙ্গ থেকে প্রয়োজন অনুযায়ী আপনাকে সবসময় এইসব অবজেক্ট ফেচ করতে হবে। এই ধরনের অবজেক্ট ক্যাশে করলে, ফিচার মডিউল ইনস্টল করার সময় অ্যাপ ক্র্যাশ করতে পারে।

ইনস্টল করা মডিউল ম্যানেজ করুন

ডিভাইসে বর্তমানে কোন ফিচার মডিউল ইনস্টল করা আছে তা চেক করতে, আপনি SplitInstallManager.getInstalledModules() কল করতে পারেন, যা ইনস্টল করা মডিউলের নামের একটি Set<String> রিটার্ন করে, যেমনটি নিচে দেখানো হয়েছে।

Kotlin

val installedModules: Set<String> = splitInstallManager.installedModules

জাভা

Set<String> installedModules = splitInstallManager.getInstalledModules();

মডিউল আনইনস্টল করুন

আপনি নিচে দেখানো SplitInstallManager.deferredUninstall(List<String> moduleNames) ইনভোক করে ডিভাইসকে মডিউল আনইনস্টল করার অনুরোধ করতে পারেন।

Kotlin

// Specifies two feature modules for deferred uninstall.
splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))

জাভা

// Specifies two feature modules for deferred uninstall.
splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));

মডিউল আনইনস্টল করার সাথে সাথেই তা কার্যকর হয় না। অর্থাৎ, স্টোরেজ স্পেস বাঁচাতে ডিভাইস ব্যাকগ্রাউন্ডে প্রয়োজন অনুযায়ী সেগুলি আনইনস্টল করে দেয়। আপনি কনফার্ম করতে পারেন যে ডিভাইসটি SplitInstallManager.getInstalledModules() ইনভোক করে এবং ফলাফল পরীক্ষা করে একটি মডিউল মুছে দিয়েছে, যেমনটি আগের বিভাগে বর্ণনা করা হয়েছে।

অতিরিক্ত ভাষা সংক্রান্ত রিসোর্স ডাউনলোড করুন

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

আপনি যদি চান যে আপনার অ্যাপে অতিরিক্ত ভাষা রিসোর্সের অ্যাক্সেস থাকুক—যেমন, ইন-অ্যাপ ভাষা বাছাইকারী প্রয়োগ করতে, আপনি চাহিদা অনুযায়ী সেগুলি ডাউনলোড করতে Play ফিচার ডেলিভারি লাইব্রেরি ব্যবহার করতে পারেন। এই প্রসেসটি ফিচার মডিউল ডাউনলোড করার মতোই, যেমন নিচে দেখানো হয়েছে।

Kotlin

// Captures the user’s preferred language and persists it
// through the app’s SharedPreferences.
sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply()
...

// Creates a request to download and install additional language resources.
val request = SplitInstallRequest.newBuilder()
        // Uses the addLanguage() method to include French language resources in the request.
        // Note that country codes are ignored. That is, if your app
        // includes resources for “fr-FR” and “fr-CA”, resources for both
        // country codes are downloaded when requesting resources for "fr".
        .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
        .build()

// Submits the request to install the additional language resources.
splitInstallManager.startInstall(request)

জাভা

// Captures the user’s preferred language and persists it
// through the app’s SharedPreferences.
sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply();
...

// Creates a request to download and install additional language resources.
SplitInstallRequest request =
    SplitInstallRequest.newBuilder()
        // Uses the addLanguage() method to include French language resources in the request.
        // Note that country codes are ignored. That is, if your app
        // includes resources for “fr-FR” and “fr-CA”, resources for both
        // country codes are downloaded when requesting resources for "fr".
        .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
        .build();

// Submits the request to install the additional language resources.
splitInstallManager.startInstall(request);

অনুরোধটি এমনভাবে ম্যানেজ করা হয় যেন এটি কোনও ফিচার মডিউলের জন্য করা অনুরোধ। অর্থাৎ, আপনি সাধারণত যেভাবে করেন, সেভাবেই অনুরোধের স্ট্যাটাস মনিটর করতে পারবেন।

আপনার অ্যাপের যদি অবিলম্বে অতিরিক্ত ভাষা রিসোর্সের প্রয়োজন না হয়, তাহলে আপনি অ্যাপটি ব্যাকগ্রাউন্ডে থাকাকালীন ইনস্টলেশন স্থগিত করতে পারেন, যেমন নিচে দেখানো হয়েছে।

Kotlin

splitInstallManager.deferredLanguageInstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))

জাভা

splitInstallManager.deferredLanguageInstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));

ডাউনলোড করা ভাষার রিসোর্স অ্যাক্সেস করুন

ডাউনলোড করা ভাষা রিসোর্স অ্যাক্সেস করতে, আপনার অ্যাপকে প্রতিটি অ্যাক্টিভিটির attachBaseContext() মেথডের মধ্যে SplitCompat.installActivity() মেথড রান করতে হবে, যেটির জন্য নিচে দেখানো হিসেবে সেইসব রিসোর্স অ্যাক্সেস করতে হবে।

Kotlin

override fun attachBaseContext(base: Context) {
  super.attachBaseContext(base)
  SplitCompat.installActivity(this)
}

জাভা

@Override
protected void attachBaseContext(Context base) {
  super.attachBaseContext(base);
  SplitCompat.installActivity(this);
}

আপনার অ্যাপ ডাউনলোড করেছে এমন ভাষা রিসোর্স ব্যবহার করতে চান এমন প্রতিটি অ্যাক্টিভিটির জন্য, বেস কনটেক্সট আপডেট করুন এবং এর মাধ্যমে একটি নতুন লোকেল সেট করুন Configuration:

Kotlin

override fun attachBaseContext(base: Context) {
  val configuration = Configuration()
  configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
  val context = base.createConfigurationContext(configuration)
  super.attachBaseContext(context)
  SplitCompat.install(this)
}

জাভা

@Override
protected void attachBaseContext(Context base) {
  Configuration configuration = new Configuration();
  configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
  Context context = base.createConfigurationContext(configuration);
  super.attachBaseContext(context);
  SplitCompat.install(this);
}

এইসব পরিবর্তন কার্যকর করতে, নতুন ভাষা ইনস্টল করা এবং ব্যবহারের জন্য প্রস্তুত হওয়ার পরে আপনাকে অ্যাক্টিভিটি আবার তৈরি করতে হবে। আপনি Activity#recreate() পদ্ধতি ব্যবহার করতে পারেন।

Kotlin

when (state.status()) {
  SplitInstallSessionStatus.INSTALLED -> {
      // Recreates the activity to load resources for the new language
      // preference.
      activity.recreate()
  }
  ...
}

জাভা

switch (state.status()) {
  case SplitInstallSessionStatus.INSTALLED:
      // Recreates the activity to load resources for the new language
      // preference.
      activity.recreate();
  ...
}

অতিরিক্ত ভাষা সংক্রান্ত রিসোর্স আনইনস্টল করুন

ফিচার মডিউলের মতো, আপনি যেকোনও সময় অতিরিক্ত রিসোর্স আনইনস্টল করতে পারবেন। আনইনস্টল করার অনুরোধ করার আগে, আপনি প্রথমে কোন কোন ভাষা বর্তমানে ইনস্টল করা আছে তা নির্ধারণ করতে চাইতে পারেন, যেমন নিচে দেখানো হয়েছে।

Kotlin

val installedLanguages: Set<String> = splitInstallManager.installedLanguages

জাভা

Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();

তারপর আপনি সিদ্ধান্ত নিতে পারবেন যে কোন ভাষা আনইনস্টল করবেন। এর জন্য নিচে দেখানো deferredLanguageUninstall() পদ্ধতি ব্যবহার করুন।

Kotlin

splitInstallManager.deferredLanguageUninstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))

জাভা

splitInstallManager.deferredLanguageUninstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));

লোকালি টেস্ট মডিউল ইনস্টল করে

Play ফিচার ডেলিভারি লাইব্রেরি আপনাকে Play Store-এ কানেক্ট না করেই নিম্নলিখিত কাজগুলি করার জন্য আপনার অ্যাপের ক্ষমতা স্থানীয়ভাবে পরীক্ষা করার অনুমতি দেয়:

এই পৃষ্ঠায় আপনার অ্যাপের স্প্লিট APK কীভাবে টেস্ট ডিভাইসে ডেপ্লয় করবেন তা বর্ণনা করা হয়েছে যাতে Play ফিচার ডেলিভারি অটোমেটিক সেইসব APK ব্যবহার করে Play Store থেকে মডিউল অনুরোধ, ডাউনলোড ও ইনস্টল করার সিমুলেশন করতে পারে।

আপনার অ্যাপের লজিকে কোনও পরিবর্তন করার প্রয়োজন না থাকলেও, আপনাকে নিম্নলিখিত শর্ত পূরণ করতে হবে:

  • bundletool-এর লেটেস্ট ভার্সন ডাউনলোড ও ইনস্টল করুন। আপনার অ্যাপের বান্ডেল থেকে ইনস্টল করা যায় এমন APK-এর নতুন সেট তৈরি করতে bundletool প্রয়োজন।

APK-এর একটি সেট তৈরি করুন

আপনি আগে থেকে এটি না করে থাকলে, নিম্নলিখিত উপায়ে আপনার অ্যাপের স্প্লিট APK তৈরি করুন:

  1. নিম্নলিখিত পদ্ধতিগুলির মধ্যে যেকোনও একটি ব্যবহার করে আপনার অ্যাপের জন্য অ্যাপ বান্ডেল তৈরি করুন:
  2. নিম্নলিখিত কমান্ডের সাহায্যে সব ডিভাইস কনফিগারেশনের জন্য APK-এর একটি সেট তৈরি করতে bundletool ব্যবহার করুন:

    bundletool build-apks --local-testing
      --bundle my_app.aab
      --output my_app.apks
    

--local-testing ফ্ল্যাগ আপনার APK-এর ম্যানিফেস্টে মেটা-ডেটা অন্তর্ভুক্ত করে যা Play ফিচার ডেলিভারি লাইব্রেরিকে Play Store-এ কানেক্ট না করেই ফিচার মডিউল ইনস্টল করার পরীক্ষা করতে লোকাল স্প্লিট APK ব্যবহার করার অনুমতি দেয়।

ডিভাইসে আপনার অ্যাপ ডিপ্লয় করুন

--local-testing ফ্ল্যাগ ব্যবহার করে এপিকে (APK)-এর সেট তৈরি করার পরে, আপনার অ্যাপের বেস ভার্সন ইনস্টল করতে bundletool ব্যবহার করুন এবং আপনার ডিভাইসের লোকাল স্টোরেজে অতিরিক্ত এপিকে (APK) ট্রান্সফার করুন। আপনি নিম্নলিখিত কমান্ডের সাহায্যে দুটি অ্যাকশনই সম্পাদন করতে পারবেন:

bundletool install-apks --apks my_app.apks

এখন, আপনি অ্যাপ চালু করে ফিচার মডিউল ডাউনলোড ও ইনস্টল করার জন্য ব্যবহারকারীর ফ্লো সম্পূর্ণ করলে, Play ফিচার ডেলিভারি লাইব্রেরি সেই APK ব্যবহার করে যা bundletool ডিভাইসের লোকাল স্টোরেজে ট্রান্সফার করেছে।

নেটওয়ার্কের সমস্যা সিমুলেট করুন

Play Store থেকে মডিউল ইনস্টল সিমুলেট করতে, Play ফিচার ডেলিভারি লাইব্রেরি SplitInstallManager-এর বিকল্প হিসেবে FakeSplitInstallManager ব্যবহার করে মডিউলের জন্য অনুরোধ করে। APK-এর সেট তৈরি করতে এবং আপনার টেস্ট ডিভাইসে সেগুলি ডেপ্লয় করতে --local-testing ফ্ল্যাগ সহ bundletool ব্যবহার করলে, এতে মেটাডেটা অন্তর্ভুক্ত থাকে যা Play ফিচার ডেলিভারি লাইব্রেরিকে নির্দেশ দেয় যাতে আপনার অ্যাপের API কল অটোমেটিক পাল্টে SplitInstallManager-এর পরিবর্তে FakeSplitInstallManager-কে কল করা হয়।

FakeSplitInstallManager-এ একটি বুলিয়ান ফ্ল্যাগ অন্তর্ভুক্ত থাকে যা আপনি চালু করতে পারেন যাতে পরের বার আপনার অ্যাপ কোনও মডিউল ইনস্টল করার অনুরোধ করলে নেটওয়ার্কের সমস্যা সিমুলেট করা যায়। আপনার টেস্টে FakeSplitInstallManager অ্যাক্সেস করতে, FakeSplitInstallManagerFactory ব্যবহার করে আপনি এটির একটি ইনস্ট্যান্স পেতে পারেন, যেমন নিচে দেখানো হয়েছে:

Kotlin

// Creates an instance of FakeSplitInstallManager with the app's context.
val fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context)
// Tells Play Feature Delivery Library to force the next module request to
// result in a network error.
fakeSplitInstallManager.setShouldNetworkError(true)

জাভা

// Creates an instance of FakeSplitInstallManager with the app's context.
FakeSplitInstallManager fakeSplitInstallManager =
    FakeSplitInstallManagerFactory.create(context);
// Tells Play Feature Delivery Library to force the next module request to
// result in a network error.
fakeSplitInstallManager.setShouldNetworkError(true);