চাহিদা ডেলিভারি কনফিগার করুন

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

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

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

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

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

চাহিদা অনুযায়ী ডেলিভারির জন্য একটি নতুন মডিউল কনফিগার করুন

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

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

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

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

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

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

      <dist:module ...>
          <dist:fusing dist:include="true | false" />
      </dist:module>
      
  7. শেষ ক্লিক করুন.

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

এর পরে, আপনাকে প্লে ফিচার ডেলিভারি লাইব্রেরি ব্যবহার করে অন ডিমান্ড ইনস্টল কার্যকারিতা বাস্তবায়ন করতে হবে।

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

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

একটি চাহিদা মডিউল অনুরোধ করুন

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

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

কোটলিন

// 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 -> { ... });

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

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

মডিউলের কোড এবং সংস্থানগুলিতে অ্যাক্সেস পেতে, আপনার অ্যাপটিকে SplitCompat সক্ষম করতে হবে। মনে রাখবেন যে অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপের জন্য SplitCompat এর প্রয়োজন নেই।

চাহিদা মডিউল ইনস্টলেশন বিলম্বিত

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

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

কোটলিন

// 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() টাস্ক থেকে স্টেট আপডেট শুনতে হবে। আপনি আপনার ইনস্টল অনুরোধের জন্য আপডেটগুলি পেতে শুরু করার আগে, একজন শ্রোতা নিবন্ধন করুন এবং অনুরোধের জন্য সেশন আইডি পান, যেমনটি নীচে দেখানো হয়েছে৷

কোটলিন

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

অনুরোধের ত্রুটিগুলি পরিচালনা করুন

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

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

কোটলিন

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 প্লে ফিচার ডেলিভারি লাইব্রেরি বর্তমান ডিভাইসে সমর্থিত নয়। অর্থাৎ ডিভাইসটি চাহিদা অনুযায়ী ফিচার ডাউনলোড ও ইনস্টল করতে সক্ষম নয়। Android 4.4 (API লেভেল 20) বা তার কম চলমান ডিভাইসগুলির জন্য, আপনি 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 প্লে স্টোর অ্যাপটি ডিভাইসে ইনস্টল করা নেই। ব্যবহারকারীকে জানিয়ে দিন যে এই বৈশিষ্ট্যটি ডাউনলোড করার জন্য প্লে স্টোর অ্যাপের প্রয়োজন।
APP_NOT_OWNED অ্যাপটি Google Play দ্বারা ইনস্টল করা হয়নি এবং বৈশিষ্ট্যটি ডাউনলোড করা যাবে না। এই ত্রুটি শুধুমাত্র বিলম্বিত ইনস্টলের জন্য ঘটতে পারে। আপনি যদি ব্যবহারকারীকে Google Play-তে অ্যাপটি অর্জন করতে চান, startInstall() ব্যবহার করুন যা প্রয়োজনীয় ব্যবহারকারীর নিশ্চয়তা পেতে পারে।
অভ্যন্তরীণ_ত্রুটি প্লে স্টোরের মধ্যে একটি অভ্যন্তরীণ ত্রুটি ঘটেছে৷ অনুরোধ পুনরায় চেষ্টা করুন.

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

রাষ্ট্রীয় আপডেটগুলি পরিচালনা করুন

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

কোটলিন

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 লেভেল 26) বা উচ্চতর সংস্করণে চলমান একটি Android Instant অ্যাপের জন্য হয়, তাহলে নতুন মডিউলের সাথে অ্যাপের উপাদান আপডেট করতে আপনাকে splitInstallHelper ব্যবহার করতে হবে।

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

ব্যবহারকারী নিশ্চিতকরণ প্রাপ্ত

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

কোটলিন

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 ওভাররাইড করতে পারেন।

কোটলিন

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() পদ্ধতি ব্যবহার করতে পারে।

কোটলিন

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 ওভাররাইড করুন।

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

কোটলিন

class MyApplication : SplitCompatApplication() {
    ...
}

জাভা

public class MyApplication extends SplitCompatApplication {
    ...
}

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

কোটলিন

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 চালু করতে পারেন, নিম্নরূপ:

কোটলিন

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() পদ্ধতিটি ব্যবহার করুন, নিম্নরূপ:

কোটলিন

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() ব্যবহার করে বৈশিষ্ট্য মডিউলগুলিতে সংজ্ঞায়িত ক্রিয়াকলাপগুলি চালু করতে পারেন।

কোটলিন

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

জাভা

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

setClassName প্রথম প্যারামিটারটি অ্যাপের প্যাকেজের নাম এবং দ্বিতীয় প্যারামিটারটি কার্যকলাপের পুরো ক্লাসের নাম।

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

একটি বৈশিষ্ট্য মডিউলে সংজ্ঞায়িত একটি পরিষেবা শুরু করুন

আপনি স্প্লিটকম্প্যাট সক্ষম করার পরে startService() ব্যবহার করে বৈশিষ্ট্য মডিউলগুলিতে সংজ্ঞায়িত পরিষেবাগুলি চালু করতে পারেন।

কোটলিন

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-এর একটি অংশ।

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

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

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

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

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

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

ইন্সট্যান্টেশনের পরে বস্তুর সাথে মিথস্ক্রিয়া সহজ করার জন্য, বেস মডিউলে একটি ইন্টারফেস এবং বৈশিষ্ট্য মডিউলে এর বাস্তবায়নের সংজ্ঞায়িত করার সুপারিশ করা হয়। উদাহরণস্বরূপ:

কোটলিন

// 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 একটি বৈশিষ্ট্য মডিউল ইনস্টল করার পরে নেটিভ লাইব্রেরি লোড করার একটি সমস্যা সমাধান করে। আপনি Android JNI টিপসে ReLinker সম্পর্কে আরও জানতে পারবেন।

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

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

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

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

ইনস্টল করা Android ঝটপট অ্যাপ অ্যাক্সেস করুন

একটি অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপ মডিউল INSTALLED হিসাবে রিপোর্ট করার পরে, আপনি একটি রিফ্রেশ করা অ্যাপ প্রসঙ্গ ব্যবহার করে এর কোড এবং সংস্থানগুলি অ্যাক্সেস করতে পারেন৷ একটি মডিউল ইনস্টল করার আগে আপনার অ্যাপ তৈরি করে এমন একটি প্রসঙ্গ (উদাহরণস্বরূপ, যেটি ইতিমধ্যে একটি ভেরিয়েবলে সংরক্ষিত আছে) তাতে নতুন মডিউলের বিষয়বস্তু থাকে না। কিন্তু একটি নতুন প্রসঙ্গ আছে—এটি পাওয়া যেতে পারে, উদাহরণস্বরূপ, createPackageContext ব্যবহার করে।

কোটলিন

// 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 লেভেল 26) এবং উচ্চতর একটি Android Instant App-এর জন্য একটি অন ডিমান্ড মডিউলের অনুরোধ করার সময়, একটি ইন্সটল রিকোয়েস্ট INSTALLED হিসাবে রিপোর্ট করার পরে, আপনাকে SplitInstallHelper.updateAppInfo(Context context) তে একটি কলের মাধ্যমে নতুন মডিউলের প্রসঙ্গে অ্যাপটি আপডেট করতে হবে। SplitInstallHelper.updateAppInfo(Context context) । অন্যথায়, অ্যাপটি এখনও মডিউলের কোড এবং সংস্থান সম্পর্কে সচেতন নয়। অ্যাপের মেটাডেটা আপডেট করার পরে, আপনাকে পরবর্তী প্রধান থ্রেড ইভেন্টের সময় একটি নতুন Handler আহ্বান করে মডিউলের বিষয়বস্তু লোড করতে হবে, যেমনটি নীচে দেখানো হয়েছে:

কোটলিন

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) ব্যবহার করুন:

কোটলিন

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 ব্যবহার করা সম্ভব নয়। এটি অ্যান্ড্রয়েড এপিআই লেভেল 28 এবং তার নিচের ওয়েবভিউ এবং স্প্লিটকম্প্যাটের মধ্যে একটি অসামঞ্জস্যতার কারণে।
  • আপনি Android ApplicationInfo অবজেক্ট, তাদের বিষয়বস্তু বা আপনার অ্যাপের মধ্যে থাকা বস্তুগুলি ক্যাশে করতে পারবেন না। আপনি সবসময় একটি অ্যাপ্লিকেশন প্রসঙ্গ থেকে প্রয়োজন হিসাবে এই বস্তুগুলি আনয়ন করা উচিত. ফিচার মডিউল ইনস্টল করার সময় এই ধরনের অবজেক্ট ক্যাশ করার ফলে অ্যাপটি ক্র্যাশ হতে পারে।

ইনস্টল করা মডিউল পরিচালনা করুন

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

কোটলিন

val installedModules: Set<String> = splitInstallManager.installedModules

জাভা

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

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

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

কোটলিন

// 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() ব্যবহার করে এবং ফলাফল পরিদর্শন করে একটি মডিউল মুছে দিয়েছে, যেমনটি পূর্ববর্তী বিভাগে বর্ণিত হয়েছে।

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

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

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

কোটলিন

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

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

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

কোটলিন

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

জাভা

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

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

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

কোটলিন

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

জাভা

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

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

কোটলিন

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() পদ্ধতি ব্যবহার করতে পারেন।

কোটলিন

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();
  ...
}

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

বৈশিষ্ট্য মডিউল অনুরূপ, আপনি যে কোনো সময় অতিরিক্ত সম্পদ আনইনস্টল করতে পারেন. একটি আনইনস্টল করার অনুরোধ করার আগে, আপনি প্রথমে নির্ধারণ করতে চাইতে পারেন যে কোন ভাষাগুলি বর্তমানে ইনস্টল করা আছে, নিম্নরূপ।

কোটলিন

val installedLanguages: Set<String> = splitInstallManager.installedLanguages

জাভা

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

তারপর আপনি deferredLanguageUninstall() পদ্ধতি ব্যবহার করে কোন ভাষাগুলিকে আনইনস্টল করতে হবে তা নির্ধারণ করতে পারেন, যেমনটি নীচে দেখানো হয়েছে।

কোটলিন

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

জাভা

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

স্থানীয়ভাবে পরীক্ষা মডিউল ইনস্টল

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

  • অনুরোধ এবং মডিউল ইনস্টল মনিটর.
  • ইনস্টলেশন ত্রুটিগুলি পরিচালনা করুন।
  • মডিউল অ্যাক্সেস করতে SplitCompat ব্যবহার করুন।

এই পৃষ্ঠাটি বর্ণনা করে যে কীভাবে আপনার পরীক্ষা ডিভাইসে আপনার অ্যাপের বিভক্ত APKগুলি স্থাপন করতে হয় যাতে প্লে বৈশিষ্ট্য ডেলিভারি স্বয়ংক্রিয়ভাবে সেই APKগুলিকে প্লে স্টোর থেকে মডিউলগুলিকে অনুরোধ, ডাউনলোড এবং ইনস্টল করার অনুকরণ করতে ব্যবহার করে৷

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

  • 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 বৈশিষ্ট্য ডেলিভারি লাইব্রেরীকে প্লে স্টোরের সাথে সংযোগ না করেই বৈশিষ্ট্য মডিউল ইনস্টল করার জন্য স্থানীয় স্প্লিট APK ব্যবহার করতে দেয়।

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

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

bundletool install-apks --apks my_app.apks

এখন, যখন আপনি আপনার অ্যাপটি শুরু করেন এবং একটি বৈশিষ্ট্য মডিউল ডাউনলোড এবং ইনস্টল করার জন্য ব্যবহারকারীর প্রবাহ সম্পূর্ণ করেন, প্লে ফিচার ডেলিভারি লাইব্রেরি এমন APK ব্যবহার করে যা ডিভাইসের স্থানীয় স্টোরেজে bundletool হয়।

একটি নেটওয়ার্ক ত্রুটি অনুকরণ

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

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

কোটলিন

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

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

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

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

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

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

চাহিদা অনুযায়ী ডেলিভারির জন্য একটি নতুন মডিউল কনফিগার করুন

একটি নতুন বৈশিষ্ট্য মডিউল তৈরির সহজতম উপায় হ'ল অ্যান্ড্রয়েড স্টুডিও 3.5 বা তার বেশি ব্যবহার করে। কারণ বৈশিষ্ট্য মডিউলগুলির বেস অ্যাপ মডিউলটির উপর অন্তর্নিহিত নির্ভরতা রয়েছে, আপনি সেগুলি কেবল বিদ্যমান অ্যাপ্লিকেশন প্রকল্পগুলিতে যুক্ত করতে পারেন।

অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে আপনার অ্যাপ্লিকেশন প্রকল্পে একটি বৈশিষ্ট্য মডিউল যুক্ত করতে, নিম্নলিখিত হিসাবে এগিয়ে যান:

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

    1. 50 টি অক্ষর ব্যবহার করে মডিউল শিরোনাম নির্দিষ্ট করুন। প্ল্যাটফর্মটি ব্যবহারকারীদের কাছে মডিউলটি সনাক্ত করতে এই শিরোনামটি ব্যবহার করে যখন উদাহরণস্বরূপ, ব্যবহারকারী মডিউলটি ডাউনলোড করতে চান কিনা তা নিশ্চিত করে। এই কারণে, আপনার অ্যাপ্লিকেশনটির বেস মডিউলটিতে অবশ্যই মডিউল শিরোনামটি স্ট্রিং রিসোর্স হিসাবে অন্তর্ভুক্ত করা উচিত, যা আপনি অনুবাদ করতে পারেন। অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে মডিউলটি তৈরি করার সময়, আইডিই আপনার জন্য বেস মডিউলটিতে স্ট্রিং রিসোর্স যুক্ত করে এবং বৈশিষ্ট্য মডিউলটির ম্যানিফেস্টে নিম্নলিখিত এন্ট্রি ইনজেকশন দেয়:

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

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

      <dist:module ...>
          <dist:fusing dist:include="true | false" />
      </dist:module>
      
  7. শেষ ক্লিক করুন.

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

এরপরে, আপনাকে প্লে বৈশিষ্ট্য বিতরণ লাইব্রেরি ব্যবহার করে অন ডিমান্ড ইনস্টল কার্যকারিতা প্রয়োগ করতে হবে।

আপনার প্রকল্পে প্লে বৈশিষ্ট্য বিতরণ গ্রন্থাগার অন্তর্ভুক্ত করুন

আপনি শুরু করার আগে আপনাকে প্রথমে আপনার প্রকল্পে প্লে বৈশিষ্ট্য বিতরণ গ্রন্থাগারটি যুক্ত করতে হবে।

একটি অন চাহিদা মডিউল অনুরোধ

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

উদাহরণস্বরূপ, ডিভাইসের ক্যামেরাটি ব্যবহার করে চিত্র বার্তাগুলি ক্যাপচার এবং প্রেরণের জন্য একটি অন চাহিদা মডিউল রয়েছে এমন একটি অ্যাপ্লিকেশন বিবেচনা করুন এবং এটি অন ডিমান্ড মডিউলটি তার ম্যানিফেস্টে split="pictureMessages" নির্দিষ্ট করে। নিম্নলিখিত নমুনায় pictureMessages মডিউলটির জন্য অনুরোধ করতে SplitInstallManager ব্যবহার করা হয়েছে (কিছু প্রচারমূলক ফিল্টারগুলির জন্য অতিরিক্ত মডিউল সহ):

কোটলিন

// 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 -> { ... });

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

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

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

অন ​​ডিমান্ড মডিউলগুলির ইনস্টলেশন স্থগিত করুন

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

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

কোটলিন

// 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() টাস্ক থেকে রাষ্ট্রীয় আপডেটগুলি শুনতে হবে। আপনি আপনার ইনস্টল অনুরোধের জন্য আপডেটগুলি গ্রহণ শুরু করার আগে, শ্রোতা নিবন্ধন করুন এবং অনুরোধটির জন্য সেশন আইডি পেতে নীচে দেখানো হয়েছে।

কোটলিন

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

অনুরোধের ত্রুটিগুলি পরিচালনা করুন

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

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

কোটলিন

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 গুগল প্লে অ্যাপ্লিকেশন, ডিভাইস এবং ব্যবহারকারীর গুগল প্লে অ্যাকাউন্টের বর্তমান ইনস্টলড সংস্করণের ভিত্তিতে অনুরোধ করা মডিউলটি সন্ধান করতে অক্ষম। যদি ব্যবহারকারীর মডিউলটিতে অ্যাক্সেস না থাকে তবে সেগুলি অবহিত করুন।
INVALID_REQUEST গুগল প্লে অনুরোধটি পেয়েছে, তবে অনুরোধটি বৈধ নয়। অনুরোধে অন্তর্ভুক্ত তথ্যগুলি সম্পূর্ণ এবং নির্ভুল কিনা তা যাচাই করুন।
SESSION_NOT_FOUND প্রদত্ত সেশন আইডির জন্য একটি সেশন পাওয়া যায় নি। আপনি যদি কোনও সেশন আইডি দ্বারা কোনও অনুরোধের অবস্থা পর্যবেক্ষণ করার চেষ্টা করছেন তবে সেশন আইডিটি সঠিক কিনা তা নিশ্চিত করুন।
API_NOT_AVAILABLE প্লে ফিচার ডেলিভারি লাইব্রেরি বর্তমান ডিভাইসে সমর্থিত নয়। এটি হ'ল, ডিভাইসটি চাহিদা অনুযায়ী বৈশিষ্ট্যগুলি ডাউনলোড এবং ইনস্টল করতে সক্ষম নয়। অ্যান্ড্রয়েড 4.4 (এপিআই স্তর 20) বা তার চেয়ে কম চলমান ডিভাইসগুলির জন্য আপনার dist:fusing ম্যানিফেস্ট সম্পত্তি ব্যবহার করে ইনস্টল করার সময় বৈশিষ্ট্য মডিউলগুলি অন্তর্ভুক্ত করা উচিত। আরও জানতে, বৈশিষ্ট্য মডিউল ম্যানিফেস্ট সম্পর্কে পড়ুন।
NETWORK_ERROR নেটওয়ার্ক ত্রুটির কারণে অনুরোধটি ব্যর্থ হয়েছিল। ব্যবহারকারীকে হয় একটি নেটওয়ার্ক সংযোগ স্থাপন করতে বা অন্য কোনও নেটওয়ার্কে পরিবর্তন করতে অনুরোধ করুন।
ACCESS_DENIED অপর্যাপ্ত অনুমতিগুলির কারণে অ্যাপ্লিকেশনটি অনুরোধটি নিবন্ধ করতে অক্ষম। এটি সাধারণত ঘটে যখন অ্যাপটি পটভূমিতে থাকে। অ্যাপ্লিকেশনটি অগ্রভাগে ফিরে এলে অনুরোধটি চেষ্টা করুন।
INCOMPATIBLE_WITH_EXISTING_SESSION অনুরোধে এক বা একাধিক মডিউল রয়েছে যা ইতিমধ্যে অনুরোধ করা হয়েছে তবে এখনও ইনস্টল করা হয়নি। হয় একটি নতুন অনুরোধ তৈরি করুন যা আপনার অ্যাপ্লিকেশনটি ইতিমধ্যে অনুরোধ করেছে এমন মডিউলগুলি অন্তর্ভুক্ত করে না, বা অনুরোধটি পুনরায় চেষ্টা করার আগে বর্তমানে অনুরোধ করা সমস্ত মডিউলগুলির জন্য অপেক্ষা করুন।

মনে রাখবেন, ইতিমধ্যে ইনস্টল করা একটি মডিউলটির জন্য অনুরোধ করা কোনও ত্রুটিতে সমাধান করে না।

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

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

INSUFFICIENT_STORAGE বৈশিষ্ট্য মডিউলটি ইনস্টল করার জন্য ডিভাইসে পর্যাপ্ত ফ্রি স্টোরেজ নেই। ব্যবহারকারীকে অবহিত করুন যে এই বৈশিষ্ট্যটি ইনস্টল করার জন্য তাদের কাছে পর্যাপ্ত স্টোরেজ নেই।
স্প্লিটকম্প্যাট_ভারিফিকেশন_অরর, স্প্লিট কমপ্যাট_মুলেশন_আরর, স্প্লিটকম্প্যাট_কপি_আররোর স্প্লিটকম্প্যাট বৈশিষ্ট্য মডিউলটি লোড করতে পারেনি। এই ত্রুটিগুলি পরবর্তী অ্যাপটি পুনরায় চালু হওয়ার পরে স্বয়ংক্রিয়ভাবে নিজেকে সমাধান করা উচিত।
PLAY_STORE_NOT_FOUND প্লে স্টোর অ্যাপটি ডিভাইসে ইনস্টল করা নেই। ব্যবহারকারীকে জানতে দিন যে প্লে স্টোর অ্যাপটি এই বৈশিষ্ট্যটি ডাউনলোড করার জন্য প্রয়োজন।
APP_NOT_OWNED অ্যাপ্লিকেশনটি গুগল প্লে দ্বারা ইনস্টল করা হয়নি এবং বৈশিষ্ট্যটি ডাউনলোড করা যাবে না। এই ত্রুটিটি কেবল স্থগিত ইনস্টলগুলির জন্য ঘটতে পারে। আপনি যদি ব্যবহারকারীকে গুগল প্লেতে অ্যাপটি অর্জন করতে চান তবে startInstall() ব্যবহার করুন যা প্রয়োজনীয় ব্যবহারকারীর নিশ্চিতকরণ পেতে পারে।
অভ্যন্তরীণ_ত্রুটি প্লে স্টোরের মধ্যে একটি অভ্যন্তরীণ ত্রুটি ঘটেছে। অনুরোধটি আবার চেষ্টা করুন।

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

রাষ্ট্রীয় আপডেটগুলি পরিচালনা করুন

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

কোটলিন

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

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

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

যদি মডিউলটি অ্যান্ড্রয়েড তাত্ক্ষণিক অ্যাপ্লিকেশনটির জন্য হয় যদি অ্যান্ড্রয়েড 8.0 (এপিআই স্তর 26) বা উচ্চতর হয় তবে আপনাকে নতুন মডিউলটির সাথে অ্যাপ্লিকেশন উপাদানগুলি আপডেট করতে splitInstallHelper ব্যবহার করতে হবে।

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

ব্যবহারকারীর নিশ্চিতকরণ পান

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

কোটলিন

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 চুক্তি ব্যবহার করে কোনও ক্রিয়াকলাপের ফলাফল প্রবর্তক নিবন্ধন করতে পারেন। ক্রিয়াকলাপের ফলাফল এপিআই দেখুন।

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

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

ব্যবহারকারীর প্রতিক্রিয়া সহ একটি কলব্যাক পেতে, আপনি নীচে প্রদর্শিত হিসাবে ক্রিয়াকলাপেরসাল্টক্যালব্যাককে ওভাররাইড করতে পারেন।

কোটলিন

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() পদ্ধতিটি অনুরোধ করতে পারে।

কোটলিন

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

জাভা

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

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

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

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

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

স্প্লিট কমপ্যাট সক্ষম করুন

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

আপনি আপনার অ্যাপ্লিকেশনটির জন্য স্প্লিটকপ্যাট সক্ষম করার পরে, আপনার অ্যাপ্লিকেশনটিতে অ্যাক্সেস থাকতে চান এমন বৈশিষ্ট্য মডিউলগুলিতে প্রতিটি ক্রিয়াকলাপের জন্য আপনাকে স্প্লিটক্যাটও সক্ষম করতে হবে।

ম্যানিফেস্টে স্প্লিট কমপ্যাট অ্যাপ্লিকেশন ঘোষণা করুন

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

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

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

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

আপনি রানটাইমে নির্দিষ্ট ক্রিয়াকলাপ বা পরিষেবাদিতে স্প্লিটক্যাটকে সক্ষম করতে পারেন। বৈশিষ্ট্য মডিউলগুলিতে অন্তর্ভুক্ত ক্রিয়াকলাপগুলি চালু করতে এইভাবে স্প্লিটকপট সক্ষম করা প্রয়োজন। এটি করার জন্য, নীচের মতো attachBaseContext ওভাররাইড করুন।

আপনার যদি কাস্টম অ্যাপ্লিকেশন ক্লাস থাকে তবে আপনার অ্যাপ্লিকেশনটির জন্য স্প্লিটক্যাট সক্ষম করার জন্য এটি পরিবর্তে SplitCompatApplication প্রসারিত করুন, নীচে দেখানো হয়েছে:

কোটলিন

class MyApplication : SplitCompatApplication() {
    ...
}

জাভা

public class MyApplication extends SplitCompatApplication {
    ...
}

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

কোটলিন

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

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

কোটলিন

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.installActivity() পদ্ধতিটি ব্যবহার করুন:

কোটলিন

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

বৈশিষ্ট্য মডিউলগুলিতে সংজ্ঞায়িত উপাদানগুলি অ্যাক্সেস করুন

একটি বৈশিষ্ট্য মডিউলে সংজ্ঞায়িত একটি ক্রিয়াকলাপ শুরু করুন

আপনি স্প্লিটকম্প্যাট সক্ষম করার পরে startActivity() ব্যবহার করে বৈশিষ্ট্য মডিউলগুলিতে সংজ্ঞায়িত ক্রিয়াকলাপগুলি চালু করতে পারেন।

কোটলিন

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

জাভা

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

setClassName প্রথম প্যারামিটারটি হ'ল অ্যাপটির প্যাকেজ নাম এবং দ্বিতীয় প্যারামিটারটি ক্রিয়াকলাপের পুরো শ্রেণীর নাম।

আপনি যখন অন-চাহিদা ডাউনলোড করেছেন এমন কোনও বৈশিষ্ট্য মডিউলটিতে আপনার কোনও ক্রিয়াকলাপ থাকে, তখন আপনাকে অবশ্যই ক্রিয়াকলাপে স্প্লিট কমপ্যাট সক্ষম করতে হবে

একটি বৈশিষ্ট্য মডিউলে সংজ্ঞায়িত একটি পরিষেবা শুরু করুন

আপনি স্প্লিটকম্প্যাট সক্ষম করার পরে startService() ব্যবহার করে বৈশিষ্ট্য মডিউলগুলিতে সংজ্ঞায়িত পরিষেবাগুলি চালু করতে পারেন।

কোটলিন

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

জাভা

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

একটি বৈশিষ্ট্য মডিউলে সংজ্ঞায়িত একটি উপাদান রফতানি করুন

আপনার al চ্ছিক মডিউলগুলির মধ্যে রফতানি করা অ্যান্ড্রয়েড উপাদানগুলি অন্তর্ভুক্ত করা উচিত নয়।

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

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

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

ইনস্টল করা মডিউলগুলি থেকে কোড এবং সংস্থানগুলি অ্যাক্সেস করুন

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

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

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

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

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

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

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

তাত্ক্ষণিকতার পরে অবজেক্টের সাথে মিথস্ক্রিয়াগুলি সহজ করার জন্য, এটি বেস মডিউলটিতে একটি ইন্টারফেস এবং বৈশিষ্ট্য মডিউলটিতে এর বাস্তবায়ন সংজ্ঞায়িত করার পরামর্শ দেওয়া হয়। উদাহরণস্বরূপ:

কোটলিন

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

একটি ভিন্ন মডিউল থেকে সংস্থান এবং সম্পদ অ্যাক্সেস করুন

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

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

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

বৈশিষ্ট্য মডিউলগুলির অন-ডিমান্ড বিতরণ ব্যবহার করার সময় আমরা আপনার সমস্ত নেটিভ লাইব্রেরি লোড করতে রিলিঙ্কার ব্যবহার করার পরামর্শ দিই। রিলিঙ্কার কোনও বৈশিষ্ট্য মডিউল ইনস্টল করার পরে দেশীয় গ্রন্থাগারগুলি লোড করার ক্ষেত্রে একটি সমস্যা সমাধান করে। আপনি অ্যান্ড্রয়েড জেএনআই টিপসে রিলিংকার সম্পর্কে আরও জানতে পারেন।

একটি al চ্ছিক মডিউল থেকে নেটিভ কোড লোড করুন

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

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

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

ইনস্টলড অ্যান্ড্রয়েড তাত্ক্ষণিক অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করুন

একটি অ্যান্ড্রয়েড তাত্ক্ষণিক অ্যাপ্লিকেশন মডিউল INSTALLED হিসাবে রিপোর্ট করার পরে, আপনি একটি রিফ্রেশ অ্যাপ্লিকেশন প্রসঙ্গ ব্যবহার করে এর কোড এবং সংস্থানগুলি অ্যাক্সেস করতে পারেন। একটি মডিউল ইনস্টল করার আগে আপনার অ্যাপ্লিকেশনটি তৈরি করে এমন একটি প্রসঙ্গ (উদাহরণস্বরূপ, ইতিমধ্যে একটি ভেরিয়েবলে সঞ্চিত একটি) নতুন মডিউলটির সামগ্রী ধারণ করে না। তবে একটি নতুন প্রসঙ্গটি করে - এটি পাওয়া যায়, উদাহরণস্বরূপ, createPackageContext ব্যবহার করে।

কোটলিন

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

অ্যান্ড্রয়েড তাত্ক্ষণিক অ্যাপ্লিকেশন অ্যান্ড্রয়েড 8.0 এবং উচ্চতর

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

কোটলিন

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();
                        ...
                    }
                });
            }
        }
    }
}

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

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

কোটলিন

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”);
                ...
        }
    }
}

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

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

ইনস্টল করা মডিউলগুলি পরিচালনা করুন

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

কোটলিন

val installedModules: Set<String> = splitInstallManager.installedModules

জাভা

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

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

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

কোটলিন

// 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() পূর্ববর্তী বিভাগে বর্ণিত হিসাবে ফলাফলটি পরিদর্শন করে একটি মডিউল মুছে ফেলেছে।

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

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

আপনি যদি চান যে আপনার অ্যাপ্লিকেশনটি অতিরিক্ত ভাষার সংস্থানগুলিতে অ্যাক্সেস পেতে পারে example প্রক্রিয়াটি নীচে দেখানো হিসাবে কোনও বৈশিষ্ট্য মডিউল ডাউনলোড করার মতো।

কোটলিন

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

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

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

কোটলিন

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

জাভা

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

ডাউনলোড করা ভাষা সংস্থান অ্যাক্সেস

ডাউনলোড করা ভাষার সংস্থানগুলিতে অ্যাক্সেস পেতে, আপনার অ্যাপ্লিকেশনটিতে প্রতিটি ক্রিয়াকলাপের attachBaseContext() পদ্ধতির মধ্যে SplitCompat.installActivity() পদ্ধতি চালানো দরকার যা নীচে দেখানো হয়েছে।

কোটলিন

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

জাভা

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

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

কোটলিন

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() ব্যবহার করতে পারেন।

কোটলিন

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();
  ...
}

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

বৈশিষ্ট্য মডিউলগুলির অনুরূপ, আপনি যে কোনও সময় অতিরিক্ত সংস্থান আনইনস্টল করতে পারেন। একটি আনইনস্টলের অনুরোধ করার আগে, আপনি প্রথমে নির্ধারণ করতে পারেন যে বর্তমানে কোন ভাষাগুলি বর্তমানে ইনস্টল করা আছে।

কোটলিন

val installedLanguages: Set<String> = splitInstallManager.installedLanguages

জাভা

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

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

কোটলিন

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

জাভা

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

স্থানীয়ভাবে পরীক্ষা মডিউল ইনস্টল

প্লে ফিচার ডেলিভারি লাইব্রেরি আপনাকে প্লে স্টোরের সাথে সংযোগ না করে স্থানীয়ভাবে আপনার অ্যাপ্লিকেশনটির নিম্নলিখিতগুলি করার ক্ষমতা পরীক্ষা করার অনুমতি দেয়:

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

যদিও আপনার অ্যাপ্লিকেশনটির যুক্তিতে আপনার কোনও পরিবর্তন করার দরকার নেই, আপনার নিম্নলিখিত প্রয়োজনীয়তাগুলি পূরণ করতে হবে:

  • ডাউনলোড করুন এবং bundletool সর্বশেষ সংস্করণটি ইনস্টল করুন। আপনার অ্যাপের বান্ডিল থেকে ইনস্টলযোগ্য এপিকগুলির একটি নতুন সেট তৈরি করতে আপনার bundletool দরকার।

APKS এর একটি সেট তৈরি করুন

আপনি যদি ইতিমধ্যে এটি না করে থাকেন তবে আপনার অ্যাপ্লিকেশনটির স্প্লিট এপিকগুলি তৈরি করুন, নিম্নরূপ:

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

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

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

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

আপনি --local-testing পতাকা ব্যবহার করে এপিকেএসের একটি সেট তৈরি করার পরে, আপনার অ্যাপ্লিকেশনটির বেস সংস্করণটি ইনস্টল করতে bundletool ব্যবহার করুন এবং আপনার ডিভাইসের স্থানীয় স্টোরেজে অতিরিক্ত এপিকে স্থানান্তর করুন। আপনি নিম্নলিখিত কমান্ড দিয়ে উভয় ক্রিয়া সম্পাদন করতে পারেন:

bundletool install-apks --apks my_app.apks

এখন, আপনি যখন আপনার অ্যাপ্লিকেশনটি শুরু করেন এবং কোনও বৈশিষ্ট্য মডিউলটি ডাউনলোড এবং ইনস্টল করতে ব্যবহারকারী প্রবাহটি সম্পূর্ণ করেন, প্লে বৈশিষ্ট্য বিতরণ লাইব্রেরিতে bundletool ডিভাইসের স্থানীয় স্টোরেজে স্থানান্তরিত এপিকগুলি ব্যবহার করে।

একটি নেটওয়ার্ক ত্রুটি অনুকরণ

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

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

কোটলিন

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

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

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

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

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

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

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

একটি নতুন বৈশিষ্ট্য মডিউল তৈরির সহজতম উপায় হ'ল অ্যান্ড্রয়েড স্টুডিও 3.5 বা তার বেশি ব্যবহার করে। কারণ বৈশিষ্ট্য মডিউলগুলির বেস অ্যাপ মডিউলটির উপর অন্তর্নিহিত নির্ভরতা রয়েছে, আপনি সেগুলি কেবল বিদ্যমান অ্যাপ্লিকেশন প্রকল্পগুলিতে যুক্ত করতে পারেন।

অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে আপনার অ্যাপ্লিকেশন প্রকল্পে একটি বৈশিষ্ট্য মডিউল যুক্ত করতে, নিম্নলিখিত হিসাবে এগিয়ে যান:

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

    1. 50 টি অক্ষর ব্যবহার করে মডিউল শিরোনাম নির্দিষ্ট করুন। প্ল্যাটফর্মটি ব্যবহারকারীদের কাছে মডিউলটি সনাক্ত করতে এই শিরোনামটি ব্যবহার করে যখন উদাহরণস্বরূপ, ব্যবহারকারী মডিউলটি ডাউনলোড করতে চান কিনা তা নিশ্চিত করে। For this reason, your app's base module must include the module title as a string resource , which you can translate. When creating the module using Android Studio, the IDE adds the string resource to the base module for you and injects the following entry in the feature module's manifest:

      <dist:module
          ...
          dist:title="@string/feature_title">
      </dist:module>
      
    2. In the dropdown menu under Install-time inclusion , select Do not include module at install-time . Android Studio injects the following in the module's manifest to reflect your choice:

      <dist:module ... >
        <dist:delivery>
            <dist:on-demand/>
        </dist:delivery>
      </dist:module>
      
    3. Check the box next to Fusing if you want this module to be available to devices running Android 4.4 (API level 20) and lower and included in multi-APKs. This means you can enable on demand behavior for this module and disable fusing to omit it from devices that don't support downloading and installing split APKs. Android Studio injects the following in the module's manifest to reflect your choice:

      <dist:module ...>
          <dist:fusing dist:include="true | false" />
      </dist:module>
      
  7. শেষ ক্লিক করুন.

After Android Studio finishes creating your module, inspect its contents yourself from the Project pane (select View > Tool Windows > Project from the menu bar). The default code, resources, and organization should be similar to those of the standard app module.

Next, you will need to implement the on demand install functionality using the Play Feature Delivery library.

Include the Play Feature Delivery Library in your project

Before you can start, you need to first add the Play Feature Delivery Library to your project.

Request an on demand module

When your app needs to use a feature module, it can request one while it's in the foreground through the SplitInstallManager class. When making a request, your app needs to specify the name of the module as defined by the split element in the target module's manifest. When you create a feature module using Android Studio, the build system uses the Module name you provide to inject this property into the module's manifest at compile time. For more information, read about the feature module manifests .

For example, consider an app that has an on demand module to capture and send picture messages using the device's camera, and this on demand module specifies split="pictureMessages" in its manifest. The following sample uses SplitInstallManager to request the pictureMessages module (along with an additional module for some promotional filters):

কোটলিন

// 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 -> { ... });

When your app requests an on demand module, the Play Feature Delivery Library employs a “fire-and-forget” strategy. That is, it sends the request to download the module to the platform, but it does not monitor whether the installation succeeded. To move the user journey forward after installation or gracefully handle errors, make sure you monitor the request state .

Note: It's okay to request a feature module that's already installed on the device. The API instantly considers the request as completed if it detects the module is already installed. Additionally, after a module is installed, Google Play keeps it updated automatically. That is, when you upload a new version of your app bundle, the platform updates all installed APKs that belong to your app. For more information, read Manage app updates .

To have access to the module's code and resources, your app needs to enable SplitCompat . Note that SplitCompat is not required for Android Instant Apps.

Defer installation of on demand modules

If you do not need your app to immediately download and install an on demand module, you can defer installation for when the app is in the background. For example, if you want to preload some promotional material for a later launch of your app.

You can specify a module to be download later using the deferredInstall() method, as shown below. And, unlike SplitInstallManager.startInstall() , your app does not need to be in the foreground to initiate a request for a deferred installation.

কোটলিন

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

Requests for deferred installs are best-effort and you cannot track their progress. So, before trying to access a module you have specified for deferred installation, you should check that the module has been installed . If you need the module to be available immediately, instead use SplitInstallManager.startInstall() to request it, as shown in the previous section.

Monitor the request state

To be able to update a progress bar, fire an intent after installation, or gracefully handle a request error, you need to listen for state updates from the asynchronous SplitInstallManager.startInstall() task. Before you can start receiving updates for your install request, register a listener and get the session ID for the request, as shown below.

কোটলিন

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

অনুরোধের ত্রুটিগুলি পরিচালনা করুন

Keep in mind that on demand installation of feature modules can sometime fail, just like app installation doesn't always succeed. Failure to install can be due to issues like low device storage, no network connectivity, or the user not being signed in to the Google Play Store. For suggestions on how to handle these situations gracefully from the user's perspective, check out our UX guidelines for on demand delivery .

Code-wise, you should handle failures downloading or installing a module using addOnFailureListener() , as shown below:

কোটলিন

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

The table below describes the error states your app may need to handle:

ত্রুটি কোড বর্ণনা ব্যবস্থা নেওয়ার পরামর্শ দিয়েছেন
ACTIVE_SESSIONS_LIMIT_EXCEEDED The request is rejected because there is at least one existing request that is currently downloading. Check if there are any requests that are still downloading, as shown in the sample above.
MODULE_UNAVAILABLE Google Play is unable to find the requested module based on the current installed version of the app, device, and user's Google Play account. If the user does not have access to the module, notify them.
INVALID_REQUEST Google Play received the request, but the request is not valid. Verify that the information included in the request is complete and accurate.
SESSION_NOT_FOUND A session for a given session ID was not found. If you're trying to monitor the state of a request by its session ID, make sure that the session ID is correct.
API_NOT_AVAILABLE The Play Feature Delivery Library is not supported on the current device. That is, the device is not able to download and install features on demand. For devices running Android 4.4 (API level 20) or lower, you should include feature modules at install time using the dist:fusing manifest property. To learn more, read about the feature module manifest .
NETWORK_ERROR The request failed because of a network error. Prompt the user to either establish a network connection or change to a different network.
ACCESS_DENIED The app is unable to register the request because of insufficient permissions. This typically occurs when the app is in the background. Attempt the request when the app returns to the foreground.
INCOMPATIBLE_WITH_EXISTING_SESSION The request contains one or more modules that have already been requested but have not yet been installed. Either create a new request that does not include modules that your app has already requested, or wait for all currently requested modules to finish installing before retrying the request.

Keep in mind, requesting a module that has already been installed does not resolve in an error.

SERVICE_DIED The service responsible for handling the request has died. Retry the request.

Your SplitInstallStateUpdatedListener receives a SplitInstallSessionState with this error code, status FAILED and session ID -1 .

INSUFFICIENT_STORAGE The device does not have enough free storage to install the feature module. Notify the user that they do not have enough storage to install this feature.
SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR SplitCompat could not load the feature module. These errors should automatically resolve themselves after the next app restart.
PLAY_STORE_NOT_FOUND The Play Store app is not installed on the device. Let the user know that the Play Store app is required to download this feature.
APP_NOT_OWNED The app has not been installed by Google Play and the feature cannot be downloaded. This error can only occur for deferred installs. If you want the user to acquire the app on Google Play, use startInstall() which can obtain the necessary user confirmation .
অভ্যন্তরীণ_ত্রুটি An internal error occurred within the Play Store. Retry the request.

If a user requests downloading an on demand module and an error occurs, consider displaying a dialog that provides two options for the user: Try again (which attempts the request again) and Cancel (which abandons the request). For additional support, you should also provide Help link that directs users to the Google Play Help center .

Handle state updates

After you register a listener and record the session ID for your request, use StateUpdatedListener.onStateUpdate() to handle state changes, as shown below.

কোটলিন

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

The possible states for your install request are described in the table below.

Request state বর্ণনা ব্যবস্থা নেওয়ার পরামর্শ দিয়েছেন
মুলতুবি The request has been accepted and the download should start soon. Initialize UI components, such as a progress bar, to provide the user feedback on the download.
REQUIRES_USER_CONFIRMATION The download requires user confirmation. Most commonly this status occurs if the app has not been installed through Google Play. Prompt the user to confirm the feature download through Google Play. To learn more, go to the section about how to obtain user confirmation .
ডাউনলোড হচ্ছে ডাউনলোড চলছে। If you provide a progress bar for the download, use the SplitInstallSessionState.bytesDownloaded() and SplitInstallSessionState.totalBytesToDownload() methods to update the UI (see the code sample above this table).
DOWNLOADED The device has downloaded the module but installation has not yet begun. Apps should enable SplitCompat to have access to downloaded modules and avoid seeing this state. This is required in order to access the feature module's code and resources.
ইনস্টল করা হচ্ছে The device is currently installing the module. Update the progress bar. This state is typically short.
INSTALLED The module is installed on the device. Access code and resource in the module to continue the user journey.

If the module is for an Android Instant App running on Android 8.0 (API level 26) or higher, you need to use splitInstallHelper to update app components with the new module .

ব্যর্থ হয়েছে The request failed before the module was installed on the device. Prompt the user to either retry the request or cancel it.
CANCELING The device is in the process of cancelling the request. To learn more, go to the section about how to cancel an install request .
বাতিল করা হয়েছে The request has been cancelled.

Obtain user confirmation

In some cases, Google Play may require user confirmation before satisfying a download request. For example, if your app has not been installed by Google Play or if you are attempting a large download over mobile data. In such cases, the status for the request reports REQUIRES_USER_CONFIRMATION , and your app needs to obtain user confirmation before the device is able to download and install the modules in the request. To obtain confirmation, your app should prompt the user as follows:

কোটলিন

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

You can register an activity result launcher using the builtin ActivityResultContracts.StartIntentSenderForResult contract. See Activity Result APIs .

The status for the request is updated depending on the user response:

  • If the user accepts the confirmation, the request status changes to PENDING and the download proceeds.
  • If the user denies the confirmation, the request status changes to CANCELED .
  • If the user does not make a selection before the dialog is destroyed, the request status remains as REQUIRES_USER_CONFIRMATION . Your app can prompt the user again to complete the request.

To receive a callback with the user's response, you can override the ActivityResultCallback as shown below.

কোটলিন

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

Cancel an install request

If your app needs to cancel a request before it is installed, it can invoke the cancelInstall() method using the request's session ID, as shown below.

কোটলিন

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

জাভা

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

Access modules

To access code and resources from a downloaded module after it is downloaded, your app needs to enable the SplitCompat Library for both your app and each activity in the feature modules your app downloads.

You should note, however, the platform experiences the following restrictions to accessing contents of a module, for some time (days, in some cases) after downloading the module:

  • The platform can not apply any new manifest entries introduced by the module.
  • The platform can not access the module's resources for system UI components, such as notifications. If you need to use such resources immediately, consider including those resource in the base module of your app.

Enable SplitCompat

For your app to access code and resources from a downloaded module, you need to enable SplitCompat using only one of the methods described in the following sections.

After you enable SplitCompat for your app, you need to also enable SplitCompat for each activity in the feature modules you want your app to have access to.

Declare SplitCompatApplication in the manifest

The simplest way to enable SplitCompat is to declare SplitCompatApplication as the Application subclass in your app's manifest, as shown below:

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

After the app is installed on a device, you can access code and resources from downloaded feature modules automatically.

Invoke SplitCompat at runtime

You can also enable SplitCompat in specific activities or services at runtime. Enabling SplitCompat this way is required to launch activities included in feature modules. To do this, override attachBaseContext as seen below.

If you have a custom Application class, have it instead extend SplitCompatApplication in order to enable SplitCompat for your app, as shown below:

কোটলিন

class MyApplication : SplitCompatApplication() {
    ...
}

জাভা

public class MyApplication extends SplitCompatApplication {
    ...
}

SplitCompatApplication simply overrides ContextWrapper.attachBaseContext() to include SplitCompat.install(Context applicationContext) . If you don't want your Application class to extend SplitCompatApplication , you can override the attachBaseContext() method manually, as follows:

কোটলিন

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

If your on demand module is compatible with both instant apps and installed apps, you can invoke SplitCompat conditionally, as follows:

কোটলিন

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

Enable SplitCompat for module activities

After you enable SplitCompat for your base app, you need to enable SplitCompat for each activity that your app downloads in a feature module. To do so, use the SplitCompat.installActivity() method, as follows:

কোটলিন

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

Access components defined in feature modules

Start an activity defined in a feature module

You can launch activities defined in feature modules using startActivity() after enabling SplitCompat.

কোটলিন

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

জাভা

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

The first parameter to setClassName is the package name of the app and the second parameter is the full class name of the activity.

When you have an activity in a feature module you downloaded on-demand, you must enable SplitCompat in the activity .

Start a service defined in a feature module

You can launch services defined in feature modules using startService() after enabling SplitCompat.

কোটলিন

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

জাভা

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

Export a component defined in a feature module

You should not include exported Android components inside optional modules.

The build system merges manifest entries for all modules into the base module; if an optional module contained an exported component, it would be accessible even before the module is installed and can cause a crash due to missing code when invoked from another app.

This is not a problem for internal components; they are accessed only by the app, so the app can check that the module is installed before accessing the component.

If you need an exported component, and you want its content to be in an optional module, consider implementing a proxy pattern. You can do that by adding a proxy exported component in the base; when accessed, the proxy component can check for the presence of the module that contains the content. If the module is present, the proxy component can start the internal component from the module via an Intent , relaying the intent from the caller app. If the module is not present, the component can download the module or return an appropriate error message to the caller app.

Access code and resources from installed modules

If you enable SplitCompat for your base application context and the activities in your feature module, you can use the code and resources from a feature module as if it were a part of the base APK, once the optional module is installed.

Access code from a different module

Access base code from a module

Code that is inside your base module can be used directly by other modules. You don't need to do anything special; just import and use the classes you need.

Access module code from another module

An object or class inside a module cannot be statically accessed from another module directly, but it can be accessed indirectly, using reflection.

You should be wary of how often this happens, due to the performance costs of reflection. For complex use cases, use dependency injection frameworks like Dagger 2 to guarantee a single reflection call per application lifetime.

To simplify the interactions with the object after instantiation, it is recommended to define an interface in the base module and its implementation in the feature module. উদাহরণস্বরূপ:

কোটলিন

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

Access resources and assets from a different module

Once a module is installed, you can access resources and assets within the module in the standard way, with two caveats:

  • If you are accessing a resource from a different module, the module will not have access to the resource identifier, though the resource can still be accessed by name. Note that the package to use to reference the resource is the package of the module where the resource is defined.
  • If you want to access assets or resources that exist in a newly installed module from a different installed module of your app, you must do so using the application context . The context of the component that's trying to access the resources will not yet be updated. Alternatively, you can recreate that component (for instance calling Activity.recreate() ) or reinstall SplitCompat on it after the feature module installation.

Load native code in an app using on-demand delivery

We recommend using ReLinker to load all your native libraries when using on-demand delivery of feature modules. ReLinker fixes an issue in loading native libraries after the installation of a feature module. You can learn more about ReLinker in the Android JNI Tips .

Load native code from an optional module

Once a split is installed, we recommend loading its native code through ReLinker . For instant apps you should use this special method .

If you are using System.loadLibrary() to load your native code and your native library has a dependency on another library in the module, you must manually load that other library first. If you are using ReLinker, the equivalent operation is Relinker.recursively().loadLibrary() .

If you are using dlopen() in native code to load a library defined in an optional module, it will not work with relative library paths. The best solution is to retrieve the absolute path of the library from Java code via ClassLoader.findLibrary() and then use it in your dlopen() call. Do this before entering the native code or use a JNI call from your native code into Java.

Access installed Android Instant Apps

After an Android Instant App module reports as INSTALLED , you can access its code and resources using a refreshed app Context . A context that your app creates before installing a module (for example, one that's already stored in a variable) does not contain the content of the new module. But a fresh context does—this can be obtained, for example, using createPackageContext .

কোটলিন

// 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 Instant Apps on Android 8.0 and higher

When requesting an on demand module for an Android Instant App on Android 8.0 (API level 26) and higher, after an install request reports as INSTALLED , you need to update the app with the context of the new module through a call to SplitInstallHelper.updateAppInfo(Context context) . Otherwise, the app is not yet aware of the module's code and resources. After updating the app's metadata, you should load the module's contents during the next main thread event by invoking a new Handler , as shown below:

কোটলিন

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();
                        ...
                    }
                });
            }
        }
    }
}

Load C/C++ libraries

If you want to load C/C++ libraries from a module that the device has already downloaded in an Instant App, use SplitInstallHelper.loadLibrary(Context context, String libName) , as shown below:

কোটলিন

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”);
                ...
        }
    }
}

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

  • It isn't possible to use Android WebView in an activity that accesses resources or assets from an optional module. This is due to an incompatibility between WebView and SplitCompat on Android API level 28 and lower.
  • You can't cache Android ApplicationInfo objects, their contents, or objects that contain them within your app. You should always fetch these objects as needed from an app context. Caching such objects could cause the app to crash when installing a feature module.

Manage installed modules

To check which feature modules are currently installed on the device, you can call SplitInstallManager.getInstalledModules() , which returns a Set<String> of the names of the installed modules, as shown below.

কোটলিন

val installedModules: Set<String> = splitInstallManager.installedModules

জাভা

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

Uninstall modules

You can request the device to uninstall modules by invoking SplitInstallManager.deferredUninstall(List<String> moduleNames) , as shown below.

কোটলিন

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

Module uninstalls do not occur immediately. That is, the device uninstalls them in the background as needed to save storage space. You can confirm that the device has deleted a module by invoking SplitInstallManager.getInstalledModules() and inspecting the result, as described in the previous section.

Download additional language resources

With app bundles, devices download only the code and resources they require to run your app. So, for language resources, a user's device downloads only your app's language resources that match the one or more languages currently selected in the device's settings.

If you want your app to have access to additional language resources—for example, to implement an in-app language picker, you can use the Play Feature Delivery Library to download them on demand. The process is similar to that of downloading a feature module, as shown below.

কোটলিন

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

The request is handled as if it were a request for a feature module. That is, you can monitor the request state like you normally would.

If your app doesn't require the additional language resources immediately, you can defer the installation for when the app is in the background, as shown below.

কোটলিন

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

জাভা

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

Access downloaded language resources

To gain access to downloaded language resources, your app needs to run the SplitCompat.installActivity() method within the attachBaseContext() method of each activity that requires access to those resources, as shown below.

কোটলিন

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

জাভা

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

For each activity you want to use language resources your app has downloaded, update the base context and set a new locale through its Configuration :

কোটলিন

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

In order for these changes to take effect, you have to recreate your activity after the new language is installed and ready to use. You can use the Activity#recreate() method.

কোটলিন

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();
  ...
}

Uninstall additional language resources

Similar to feature modules, you can uninstall additional resources at any time. Before requesting an uninstall, you may want to first determine which languages are currently installed, as follows.

কোটলিন

val installedLanguages: Set<String> = splitInstallManager.installedLanguages

জাভা

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

You can then decide which languages to uninstall using the deferredLanguageUninstall() method, as shown below.

কোটলিন

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

জাভা

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

Locally test module installs

The Play Feature Delivery Library allows you to locally test your app's ability to do the following, without connecting to the Play Store:

This page describes how to deploy your app's split APKs to your test device so that Play Feature Delivery automatically uses those APKs to simulate requesting, downloading, and installing modules from the Play Store.

Although you don't need to make any changes to your app's logic, you need to meet the following requirements:

Build a set of APKs

If you haven't already done so, build your app's split APKs, as follows:

  1. Build an app bundle for your app using one of the following methods:
  2. Use bundletool to generate a set of APKs for all device configurations with the following command:

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

The --local-testing flag includes meta-data in your APKs' manifests that lets the Play Feature Delivery Library know to use the local split APKs to test installing feature modules, without connecting to the Play Store.

Deploy your app to the device

After you build a set of APKs using the --local-testing flag, use bundletool to install the base version of your app and transfer additional APKs to your device's local storage. You can perform both actions with the following command:

bundletool install-apks --apks my_app.apks

Now, when you start your app and complete the user flow to download and install a feature module, the Play Feature Delivery Library uses the APKs that bundletool transferred to the device's local storage.

Simulate a network error

To simulate module installs from the Play Store, the Play Feature Delivery Library uses an alternative to the SplitInstallManager , called FakeSplitInstallManager , to request the module. When you use bundletool with the --local-testing flag to build a set of APKs and deploy them to your test device, it includes metadata that instructs the Play Feature Delivery Library to automatically switch your app's API calls to invoke FakeSplitInstallManager , instead of SplitInstallManager .

FakeSplitInstallManager includes a boolean flag that you can enable to simulate a network error the next time your app requests to install a module. To access FakeSplitInstallManager in your tests, you can get an instance of it using the FakeSplitInstallManagerFactory , as shown below:

কোটলিন

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

Feature modules allow you to separate certain features and resources from the base module of your app and include them in your app bundle. Through Play Feature Delivery, users can, for example, later download and install those components on demand after they've already installed the base APK of your app.

For example, consider a text messaging app that includes functionality for capturing and sending picture messages, but only a small percentage of users send picture messages. It may make sense to include picture messaging as a downloadable feature module. That way, the initial app download is smaller for all users and only those users who send picture messages need to download that additional component.

Keep in mind, this type of modularization requires more effort and possibly refactoring your app's existing code, so consider carefully which of your app's features would benefit the most from being available to users on demand. To better understand optimal use cases and guidelines for on demand features, read UX best practices for on demand delivery .

If you want to gradually modularize app features over time, without enabling advanced delivery options, such as on demand deliver, instead configure install-time delivery .

This page helps you add a feature module to your app project and configure it for on demand delivery. Before you begin, make sure you're using Android Studio 3.5 or higher and Android Gradle Plugin 3.5.0 or higher.

Configure a new module for on demand delivery

The easiest way to create a new feature module is by using Android Studio 3.5 or higher. Because feature modules have an inherent dependency on the base app module, you can add them only to existing app projects.

To add a feature module to your app project using Android Studio, proceed as follows:

  1. If you haven't already done so, open your app project in the IDE.
  2. Select File > New > New Module from the menu bar.
  3. In the Create New Module dialog, select Dynamic Feature Module and click Next .
  4. In the Configure your new module section, complete the following:
    1. Select the Base application module for your app project from the dropdown menu.
    2. Specify a Module name . The IDE uses this name to identify the module as a Gradle subproject in your Gradle settings file . When you build your app bundle, Gradle uses the last element of the subproject name to inject the <manifest split> attribute in the feature module's manifest .
    3. Specify the module's package name . By default, Android Studio suggests a package name that combines the root package name of the base module and the module name you specified in the previous step.
    4. Select the Minimum API level you want the module to support. This value should match that of the base module.
  5. পরবর্তী ক্লিক করুন.
  6. In the Module Download Options section, complete the following:

    1. Specify the Module title using up to 50 characters. The platform uses this title to identify the module to users when, for example, confirming whether the user wants to download the module. For this reason, your app's base module must include the module title as a string resource , which you can translate. When creating the module using Android Studio, the IDE adds the string resource to the base module for you and injects the following entry in the feature module's manifest:

      <dist:module
          ...
          dist:title="@string/feature_title">
      </dist:module>
      
    2. In the dropdown menu under Install-time inclusion , select Do not include module at install-time . Android Studio injects the following in the module's manifest to reflect your choice:

      <dist:module ... >
        <dist:delivery>
            <dist:on-demand/>
        </dist:delivery>
      </dist:module>
      
    3. Check the box next to Fusing if you want this module to be available to devices running Android 4.4 (API level 20) and lower and included in multi-APKs. This means you can enable on demand behavior for this module and disable fusing to omit it from devices that don't support downloading and installing split APKs. Android Studio injects the following in the module's manifest to reflect your choice:

      <dist:module ...>
          <dist:fusing dist:include="true | false" />
      </dist:module>
      
  7. শেষ ক্লিক করুন.

After Android Studio finishes creating your module, inspect its contents yourself from the Project pane (select View > Tool Windows > Project from the menu bar). The default code, resources, and organization should be similar to those of the standard app module.

Next, you will need to implement the on demand install functionality using the Play Feature Delivery library.

Include the Play Feature Delivery Library in your project

Before you can start, you need to first add the Play Feature Delivery Library to your project.

Request an on demand module

When your app needs to use a feature module, it can request one while it's in the foreground through the SplitInstallManager class. When making a request, your app needs to specify the name of the module as defined by the split element in the target module's manifest. When you create a feature module using Android Studio, the build system uses the Module name you provide to inject this property into the module's manifest at compile time. For more information, read about the feature module manifests .

For example, consider an app that has an on demand module to capture and send picture messages using the device's camera, and this on demand module specifies split="pictureMessages" in its manifest. The following sample uses SplitInstallManager to request the pictureMessages module (along with an additional module for some promotional filters):

কোটলিন

// 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 -> { ... });

When your app requests an on demand module, the Play Feature Delivery Library employs a “fire-and-forget” strategy. That is, it sends the request to download the module to the platform, but it does not monitor whether the installation succeeded. To move the user journey forward after installation or gracefully handle errors, make sure you monitor the request state .

Note: It's okay to request a feature module that's already installed on the device. The API instantly considers the request as completed if it detects the module is already installed. Additionally, after a module is installed, Google Play keeps it updated automatically. That is, when you upload a new version of your app bundle, the platform updates all installed APKs that belong to your app. For more information, read Manage app updates .

To have access to the module's code and resources, your app needs to enable SplitCompat . Note that SplitCompat is not required for Android Instant Apps.

Defer installation of on demand modules

If you do not need your app to immediately download and install an on demand module, you can defer installation for when the app is in the background. For example, if you want to preload some promotional material for a later launch of your app.

You can specify a module to be download later using the deferredInstall() method, as shown below. And, unlike SplitInstallManager.startInstall() , your app does not need to be in the foreground to initiate a request for a deferred installation.

কোটলিন

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

Requests for deferred installs are best-effort and you cannot track their progress. So, before trying to access a module you have specified for deferred installation, you should check that the module has been installed . If you need the module to be available immediately, instead use SplitInstallManager.startInstall() to request it, as shown in the previous section.

Monitor the request state

To be able to update a progress bar, fire an intent after installation, or gracefully handle a request error, you need to listen for state updates from the asynchronous SplitInstallManager.startInstall() task. Before you can start receiving updates for your install request, register a listener and get the session ID for the request, as shown below.

কোটলিন

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

অনুরোধের ত্রুটিগুলি পরিচালনা করুন

Keep in mind that on demand installation of feature modules can sometime fail, just like app installation doesn't always succeed. Failure to install can be due to issues like low device storage, no network connectivity, or the user not being signed in to the Google Play Store. For suggestions on how to handle these situations gracefully from the user's perspective, check out our UX guidelines for on demand delivery .

Code-wise, you should handle failures downloading or installing a module using addOnFailureListener() , as shown below:

কোটলিন

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

The table below describes the error states your app may need to handle:

ত্রুটি কোড বর্ণনা ব্যবস্থা নেওয়ার পরামর্শ দিয়েছেন
ACTIVE_SESSIONS_LIMIT_EXCEEDED The request is rejected because there is at least one existing request that is currently downloading. Check if there are any requests that are still downloading, as shown in the sample above.
MODULE_UNAVAILABLE Google Play is unable to find the requested module based on the current installed version of the app, device, and user's Google Play account. If the user does not have access to the module, notify them.
INVALID_REQUEST Google Play received the request, but the request is not valid. Verify that the information included in the request is complete and accurate.
SESSION_NOT_FOUND A session for a given session ID was not found. If you're trying to monitor the state of a request by its session ID, make sure that the session ID is correct.
API_NOT_AVAILABLE The Play Feature Delivery Library is not supported on the current device. That is, the device is not able to download and install features on demand. For devices running Android 4.4 (API level 20) or lower, you should include feature modules at install time using the dist:fusing manifest property. To learn more, read about the feature module manifest .
NETWORK_ERROR The request failed because of a network error. Prompt the user to either establish a network connection or change to a different network.
ACCESS_DENIED The app is unable to register the request because of insufficient permissions. This typically occurs when the app is in the background. Attempt the request when the app returns to the foreground.
INCOMPATIBLE_WITH_EXISTING_SESSION The request contains one or more modules that have already been requested but have not yet been installed. Either create a new request that does not include modules that your app has already requested, or wait for all currently requested modules to finish installing before retrying the request.

Keep in mind, requesting a module that has already been installed does not resolve in an error.

SERVICE_DIED The service responsible for handling the request has died. Retry the request.

Your SplitInstallStateUpdatedListener receives a SplitInstallSessionState with this error code, status FAILED and session ID -1 .

INSUFFICIENT_STORAGE The device does not have enough free storage to install the feature module. Notify the user that they do not have enough storage to install this feature.
SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR SplitCompat could not load the feature module. These errors should automatically resolve themselves after the next app restart.
PLAY_STORE_NOT_FOUND The Play Store app is not installed on the device. Let the user know that the Play Store app is required to download this feature.
APP_NOT_OWNED The app has not been installed by Google Play and the feature cannot be downloaded. This error can only occur for deferred installs. If you want the user to acquire the app on Google Play, use startInstall() which can obtain the necessary user confirmation .
অভ্যন্তরীণ_ত্রুটি An internal error occurred within the Play Store. Retry the request.

If a user requests downloading an on demand module and an error occurs, consider displaying a dialog that provides two options for the user: Try again (which attempts the request again) and Cancel (which abandons the request). For additional support, you should also provide Help link that directs users to the Google Play Help center .

Handle state updates

After you register a listener and record the session ID for your request, use StateUpdatedListener.onStateUpdate() to handle state changes, as shown below.

কোটলিন

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

The possible states for your install request are described in the table below.

Request state বর্ণনা ব্যবস্থা নেওয়ার পরামর্শ দিয়েছেন
মুলতুবি The request has been accepted and the download should start soon. Initialize UI components, such as a progress bar, to provide the user feedback on the download.
REQUIRES_USER_CONFIRMATION The download requires user confirmation. Most commonly this status occurs if the app has not been installed through Google Play. Prompt the user to confirm the feature download through Google Play. To learn more, go to the section about how to obtain user confirmation .
ডাউনলোড হচ্ছে ডাউনলোড চলছে। If you provide a progress bar for the download, use the SplitInstallSessionState.bytesDownloaded() and SplitInstallSessionState.totalBytesToDownload() methods to update the UI (see the code sample above this table).
DOWNLOADED The device has downloaded the module but installation has not yet begun. Apps should enable SplitCompat to have access to downloaded modules and avoid seeing this state. This is required in order to access the feature module's code and resources.
ইনস্টল করা হচ্ছে The device is currently installing the module. Update the progress bar. This state is typically short.
INSTALLED The module is installed on the device. Access code and resource in the module to continue the user journey.

If the module is for an Android Instant App running on Android 8.0 (API level 26) or higher, you need to use splitInstallHelper to update app components with the new module .

ব্যর্থ হয়েছে The request failed before the module was installed on the device. Prompt the user to either retry the request or cancel it.
CANCELING The device is in the process of cancelling the request. To learn more, go to the section about how to cancel an install request .
বাতিল করা হয়েছে The request has been cancelled.

Obtain user confirmation

In some cases, Google Play may require user confirmation before satisfying a download request. For example, if your app has not been installed by Google Play or if you are attempting a large download over mobile data. In such cases, the status for the request reports REQUIRES_USER_CONFIRMATION , and your app needs to obtain user confirmation before the device is able to download and install the modules in the request. To obtain confirmation, your app should prompt the user as follows:

কোটলিন

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

You can register an activity result launcher using the builtin ActivityResultContracts.StartIntentSenderForResult contract. See Activity Result APIs .

The status for the request is updated depending on the user response:

  • If the user accepts the confirmation, the request status changes to PENDING and the download proceeds.
  • If the user denies the confirmation, the request status changes to CANCELED .
  • If the user does not make a selection before the dialog is destroyed, the request status remains as REQUIRES_USER_CONFIRMATION . Your app can prompt the user again to complete the request.

To receive a callback with the user's response, you can override the ActivityResultCallback as shown below.

কোটলিন

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

Cancel an install request

If your app needs to cancel a request before it is installed, it can invoke the cancelInstall() method using the request's session ID, as shown below.

কোটলিন

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

জাভা

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

Access modules

To access code and resources from a downloaded module after it is downloaded, your app needs to enable the SplitCompat Library for both your app and each activity in the feature modules your app downloads.

You should note, however, the platform experiences the following restrictions to accessing contents of a module, for some time (days, in some cases) after downloading the module:

  • The platform can not apply any new manifest entries introduced by the module.
  • The platform can not access the module's resources for system UI components, such as notifications. If you need to use such resources immediately, consider including those resource in the base module of your app.

Enable SplitCompat

For your app to access code and resources from a downloaded module, you need to enable SplitCompat using only one of the methods described in the following sections.

After you enable SplitCompat for your app, you need to also enable SplitCompat for each activity in the feature modules you want your app to have access to.

Declare SplitCompatApplication in the manifest

The simplest way to enable SplitCompat is to declare SplitCompatApplication as the Application subclass in your app's manifest, as shown below:

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

After the app is installed on a device, you can access code and resources from downloaded feature modules automatically.

Invoke SplitCompat at runtime

You can also enable SplitCompat in specific activities or services at runtime. Enabling SplitCompat this way is required to launch activities included in feature modules. To do this, override attachBaseContext as seen below.

If you have a custom Application class, have it instead extend SplitCompatApplication in order to enable SplitCompat for your app, as shown below:

কোটলিন

class MyApplication : SplitCompatApplication() {
    ...
}

জাভা

public class MyApplication extends SplitCompatApplication {
    ...
}

SplitCompatApplication simply overrides ContextWrapper.attachBaseContext() to include SplitCompat.install(Context applicationContext) . If you don't want your Application class to extend SplitCompatApplication , you can override the attachBaseContext() method manually, as follows:

কোটলিন

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

If your on demand module is compatible with both instant apps and installed apps, you can invoke SplitCompat conditionally, as follows:

কোটলিন

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

Enable SplitCompat for module activities

After you enable SplitCompat for your base app, you need to enable SplitCompat for each activity that your app downloads in a feature module. To do so, use the SplitCompat.installActivity() method, as follows:

কোটলিন

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

Access components defined in feature modules

Start an activity defined in a feature module

You can launch activities defined in feature modules using startActivity() after enabling SplitCompat.

কোটলিন

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

জাভা

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

The first parameter to setClassName is the package name of the app and the second parameter is the full class name of the activity.

When you have an activity in a feature module you downloaded on-demand, you must enable SplitCompat in the activity .

Start a service defined in a feature module

You can launch services defined in feature modules using startService() after enabling SplitCompat.

কোটলিন

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

জাভা

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

Export a component defined in a feature module

You should not include exported Android components inside optional modules.

The build system merges manifest entries for all modules into the base module; if an optional module contained an exported component, it would be accessible even before the module is installed and can cause a crash due to missing code when invoked from another app.

This is not a problem for internal components; they are accessed only by the app, so the app can check that the module is installed before accessing the component.

If you need an exported component, and you want its content to be in an optional module, consider implementing a proxy pattern. You can do that by adding a proxy exported component in the base; when accessed, the proxy component can check for the presence of the module that contains the content. If the module is present, the proxy component can start the internal component from the module via an Intent , relaying the intent from the caller app. If the module is not present, the component can download the module or return an appropriate error message to the caller app.

Access code and resources from installed modules

If you enable SplitCompat for your base application context and the activities in your feature module, you can use the code and resources from a feature module as if it were a part of the base APK, once the optional module is installed.

Access code from a different module

Access base code from a module

Code that is inside your base module can be used directly by other modules. You don't need to do anything special; just import and use the classes you need.

Access module code from another module

An object or class inside a module cannot be statically accessed from another module directly, but it can be accessed indirectly, using reflection.

You should be wary of how often this happens, due to the performance costs of reflection. For complex use cases, use dependency injection frameworks like Dagger 2 to guarantee a single reflection call per application lifetime.

To simplify the interactions with the object after instantiation, it is recommended to define an interface in the base module and its implementation in the feature module. উদাহরণস্বরূপ:

কোটলিন

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

Access resources and assets from a different module

Once a module is installed, you can access resources and assets within the module in the standard way, with two caveats:

  • If you are accessing a resource from a different module, the module will not have access to the resource identifier, though the resource can still be accessed by name. Note that the package to use to reference the resource is the package of the module where the resource is defined.
  • If you want to access assets or resources that exist in a newly installed module from a different installed module of your app, you must do so using the application context . The context of the component that's trying to access the resources will not yet be updated. Alternatively, you can recreate that component (for instance calling Activity.recreate() ) or reinstall SplitCompat on it after the feature module installation.

Load native code in an app using on-demand delivery

We recommend using ReLinker to load all your native libraries when using on-demand delivery of feature modules. ReLinker fixes an issue in loading native libraries after the installation of a feature module. You can learn more about ReLinker in the Android JNI Tips .

Load native code from an optional module

Once a split is installed, we recommend loading its native code through ReLinker . For instant apps you should use this special method .

If you are using System.loadLibrary() to load your native code and your native library has a dependency on another library in the module, you must manually load that other library first. If you are using ReLinker, the equivalent operation is Relinker.recursively().loadLibrary() .

If you are using dlopen() in native code to load a library defined in an optional module, it will not work with relative library paths. The best solution is to retrieve the absolute path of the library from Java code via ClassLoader.findLibrary() and then use it in your dlopen() call. Do this before entering the native code or use a JNI call from your native code into Java.

Access installed Android Instant Apps

After an Android Instant App module reports as INSTALLED , you can access its code and resources using a refreshed app Context . A context that your app creates before installing a module (for example, one that's already stored in a variable) does not contain the content of the new module. But a fresh context does—this can be obtained, for example, using createPackageContext .

কোটলিন

// 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 Instant Apps on Android 8.0 and higher

When requesting an on demand module for an Android Instant App on Android 8.0 (API level 26) and higher, after an install request reports as INSTALLED , you need to update the app with the context of the new module through a call to SplitInstallHelper.updateAppInfo(Context context) . Otherwise, the app is not yet aware of the module's code and resources. After updating the app's metadata, you should load the module's contents during the next main thread event by invoking a new Handler , as shown below:

কোটলিন

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();
                        ...
                    }
                });
            }
        }
    }
}

Load C/C++ libraries

If you want to load C/C++ libraries from a module that the device has already downloaded in an Instant App, use SplitInstallHelper.loadLibrary(Context context, String libName) , as shown below:

কোটলিন

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”);
                ...
        }
    }
}

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

  • It isn't possible to use Android WebView in an activity that accesses resources or assets from an optional module. This is due to an incompatibility between WebView and SplitCompat on Android API level 28 and lower.
  • You can't cache Android ApplicationInfo objects, their contents, or objects that contain them within your app. You should always fetch these objects as needed from an app context. Caching such objects could cause the app to crash when installing a feature module.

Manage installed modules

To check which feature modules are currently installed on the device, you can call SplitInstallManager.getInstalledModules() , which returns a Set<String> of the names of the installed modules, as shown below.

কোটলিন

val installedModules: Set<String> = splitInstallManager.installedModules

জাভা

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

Uninstall modules

You can request the device to uninstall modules by invoking SplitInstallManager.deferredUninstall(List<String> moduleNames) , as shown below.

কোটলিন

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

Module uninstalls do not occur immediately. That is, the device uninstalls them in the background as needed to save storage space. You can confirm that the device has deleted a module by invoking SplitInstallManager.getInstalledModules() and inspecting the result, as described in the previous section.

Download additional language resources

With app bundles, devices download only the code and resources they require to run your app. So, for language resources, a user's device downloads only your app's language resources that match the one or more languages currently selected in the device's settings.

If you want your app to have access to additional language resources—for example, to implement an in-app language picker, you can use the Play Feature Delivery Library to download them on demand. The process is similar to that of downloading a feature module, as shown below.

কোটলিন

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

The request is handled as if it were a request for a feature module. That is, you can monitor the request state like you normally would.

If your app doesn't require the additional language resources immediately, you can defer the installation for when the app is in the background, as shown below.

কোটলিন

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

জাভা

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

Access downloaded language resources

To gain access to downloaded language resources, your app needs to run the SplitCompat.installActivity() method within the attachBaseContext() method of each activity that requires access to those resources, as shown below.

কোটলিন

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

জাভা

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

For each activity you want to use language resources your app has downloaded, update the base context and set a new locale through its Configuration :

কোটলিন

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

In order for these changes to take effect, you have to recreate your activity after the new language is installed and ready to use. You can use the Activity#recreate() method.

কোটলিন

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();
  ...
}

Uninstall additional language resources

Similar to feature modules, you can uninstall additional resources at any time. Before requesting an uninstall, you may want to first determine which languages are currently installed, as follows.

কোটলিন

val installedLanguages: Set<String> = splitInstallManager.installedLanguages

জাভা

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

You can then decide which languages to uninstall using the deferredLanguageUninstall() method, as shown below.

কোটলিন

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

জাভা

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

Locally test module installs

The Play Feature Delivery Library allows you to locally test your app's ability to do the following, without connecting to the Play Store:

This page describes how to deploy your app's split APKs to your test device so that Play Feature Delivery automatically uses those APKs to simulate requesting, downloading, and installing modules from the Play Store.

Although you don't need to make any changes to your app's logic, you need to meet the following requirements:

Build a set of APKs

If you haven't already done so, build your app's split APKs, as follows:

  1. Build an app bundle for your app using one of the following methods:
  2. Use bundletool to generate a set of APKs for all device configurations with the following command:

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

The --local-testing flag includes meta-data in your APKs' manifests that lets the Play Feature Delivery Library know to use the local split APKs to test installing feature modules, without connecting to the Play Store.

Deploy your app to the device

After you build a set of APKs using the --local-testing flag, use bundletool to install the base version of your app and transfer additional APKs to your device's local storage. You can perform both actions with the following command:

bundletool install-apks --apks my_app.apks

Now, when you start your app and complete the user flow to download and install a feature module, the Play Feature Delivery Library uses the APKs that bundletool transferred to the device's local storage.

Simulate a network error

To simulate module installs from the Play Store, the Play Feature Delivery Library uses an alternative to the SplitInstallManager , called FakeSplitInstallManager , to request the module. When you use bundletool with the --local-testing flag to build a set of APKs and deploy them to your test device, it includes metadata that instructs the Play Feature Delivery Library to automatically switch your app's API calls to invoke FakeSplitInstallManager , instead of SplitInstallManager .

FakeSplitInstallManager includes a boolean flag that you can enable to simulate a network error the next time your app requests to install a module. To access FakeSplitInstallManager in your tests, you can get an instance of it using the FakeSplitInstallManagerFactory , as shown below:

কোটলিন

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