सुविधा वाले मॉड्यूल की मदद से, कुछ सुविधाओं और रिसॉर्स को अपने ऐप्लिकेशन के बेस मॉड्यूल से अलग किया जा सकता है. साथ ही, उन्हें अपने ऐप्लिकेशन बंडल में शामिल किया जा सकता है. उदाहरण के लिए, Play की सुविधा डिलीवरी की मदद से, उपयोगकर्ता आपके ऐप्लिकेशन का बेस APK इंस्टॉल करने के बाद, ज़रूरत पड़ने पर उन कॉम्पोनेंट को डाउनलोड और इंस्टॉल कर सकते हैं.
उदाहरण के लिए, एक मैसेजिंग ऐप्लिकेशन में फ़ोटो मैसेज कैप्चर करने और भेजने की सुविधा शामिल है. हालांकि, इसका इस्तेमाल करने वाले उपयोगकर्ताओं का प्रतिशत बहुत कम है. तस्वीर वाले मैसेज को डाउनलोड किए जा सकने वाले फ़ीचर मॉड्यूल के तौर पर शामिल करना सही रहेगा. इस तरह, सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन का शुरुआती डाउनलोड साइज़ कम होता है. साथ ही, सिर्फ़ उन उपयोगकर्ताओं को अतिरिक्त कॉम्पोनेंट डाउनलोड करना होता है जो फ़ोटो मैसेज भेजते हैं.
ध्यान रखें कि इस तरह के मॉड्यूलराइज़ेशन के लिए ज़्यादा मेहनत और अपने ऐप्लिकेशन के मौजूदा कोड को रिफ़ैक्टर करना होता है. इसलिए, सोच-समझकर सोचें कि आपके ऐप्लिकेशन की किन सुविधाओं को मांग पर उपलब्ध होने से सबसे ज़्यादा फ़ायदा होगा. ऑन डिमांड सुविधाओं के इस्तेमाल के सबसे सही उदाहरणों और दिशा-निर्देशों को बेहतर तरीके से समझने के लिए, ऑन डिमांड डिलीवरी के लिए यूज़र एक्सपीरियंस के सबसे सही तरीके पढ़ें.
अगर आपको समय के साथ ऐप्लिकेशन की सुविधाओं में धीरे-धीरे मॉड्यूलराइज़ करना है, तो मांग पर डिलीवर करने जैसे बेहतर डिलीवरी विकल्पों को चालू किए बिना, इंस्टॉल के समय डिलीवरी कॉन्फ़िगर करें.
इस पेज की मदद से, अपने ऐप्लिकेशन प्रोजेक्ट में कोई फ़ीचर मॉड्यूल जोड़ा जा सकता है. साथ ही, उसे मांग पर डिलीवरी के लिए कॉन्फ़िगर किया जा सकता है. शुरू करने से पहले, पक्का करें कि Android Studio 3.5 या इसके बाद वाले वर्शन और Android Gradle प्लग इन 3.5.0 या इसके बाद वाले वर्शन का इस्तेमाल किया जा रहा हो.
मांग पर डिलीवरी के लिए नया मॉड्यूल कॉन्फ़िगर करना
नया सुविधा मॉड्यूल बनाने का सबसे आसान तरीका, Android Studio 3.5 या इसके बाद के वर्शन का इस्तेमाल करना है. सुविधा वाले मॉड्यूल, बेस ऐप्लिकेशन मॉड्यूल पर निर्भर करते हैं. इसलिए, उन्हें सिर्फ़ मौजूदा ऐप्लिकेशन प्रोजेक्ट में जोड़ा जा सकता है.
Android Studio का इस्तेमाल करके, अपने ऐप्लिकेशन प्रोजेक्ट में एक फ़ीचर मॉड्यूल जोड़ने के लिए, यह तरीका अपनाएं:
- अगर आपने अब तक ऐसा नहीं किया है, तो IDE में अपना ऐप्लिकेशन प्रोजेक्ट खोलें.
- मेन्यू बार में जाकर, फ़ाइल > नया > नया मॉड्यूल चुनें.
- नया मॉड्यूल बनाएं डायलॉग में, डाइनैमिक फ़ीचर मॉड्यूल चुनें और आगे बढ़ें पर क्लिक करें.
- अपना नया मॉड्यूल कॉन्फ़िगर करें सेक्शन में, ये काम करें:
- ड्रॉपडाउन मेन्यू से, अपने ऐप्लिकेशन प्रोजेक्ट के लिए बेस ऐप्लिकेशन मॉड्यूल चुनें.
- मॉड्यूल का नाम डालें. IDE इस नाम का इस्तेमाल करके, Gradle सेटिंग फ़ाइल में मॉड्यूल को Gradle सब-प्रोजेक्ट के तौर पर पहचानता है. ऐप्लिकेशन बंडल बनाने पर, Gradle सुविधा वाले मॉड्यूल के मेनिफ़ेस्ट में
<manifest split>
एट्रिब्यूट को इंजेक्ट करने के लिए, सब-प्रोजेक्ट के नाम के आखिरी एलिमेंट का इस्तेमाल करता है. - मॉड्यूल के पैकेज का नाम बताएं. डिफ़ॉल्ट रूप से, Android Studio एक पैकेज का नाम सुझाता है. यह नाम, बेस मॉड्यूल के रूट पैकेज के नाम और पिछले चरण में बताए गए मॉड्यूल के नाम को जोड़कर बनाया जाता है.
- वह कम से कम एपीआई लेवल चुनें जिस पर आपको मॉड्यूल का इस्तेमाल करना है. यह वैल्यू, बेस मॉड्यूल की वैल्यू से मेल खानी चाहिए.
- आगे बढ़ें पर क्लिक करें.
मॉड्यूल डाउनलोड के विकल्प सेक्शन में, इन चीज़ों को पूरा करें:
ज़्यादा से ज़्यादा 50 वर्णों का इस्तेमाल करके, मॉड्यूल का टाइटल डालें. प्लैटफ़ॉर्म, उपयोगकर्ताओं को मॉड्यूल की पहचान करने के लिए इस टाइटल का इस्तेमाल करता है. उदाहरण के लिए, यह पुष्टि करने के लिए कि उपयोगकर्ता को मॉड्यूल डाउनलोड करना है या नहीं. इस वजह से, आपके ऐप्लिकेशन के बेस मॉड्यूल में, मॉड्यूल का टाइटल स्ट्रिंग रिसॉर्स के तौर पर शामिल होना चाहिए. इस टाइटल का अनुवाद किया जा सकता है. Android Studio का इस्तेमाल करके मॉड्यूल बनाते समय, IDE आपके लिए बेस मॉड्यूल में स्ट्रिंग रिसॉर्स जोड़ता है. साथ ही, सुविधा मॉड्यूल के मेनिफ़ेस्ट में यह एंट्री इंजेक्ट करता है:
<dist:module ... dist:title="@string/feature_title"> </dist:module>
इंस्टॉल के समय शामिल करना में मौजूद ड्रॉपडाउन मेन्यू में, इंस्टॉल के समय मॉड्यूल शामिल न करें चुनें. आपकी पसंद को दिखाने के लिए, Android Studio मॉड्यूल के मेनिफ़ेस्ट में ये चीज़ें इंजेक्ट करता है:
<dist:module ... > <dist:delivery> <dist:on-demand/> </dist:delivery> </dist:module>
अगर आपको यह मॉड्यूल, Android 4.4 (एपीआई लेवल 20) और उससे पहले के वर्शन पर चलने वाले डिवाइसों के लिए उपलब्ध कराना है और मल्टी-APK में शामिल करना है, तो फ़्यूज़ करना के बगल में मौजूद बॉक्स को चुनें. इसका मतलब है कि इस मॉड्यूल के लिए मांग पर व्यवहार को चालू किया जा सकता है. साथ ही, जिन डिवाइसों पर स्प्लिट APKs डाउनलोड और इंस्टॉल नहीं किए जा सकते हैं उन पर इस मॉड्यूल को छोड़ने के लिए, फ़्यूज़िंग सुविधा को बंद किया जा सकता है. आपकी पसंद दिखाने के लिए, Android Studio मॉड्यूल के मेनिफ़ेस्ट में इन्हें शामिल करता है:
<dist:module ...> <dist:fusing dist:include="true | false" /> </dist:module>
पूरा करें पर क्लिक करें.
Android Studio आपका मॉड्यूल बनाने के बाद, प्रोजेक्ट पैनल से इसकी सामग्री की जांच खुद करें (मेन्यू बार से व्यू > टूल विंडो > प्रोजेक्ट चुनें). डिफ़ॉल्ट कोड, संसाधन, और संगठन, स्टैंडर्ड ऐप्लिकेशन मॉड्यूल के कोड से मिलते-जुलते होने चाहिए.
इसके बाद, आपको Play Feature Delivery लाइब्रेरी का इस्तेमाल करके, मांग पर इंस्टॉल करने की सुविधा लागू करनी होगी.
अपने प्रोजेक्ट में Play Feature Delivery लाइब्रेरी शामिल करना
शुरू करने से पहले, आपको अपने प्रोजेक्ट में Play Feature Delivery लाइब्रेरी जोड़नी होगी.
मांग पर उपलब्ध मॉड्यूल का अनुरोध करना
जब आपके ऐप्लिकेशन को किसी फ़ीचर मॉड्यूल का इस्तेमाल करना होता है, तब वह SplitInstallManager
क्लास के ज़रिए फ़ोरग्राउंड में होने पर
फ़ीचर मॉड्यूल का इस्तेमाल कर सकता है. अनुरोध करते समय, आपके ऐप्लिकेशन को मॉड्यूल का नाम बताना होगा. यह नाम, टारगेट मॉड्यूल के मेनिफ़ेस्ट में split
एलिमेंट के तौर पर तय किया गया होता है. Android Studio का इस्तेमाल करके कोई फ़ीचर मॉड्यूल बनाने पर, बिल्ड सिस्टम उस मॉड्यूल के नाम का इस्तेमाल करता है जो कंपाइलेशन के समय इस प्रॉपर्टी को मॉड्यूल के मेनिफ़ेस्ट में इंजेक्ट करने के लिए किया जाता है.
ज़्यादा जानकारी के लिए, सुविधा वाले मॉड्यूल के मेनिफ़ेस्ट के बारे में पढ़ें.
उदाहरण के लिए, किसी ऐसे ऐप्लिकेशन पर विचार करें जिसमें डिवाइस के कैमरे का इस्तेमाल करके फ़ोटो मैसेज कैप्चर करने और भेजने के लिए, ऑन डिमांड मॉड्यूल हो. साथ ही, यह ऑन डिमांड मॉड्यूल अपने मेनिफ़ेस्ट में split="pictureMessages"
की जानकारी देता हो. यहां दिया गया सैंपल, pictureMessages
मॉड्यूल का अनुरोध करने के लिए SplitInstallManager
का इस्तेमाल करता है. साथ ही, कुछ प्रमोशनल फ़िल्टर के लिए एक अतिरिक्त मॉड्यूल का इस्तेमाल किया जाता है:
Kotlin
// Creates an instance of SplitInstallManager. val splitInstallManager = SplitInstallManagerFactory.create(context) // Creates a request to install a module. val request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build() splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener { sessionId -> ... } .addOnFailureListener { exception -> ... }
Java
// Creates an instance of SplitInstallManager. SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(context); // Creates a request to install a module. SplitInstallRequest request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build(); splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener(sessionId -> { ... }) .addOnFailureListener(exception -> { ... });
जब आपका ऐप्लिकेशन मांग पर मिलने वाले मॉड्यूल का अनुरोध करता है, तो Play Feature Delivery लाइब्रेरी "फ़ायर-ऐंड-फ़ॉरगेट" रणनीति का इस्तेमाल करती है. इसका मतलब है कि यह प्लैटफ़ॉर्म पर मॉड्यूल डाउनलोड करने का अनुरोध भेजता है, लेकिन यह निगरानी नहीं करता कि इंस्टॉलेशन पूरा हुआ या नहीं. इंस्टॉल करने के बाद उपयोगकर्ता की गतिविधि को आगे बढ़ाने या गड़बड़ियों को सही तरीके से हैंडल करने के लिए, अनुरोध की स्थिति को मॉनिटर करना ज़रूरी है.
ध्यान दें: डिवाइस पर पहले से इंस्टॉल किए गए फ़ीचर मॉड्यूल का अनुरोध किया जा सकता है. अगर एपीआई को पता चलता है कि मॉड्यूल पहले से इंस्टॉल है, तो वह अनुरोध को तुरंत पूरा कर देता है. इसके अलावा, मॉड्यूल इंस्टॉल होने के बाद, Google Play उसे अपने-आप अपडेट करता रहता है. इसका मतलब है कि जब आपके ऐप्लिकेशन बंडल का नया वर्शन अपलोड किया जाता है, तो प्लैटफ़ॉर्म आपके ऐप्लिकेशन से जुड़े सभी इंस्टॉल किए गए APK अपडेट कर देता है. ज़्यादा जानकारी के लिए, ऐप्लिकेशन के अपडेट मैनेज करना लेख पढ़ें.
मॉड्यूल के कोड और संसाधनों का ऐक्सेस पाने के लिए, आपके ऐप्लिकेशन को SplitCompat चालू करना होगा. ध्यान दें कि Android इंस्टैंट ऐप्लिकेशन के लिए, SplitCompat का इस्तेमाल करना ज़रूरी नहीं है.
मांग पर मिलने वाले मॉड्यूल इंस्टॉल करने की प्रोसेस को रोकना
अगर आपको अपने ऐप्लिकेशन को, मांग पर उपलब्ध मॉड्यूल तुरंत डाउनलोड और इंस्टॉल करने की ज़रूरत नहीं है, तो ऐप्लिकेशन के बैकग्राउंड में चलने के दौरान, उसे इंस्टॉल किए जाने से रोका जा सकता है. उदाहरण के लिए, अगर आपको अपने ऐप्लिकेशन को बाद में लॉन्च करने के लिए, कुछ प्रमोशनल कॉन्टेंट पहले से लोड करना है.
यहां बताए गए तरीके से, deferredInstall()
तरीके का इस्तेमाल करके यह तय किया जा सकता है कि मॉड्यूल को बाद में डाउनलोड करना है या नहीं. साथ ही, SplitInstallManager.startInstall()
के उलट, डिफ़र्ड इंस्टॉलेशन का अनुरोध करने के लिए, आपके ऐप्लिकेशन को फ़ोरग्राउंड में होने की ज़रूरत नहीं है.
Kotlin
// Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(listOf("promotionalFilters"))
Java
// Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));
स्थगित इंस्टॉल के लिए अनुरोध बार-बार किए जा सकते हैं और उनकी प्रोग्रेस को ट्रैक नहीं किया जा सकता. इसलिए, किसी ऐसे मॉड्यूल को ऐक्सेस करने से पहले जिसे आपने बाद में इंस्टॉल करने के लिए चुना है, आपको देखना चाहिए कि मॉड्यूल इंस्टॉल हो गया है या नहीं. अगर आपको मॉड्यूल तुरंत उपलब्ध कराना है, तो इसका अनुरोध करने के लिए SplitInstallManager.startInstall()
का इस्तेमाल करें, जैसा कि पिछले सेक्शन में दिखाया गया है.
अनुरोध की स्थिति पर नज़र रखना
प्रोग्रेस बार को अपडेट करने, इंस्टॉल करने के बाद इंटेंट ट्रिगर करने या अनुरोध की गड़बड़ी को सही तरीके से हैंडल करने के लिए, आपको एसिंक्रोनस SplitInstallManager.startInstall()
टास्क के स्टेटस अपडेट सुनने होंगे.
अपने इंस्टॉल के अनुरोध के लिए अपडेट पाने से पहले, लिसनर रजिस्टर करें और अनुरोध के लिए सेशन आईडी पाएं, जैसा कि नीचे दिखाया गया है.
Kotlin
// Initializes a variable to later track the session ID for a given request. var mySessionId = 0 // Creates a listener for request status updates. val listener = SplitInstallStateUpdatedListener { state -> if (state.sessionId() == mySessionId) { // Read the status of the request to handle the state update. } } // Registers the listener. splitInstallManager.registerListener(listener) ... splitInstallManager .startInstall(request) // When the platform accepts your request to download // an on demand module, it binds it to the following session ID. // You use this ID to track further status updates for the request. .addOnSuccessListener { sessionId -> mySessionId = sessionId } // You should also add the following listener to handle any errors // processing the request. .addOnFailureListener { exception -> // Handle request errors. } // When your app no longer requires further updates, unregister the listener. splitInstallManager.unregisterListener(listener)
Java
// Initializes a variable to later track the session ID for a given request. int mySessionId = 0; // Creates a listener for request status updates. SplitInstallStateUpdatedListener listener = state -> { if (state.sessionId() == mySessionId) { // Read the status of the request to handle the state update. } }; // Registers the listener. splitInstallManager.registerListener(listener); ... splitInstallManager .startInstall(request) // When the platform accepts your request to download // an on demand module, it binds it to the following session ID. // You use this ID to track further status updates for the request. .addOnSuccessListener(sessionId -> { mySessionId = sessionId; }) // You should also add the following listener to handle any errors // processing the request. .addOnFailureListener(exception -> { // Handle request errors. }); // When your app no longer requires further updates, unregister the listener. splitInstallManager.unregisterListener(listener);
अनुरोध से जुड़ी गड़बड़ियां ठीक करना
ध्यान रखें कि मांग पर, फ़ीचर मॉड्यूल को इंस्टॉल करने की प्रोसेस कभी-कभी असफल हो सकती है. ठीक उसी तरह, जैसे ऐप्लिकेशन को इंस्टॉल करना हमेशा सफल नहीं होता. इंस्टॉल न हो पाने की वजह, डिवाइस का कम स्टोरेज, इंटरनेट कनेक्टिविटी न होना या उपयोगकर्ता का Google Play Store में साइन इन न होना जैसी समस्याएं हो सकती हैं. इन स्थितियों को उपयोगकर्ता के नज़रिए से हैंडल करने के सुझाव पाने के लिए, मांग पर डिलीवरी के लिए UX से जुड़े हमारे दिशा-निर्देश देखें.
कोड के हिसाब से, आपको addOnFailureListener()
का इस्तेमाल करके, मॉड्यूल डाउनलोड या इंस्टॉल करने में हो रही समस्याओं को ठीक करना चाहिए, जैसा कि यहां दिखाया गया है:
Kotlin
splitInstallManager .startInstall(request) .addOnFailureListener { exception -> when ((exception as SplitInstallException).errorCode) { SplitInstallErrorCode.NETWORK_ERROR -> { // Display a message that requests the user to establish a // network connection. } SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads() ... } } fun checkForActiveDownloads() { splitInstallManager // Returns a SplitInstallSessionState object for each active session as a List. .sessionStates .addOnCompleteListener { task -> if (task.isSuccessful) { // Check for active sessions. for (state in task.result) { if (state.status() == SplitInstallSessionStatus.DOWNLOADING) { // Cancel the request, or request a deferred installation. } } } } }
Java
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 | अनुरोध अस्वीकार कर दिया गया है, क्योंकि कम से कम एक मौजूदा अनुरोध, फ़िलहाल डाउनलोड हो रहा है. | देखें कि क्या कोई अनुरोध अब भी डाउनलोड हो रहा है, जैसा कि ऊपर दिए गए उदाहरण में दिखाया गया है. |
मोड उपलब्ध नहीं है | Google Play, ऐप्लिकेशन, डिवाइस, और उपयोगकर्ता के Google Play खाते के मौजूदा वर्शन के आधार पर, अनुरोध किया गया मॉड्यूल नहीं ढूंढ पा रहा है. | अगर उपयोगकर्ता के पास मॉड्यूल का ऐक्सेस नहीं है, तो उसे इस बारे में बताएं. |
INVALID_REQUEST | Google Play को अनुरोध मिल गया है, लेकिन यह अनुरोध मान्य नहीं है. | पुष्टि करें कि अनुरोध में दी गई जानकारी पूरी और सही है. |
SESSION_NOT_FOUND | किसी सेशन आईडी के लिए कोई सेशन नहीं मिला. | अगर आपको किसी अनुरोध की स्थिति को उसके सेशन आईडी के हिसाब से मॉनिटर करना है, तो पक्का करें कि सेशन आईडी सही हो. |
API_NOT_AVAILABLE | आपके मौजूदा डिवाइस पर, Play की सुविधा डिलीवरी लाइब्रेरी काम नहीं करती. इसका मतलब है कि डिवाइस, मांग पर सुविधाओं को डाउनलोड और इंस्टॉल नहीं कर पा रहा है. | Android 4.4 (एपीआई लेवल 20) या इससे पहले के वर्शन वाले डिवाइसों के लिए,
आपको dist:fusing मेनिफ़ेस्ट प्रॉपर्टी का इस्तेमाल करके,
इंस्टॉल के समय सुविधा वाले मॉड्यूल शामिल करने चाहिए. ज़्यादा जानने के लिए,
सुविधा मॉड्यूल मेनिफ़ेस्ट के बारे में पढ़ें.
|
नेटवर्क गड़बड़ी | नेटवर्क की गड़बड़ी की वजह से अनुरोध पूरा नहीं हुआ. | उपयोगकर्ता को नेटवर्क से कनेक्ट करने या किसी दूसरे नेटवर्क पर स्विच करने के लिए कहें. |
ACCESS_DENIED | ज़रूरी अनुमतियां न होने की वजह से, ऐप्लिकेशन अनुरोध को रजिस्टर नहीं कर पा रहा है. | आम तौर पर, ऐसा तब होता है, जब ऐप्लिकेशन बैकग्राउंड में हो. ऐप्लिकेशन के फ़ोरग्राउंड में वापस आने पर अनुरोध करने की कोशिश करें. |
INCOMPATIBLE_WITH_EXISTING_SESSION | अनुरोध में एक या उससे ज़्यादा ऐसे मॉड्यूल हैं जिनके लिए पहले ही अनुरोध किया जा चुका है लेकिन उन्हें अब तक इंस्टॉल नहीं किया गया है. | आप चाहें, तो एक नया अनुरोध करें. इसमें ऐसे मॉड्यूल शामिल न किए जाएं जिनका
आपके ऐप्लिकेशन ने पहले ही अनुरोध किया हो. इसके अलावा, फिर से अनुरोध करने से पहले,
मौजूदा समय में अनुरोध किए गए सभी मॉड्यूल के इंस्टॉल होने का इंतज़ार करें.
ध्यान रखें, पहले से इंस्टॉल किए जा चुके मॉड्यूल का अनुरोध करने पर गड़बड़ी ठीक नहीं होती है. |
सेवा_दी गई | अनुरोध को मैनेज करने के लिए ज़िम्मेदार सेवा खत्म हो गई है. | अनुरोध फिर से करें.
आपके |
InSUFFICIENT_स्टोरेज | सुविधा का मॉड्यूल इंस्टॉल करने के लिए, डिवाइस में स्टोरेज काफ़ी नहीं है. | उपयोगकर्ता को बताएं कि इस सुविधा को इंस्टॉल करने के लिए, उनके पास ज़रूरत के मुताबिक स्टोरेज नहीं है. |
SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR | SplitCompat, फ़ीचर मॉड्यूल को लोड नहीं कर सका. | ऐप्लिकेशन को अगली बार रीस्टार्ट करने के बाद, ये गड़बड़ियां अपने-आप ठीक हो जाएंगी. |
PLAY_STORE_NOT_FOUND | डिवाइस पर Play Store ऐप्लिकेशन इंस्टॉल नहीं है. | उपयोगकर्ता को बताएं कि इस सुविधा को डाउनलोड करने के लिए, Play Store ऐप्लिकेशन ज़रूरी है. |
APP_NOT_OWNED | ऐप्लिकेशन को Google Play से इंस्टॉल नहीं किया गया है और इस सुविधा को डाउनलोड नहीं किया जा सकता. यह गड़बड़ी, सिर्फ़ बाद में इंस्टॉल किए जाने वाले ऐप्लिकेशन के लिए हो सकती है. | अगर आपको उपयोगकर्ता को Google Play से ऐप्लिकेशन डाउनलोड कराना है, तो
startInstall() का इस्तेमाल करें. इससे उपयोगकर्ता की पुष्टि की ज़रूरी जानकारी मिल सकती है. |
INTERNAL_ERROR | Play Store में कोई अंदरूनी गड़बड़ी हुई. | अनुरोध फिर से करें. |
अगर कोई उपयोगकर्ता, मांग पर उपलब्ध मॉड्यूल डाउनलोड करने का अनुरोध करता है और कोई गड़बड़ी होती है, तो एक ऐसा डायलॉग दिखाएं जिसमें उपयोगकर्ता को दो विकल्प मिलते हैं: फिर से कोशिश करें (जो फिर से अनुरोध करने की कोशिश करता है) और रद्द करें (जो अनुरोध को छोड़ देता है). ज़्यादा मदद के लिए, सहायता का लिंक भी उपलब्ध कराएं, जो लोगों को Google Play के सहायता केंद्र पर ले जाता हो.
स्थिति के अपडेट मैनेज करना
लिसनर को रजिस्टर करने और अपने अनुरोध के लिए सेशन आईडी रिकॉर्ड करने के बाद, स्थिति में हुए बदलावों को मैनेज करने के लिए, StateUpdatedListener.onStateUpdate()
का इस्तेमाल करें, जैसा कि यहां दिखाया गया है.
Kotlin
override fun onStateUpdate(state : SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) { // Retry the request. return } if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.DOWNLOADING -> { val totalBytes = state.totalBytesToDownload() val progress = state.bytesDownloaded() // Update progress bar. } SplitInstallSessionStatus.INSTALLED -> { // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } } }
Java
@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. } } }
इस टेबल में, ऐप्लिकेशन इंस्टॉल करने के अनुरोध की संभावित स्थितियों की जानकारी दी गई है.
अनुरोध की स्थिति | ब्यौरा | सुझाई गई कार्रवाई |
---|---|---|
लंबित | अनुरोध स्वीकार कर लिया गया है और डाउनलोड जल्द ही शुरू हो जाना चाहिए. | उपयोगकर्ता को डाउनलोड के बारे में सुझाव देने के लिए, प्रोग्रेस बार जैसे यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट शुरू करें. |
REQUIRES_USER_पुष्टि | डाउनलोड के लिए उपयोगकर्ता की पुष्टि ज़रूरी है. आम तौर पर, यह स्टेटस तब दिखता है, जब ऐप्लिकेशन को Google Play से इंस्टॉल नहीं किया गया हो. | उपयोगकर्ता से Google Play से सुविधा डाउनलोड करने की पुष्टि करने का अनुरोध करें. ज़्यादा जानने के लिए, उपयोगकर्ता की पुष्टि करने के तरीके के बारे में बताने वाले सेक्शन पर जाएं. |
डाउनलोड करना | डाउनलोड किया जा रहा है. | अगर डाउनलोड के लिए प्रोग्रेस बार दिया जाता है, तो यूज़र इंटरफ़ेस (यूआई) को अपडेट करने के लिए, SplitInstallSessionState.bytesDownloaded() और SplitInstallSessionState.totalBytesToDownload() तरीकों का इस्तेमाल करें. इस टेबल के ऊपर दिए गए कोड का सैंपल देखें. |
डाउनलोड किए गए | डिवाइस ने मॉड्यूल डाउनलोड कर लिया है, लेकिन इंस्टॉलेशन की प्रोसेस शुरू नहीं हुई है. | डाउनलोड किए गए मॉड्यूल को ऐक्सेस करने और यह स्थिति न देखने के लिए, ऐप्लिकेशन को SplitCompat चालू करना चाहिए. सुविधा मॉड्यूल के कोड और संसाधनों को ऐक्सेस करने के लिए, यह ज़रूरी है. |
इंस्टॉल हो रहा है | फ़िलहाल, डिवाइस पर मॉड्यूल इंस्टॉल हो रहा है. | प्रोग्रेस बार को अपडेट करें. आम तौर पर, यह स्थिति कुछ समय के लिए होती है. |
इंस्टॉल किया गया | मॉड्यूल, डिवाइस पर इंस्टॉल हो गया हो. | उपयोगकर्ता के अनुभव को जारी रखने के लिए, मॉड्यूल में कोड और संसाधन का ऐक्सेस.
अगर मॉड्यूल, Android 8.0 (एपीआई लेवल 26) या उसके बाद के वर्शन पर काम करने वाले Android इंस्टैंट ऐप्लिकेशन के लिए है, तो आपको नए मॉड्यूल की मदद से ऐप्लिकेशन के कॉम्पोनेंट अपडेट करने के लिए, |
FAILED | डिवाइस पर मॉड्यूल इंस्टॉल होने से पहले, अनुरोध पूरा नहीं हो सका. | उपयोगकर्ता से अनुरोध दोबारा करने या उसे रद्द करने के लिए कहें. |
रद्द करना | डिवाइस पर अनुरोध रद्द करने की प्रोसेस चल रही है. | ज़्यादा जानने के लिए, इंस्टॉल करने का अनुरोध रद्द करने के तरीके के बारे में बताने वाले सेक्शन पर जाएं. |
रद्द | अनुरोध रद्द कर दिया गया है. |
उपयोगकर्ता की पुष्टि पाएं
कुछ मामलों में, हो सकता है कि Google Play, डाउनलोड का अनुरोध पूरा करने से पहले उपयोगकर्ता की पुष्टि करे. उदाहरण के लिए, अगर Google Play ने आपका ऐप्लिकेशन इंस्टॉल नहीं किया है या मोबाइल डेटा पर बहुत ज़्यादा डाउनलोड करने की कोशिश की जा रही है. ऐसे मामलों में, अनुरोध की स्थिति REQUIRES_USER_CONFIRMATION
के तौर पर दिखती है. साथ ही, डिवाइस में अनुरोध में दिए गए मॉड्यूल डाउनलोड और इंस्टॉल करने से पहले, आपके ऐप्लिकेशन को उपयोगकर्ता की पुष्टि करनी होगी. पुष्टि करने के लिए, आपके ऐप्लिकेशन को
उपयोगकर्ता से इस तरह अनुरोध करना चाहिए:
Kotlin
override fun onSessionStateUpdate(state: SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher) } ... }
Java
@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
कंट्रेट का इस्तेमाल करके, गतिविधि के नतीजे लॉन्चर को रजिस्टर किया जा सकता है. Activity Result APIs देखें.
अनुरोध की स्थिति, उपयोगकर्ता के जवाब के आधार पर अपडेट की जाती है:
- अगर उपयोगकर्ता पुष्टि स्वीकार कर लेता है, तो अनुरोध का स्टेटस बदलकर
PENDING
हो जाता है और डाउनलोड शुरू हो जाता है. - अगर उपयोगकर्ता पुष्टि नहीं करता है, तो अनुरोध का स्टेटस बदलकर
CANCELED
हो जाता है. - अगर डायलॉग खत्म होने से पहले उपयोगकर्ता कोई विकल्प नहीं चुनता है, तो अनुरोध का स्टेटस
REQUIRES_USER_CONFIRMATION
के तौर पर बना रहता है. आपका ऐप्लिकेशन, अनुरोध पूरा करने के लिए उपयोगकर्ता को फिर से सूचना दे सकता है.
उपयोगकर्ता के जवाब के साथ कॉलबैक पाने के लिए, यहां दिखाए गए तरीके से ActivityResultCallback को बदला जा सकता है.
Kotlin
registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } }
Java
registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } });
इंस्टॉल करने का अनुरोध रद्द करना
अगर आपके ऐप्लिकेशन को इंस्टॉल किए जाने से पहले किसी अनुरोध को रद्द करना पड़ता है, तो वह अनुरोध के सेशन आईडी का इस्तेमाल करके, cancelInstall()
तरीका शुरू कर सकता है, जैसा कि यहां दिखाया गया है.
Kotlin
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId)
Java
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId);
मॉड्यूल ऐक्सेस करें
डाउनलोड किए गए मॉड्यूल से कोड और संसाधनों को ऐक्सेस करने के लिए, आपके ऐप्लिकेशन को अपने ऐप्लिकेशन और डाउनलोड किए गए फ़ीचर मॉड्यूल की हर गतिविधि के लिए, SplitCompat लाइब्रेरी चालू करनी होगी.
हालांकि, आपको यह ध्यान रखना चाहिए कि मॉड्यूल डाउनलोड करने के बाद, कुछ समय (कुछ मामलों में, कुछ दिन) तक प्लैटफ़ॉर्म पर मॉड्यूल का कॉन्टेंट ऐक्सेस करने से जुड़ी ये पाबंदियां लागू होती हैं:
- प्लैटफ़ॉर्म, मॉड्यूल की ओर से जोड़ी गई किसी भी नई मेनिफ़ेस्ट एंट्री को लागू नहीं कर सकता.
- प्लैटफ़ॉर्म, सिस्टम के यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट, जैसे कि सूचनाओं के लिए, मॉड्यूल के संसाधनों को ऐक्सेस नहीं कर सकता. अगर आपको ऐसे रिसॉर्स तुरंत इस्तेमाल करने हैं, तो अपने ऐप्लिकेशन के बेस मॉड्यूल में उन रिसॉर्स को शामिल करें.
SplitCompat चालू करें
डाउनलोड किए गए मॉड्यूल से कोड और संसाधनों को ऐक्सेस करने के लिए, आपको यहां दिए गए किसी एक तरीके का इस्तेमाल करके SplitCompat को चालू करना होगा.
अपने ऐप्लिकेशन के लिए SplitCompat चालू करने के बाद, आपको उन सुविधा मॉड्यूल में हर गतिविधि के लिए SplitCompat चालू करना होगा जिनका ऐक्सेस आपको अपने ऐप्लिकेशन को देना है.
मेनिफ़ेस्ट में SplitCompatApplication का एलान करना
SplitCompat को चालू करने का सबसे आसान तरीका यह है कि आप अपने ऐप्लिकेशन के मेनिफ़ेस्ट में, SplitCompatApplication
को Application
सबक्लास के तौर पर एलान करें. इसके लिए, यहां दिया गया तरीका अपनाएं:
<application
...
android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
</application>
डिवाइस पर ऐप्लिकेशन इंस्टॉल होने के बाद, डाउनलोड किए गए फ़ीचर मॉड्यूल से कोड और संसाधन अपने-आप ऐक्सेस किए जा सकते हैं.
रनटाइम के दौरान SplitCompat शुरू करें
रनटाइम के दौरान, खास गतिविधियों या सेवाओं में SplitCompat को भी चालू किया जा सकता है.
सुविधा वाले मॉड्यूल में शामिल गतिविधियों को लॉन्च करने के लिए, SplitCompat को इस तरह चालू करना ज़रूरी है. ऐसा करने के लिए, नीचे बताए गए तरीके से attachBaseContext
को बदलें.
अगर आपके पास पसंद के मुताबिक कोई Application क्लास है, तो उसे अपने ऐप्लिकेशन के लिए SplitCompat चालू करने के बजाय SplitCompatApplication
को बढ़ाएं, जैसा कि नीचे दिखाया गया है:
Kotlin
class MyApplication : SplitCompatApplication() { ... }
Java
public class MyApplication extends SplitCompatApplication { ... }
SplitCompatApplication
, SplitCompat.install(Context applicationContext)
को शामिल करने के लिए ContextWrapper.attachBaseContext()
को बदल देता है. अगर आपको अपनी Application
क्लास को SplitCompatApplication
तक नहीं बढ़ाना है, तो attachBaseContext()
तरीके को मैन्युअल तरीके से बदला जा सकता है. इसके लिए, यह तरीका अपनाएं:
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // Emulates installation of future on demand modules using SplitCompat. SplitCompat.install(this) }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // Emulates installation of future on demand modules using SplitCompat. SplitCompat.install(this); }
अगर आपका ऑन डिमांड मॉड्यूल, इंस्टैंट ऐप्लिकेशन और इंस्टॉल किए गए ऐप्लिकेशन, दोनों के साथ काम करता है, तो SplitCompat को शर्तों के साथ, इस तरह शुरू किया जा सकता है:
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this) } }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this); } }
मॉड्यूल गतिविधियों के लिए SplitCompat चालू करें
अपने बुनियादी ऐप्लिकेशन के लिए SplitCompat चालू करने के बाद, आपको हर उस गतिविधि के लिए SplitCompat चालू करना होगा जिसे आपका ऐप्लिकेशन, किसी फ़ीचर मॉड्यूल में डाउनलोड करता है. ऐसा करने के लिए,
SplitCompat.installActivity()
तरीके का इस्तेमाल करें. इसके लिए, यह तरीका अपनाएं:
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // Emulates installation of on demand modules using SplitCompat. SplitCompat.installActivity(this) }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // Emulates installation of on demand modules using SplitCompat. SplitCompat.installActivity(this); }
फ़ीचर मॉड्यूल में तय किए गए कॉम्पोनेंट ऐक्सेस करना
सुविधा वाले मॉड्यूल में बताई गई गतिविधि शुरू करना
SplitCompat को चालू करने के बाद
startActivity()
का इस्तेमाल करके, फ़ीचर मॉड्यूल में बताई गई गतिविधियों को लॉन्च किया जा सकता है.
Kotlin
startActivity(Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...))
Java
startActivity(new Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...));
setClassName
का पहला पैरामीटर, ऐप्लिकेशन के पैकेज का नाम है और दूसरा पैरामीटर, ऐक्टिविटी की पूरी क्लास का नाम है.
अगर आपने मांग पर डाउनलोड किए गए सुविधा वाले मॉड्यूल में कोई गतिविधि की है, तो आपको गतिविधि में SplitCompat को चालू करना होगा.
सुविधा मॉड्यूल में बताई गई सेवा शुरू करना
SplitCompat को चालू करने के बाद, startService()
का इस्तेमाल करके, सुविधा वाले मॉड्यूल में बताई गई सेवाएं लॉन्च की जा सकती हैं.
Kotlin
startService(Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...))
Java
startService(new Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...));
सुविधा वाले मॉड्यूल में तय किए गए कॉम्पोनेंट को एक्सपोर्ट करना
आपको वैकल्पिक मॉड्यूल में, एक्सपोर्ट किए गए Android कॉम्पोनेंट शामिल नहीं करने चाहिए.
बिल्ड सिस्टम, सभी मॉड्यूल के मेनिफ़ेस्ट एंट्री को बेस मॉड्यूल में मर्ज करता है. अगर किसी वैकल्पिक मॉड्यूल में एक्सपोर्ट किया गया कॉम्पोनेंट है, तो मॉड्यूल के इंस्टॉल होने से पहले भी उसे ऐक्सेस किया जा सकता है. साथ ही, किसी दूसरे ऐप्लिकेशन से उसे ट्रिगर करने पर, कोड मौजूद न होने की वजह से ऐप्लिकेशन क्रैश हो सकता है.
यह समस्या, संगठन के कॉम्पोनेंट के लिए नहीं है. इन्हें सिर्फ़ ऐप्लिकेशन ऐक्सेस करता है. इसलिए, ऐप्लिकेशन कॉम्पोनेंट को ऐक्सेस करने से पहले, यह देख सकता है कि मॉड्यूल इंस्टॉल है या नहीं.
अगर आपको एक्सपोर्ट किए गए किसी कॉम्पोनेंट की ज़रूरत है और आपको उसका कॉन्टेंट किसी वैकल्पिक मॉड्यूल में रखना है, तो प्रॉक्सी पैटर्न लागू करें.
ऐसा करने के लिए, बेस में एक्सपोर्ट किया गया प्रॉक्सी कॉम्पोनेंट जोड़ें; ऐक्सेस किए जाने पर, प्रॉक्सी कॉम्पोनेंट उस मॉड्यूल की मौजूदगी की जांच कर सकता है जिसमें कॉन्टेंट है. अगर मॉड्यूल मौजूद है, तो प्रॉक्सी कॉम्पोनेंट, Intent
के ज़रिए मॉड्यूल से इंटरनल कॉम्पोनेंट को शुरू कर सकता है. इसके लिए, वह कॉलर ऐप्लिकेशन से मिलने वाले इंटेंट को फिर से भेजता है. अगर मॉड्यूल मौजूद नहीं है, तो कॉम्पोनेंट मॉड्यूल को डाउनलोड कर सकता है या कॉलर ऐप्लिकेशन को गड़बड़ी का सही मैसेज भेज सकता है.
इंस्टॉल किए गए मॉड्यूल से कोड और संसाधन ऐक्सेस करना
अगर आपने अपने ऐप्लिकेशन के मुख्य कॉन्टेक्स्ट और सुविधा वाले मॉड्यूल में मौजूद गतिविधियों के लिए, SplitCompat को चालू किया है, तो वैकल्पिक मॉड्यूल इंस्टॉल होने के बाद, सुविधा वाले मॉड्यूल के कोड और संसाधनों का इस्तेमाल, मुख्य APK के हिस्से के तौर पर किया जा सकता है.
किसी दूसरे मॉड्यूल से ऐक्सेस कोड
किसी मॉड्यूल से बुनियादी कोड ऐक्सेस करना
आपके बेस मॉड्यूल में मौजूद कोड का इस्तेमाल, दूसरे मॉड्यूल सीधे तौर पर कर सकते हैं. इसके लिए, आपको कुछ भी खास करने की ज़रूरत नहीं है. बस अपनी ज़रूरत के हिसाब से क्लास इंपोर्ट करें और उनका इस्तेमाल करें.
किसी दूसरे मॉड्यूल से मॉड्यूल कोड ऐक्सेस करें
किसी मॉड्यूल में मौजूद ऑब्जेक्ट या क्लास को, किसी दूसरे मॉड्यूल से सीधे तौर पर स्टैटिक तौर पर ऐक्सेस नहीं किया जा सकता. हालांकि, रिफ़्लेक्शन का इस्तेमाल करके, उसे किसी दूसरे मॉड्यूल से ऐक्सेस किया जा सकता है.
आपको इस बात का ध्यान रखना चाहिए कि ऐसा कितनी बार होता है, क्योंकि रीफ़्लेक्शन की वजह से परफ़ॉर्मेंस पर असर पड़ता है. मुश्किल इस्तेमाल के मामलों के लिए, Dagger 2 जैसे डिपेंडेंसी इंजेक्शन फ़्रेमवर्क का इस्तेमाल करें. इससे यह पक्का किया जा सकेगा कि हर ऐप्लिकेशन में एक ही रिफ़्लेक्शन कॉल होगा.
इंस्टैंशिएट करने के बाद, ऑब्जेक्ट के साथ इंटरैक्शन को आसान बनाने के लिए, बेस मॉड्यूल में इंटरफ़ेस और सुविधा मॉड्यूल में उसे लागू करने का तरीका तय करने का सुझाव दिया जाता है. उदाहरण के लिए:
Kotlin
// In the base module interface MyInterface { fun hello(): String } // In the feature module object MyInterfaceImpl : MyInterface { override fun hello() = "Hello" } // In the base module, where we want to access the feature module code val stringFromModule = (Class.forName("com.package.module.MyInterfaceImpl") .kotlin.objectInstance as MyInterface).hello();
Java
// 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 Tips में, ReLinker के बारे में ज़्यादा जानें.
किसी वैकल्पिक मॉड्यूल से नेटिव कोड लोड करना
स्प्लिट इंस्टॉल होने के बाद, हमारा सुझाव है कि आप ReLinker की मदद से उसका नेटिव कोड लोड करें. इंस्टैंट ऐप्लिकेशन के लिए, आपको इस खास तरीके का इस्तेमाल करना चाहिए.
अगर आपने अपना नेटिव कोड लोड करने के लिए System.loadLibrary()
का इस्तेमाल किया है और आपकी नेटिव लाइब्रेरी, मॉड्यूल की किसी दूसरी लाइब्रेरी पर निर्भर है, तो आपको पहले उस लाइब्रेरी को मैन्युअल तरीके से लोड करना होगा.
अगर ReLinker का इस्तेमाल किया जा रहा है, तो इसके लिए Relinker.recursively().loadLibrary()
का इस्तेमाल किया जा सकता है.
अगर किसी वैकल्पिक मॉड्यूल में बताई गई लाइब्रेरी को लोड करने के लिए, नेटिव कोड में dlopen()
का इस्तेमाल किया जा रहा है, तो यह रिलेटिव लाइब्रेरी पाथ के साथ काम नहीं करेगा.
इसका सबसे सही हल है कि आप ClassLoader.findLibrary()
के ज़रिए, Java कोड से लाइब्रेरी के ऐब्सलूट पाथ को फिर से पाएं. इसके बाद, dlopen()
कॉल में इसका इस्तेमाल करें.
नेटिव कोड डालने से पहले ऐसा करें या अपने नेटिव कोड से Java में JNI कॉल का इस्तेमाल करें.
इंस्टॉल किए गए Android Instant Apps को ऐक्सेस करें
जब Android Instant App मॉड्यूल INSTALLED
के तौर पर रिपोर्ट करता है, तो रीफ़्रेश किए गए ऐप्लिकेशन कॉन्टेक्स्ट का इस्तेमाल करके, उसका कोड और संसाधन ऐक्सेस किए जा सकते हैं. आपका ऐप्लिकेशन, मॉड्यूल इंस्टॉल करने से पहले जो कॉन्टेक्स्ट बनाता है (उदाहरण के लिए, ऐसा कॉन्टेक्स्ट जो पहले से किसी वैरिएबल में सेव है) में नए मॉड्यूल का कॉन्टेंट नहीं होता है. हालांकि, एक नए संदर्भ में यह जानकारी दी गई है. उदाहरण के लिए, इसे createPackageContext
का इस्तेमाल करके हासिल किया जा सकता है.
Kotlin
// Generate a new context as soon as a request for a new module // reports as INSTALLED. override fun onStateUpdate(state: SplitInstallSessionState ) { if (state.sessionId() == mySessionId) { when (state.status()) { ... SplitInstallSessionStatus.INSTALLED -> { val newContext = context.createPackageContext(context.packageName, 0) // If you use AssetManager to access your app’s raw asset files, you’ll need // to generate a new AssetManager instance from the updated context. val am = newContext.assets } } } }
Java
// 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 (एपीआई लेवल 26) और उसके बाद के वर्शन पर काम करने वाले Android Instant App के लिए, मांग पर मॉड्यूल का अनुरोध करने पर, इंस्टॉल का अनुरोध INSTALLED
के तौर पर रिपोर्ट करने के बाद, आपको SplitInstallHelper.updateAppInfo(Context context)
पर कॉल करके ऐप्लिकेशन को नए मॉड्यूल के हिसाब से अपडेट करना होगा.
ऐसा नहीं करने पर, ऐप्लिकेशन को अभी तक मॉड्यूल के कोड और संसाधनों की जानकारी नहीं है. ऐप्लिकेशन का मेटाडेटा अपडेट करने के बाद, अगले मुख्य थ्रेड इवेंट के दौरान मॉड्यूल का कॉन्टेंट लोड करने के लिए, नए Handler
का इस्तेमाल करें, जैसा कि यहां दिखाया गया है:
Kotlin
override fun onStateUpdate(state: SplitInstallSessionState ) { if (state.sessionId() == mySessionId) { when (state.status()) { ... SplitInstallSessionStatus.INSTALLED -> { // You need to perform the following only for Android Instant Apps // running on Android 8.0 (API level 26) and higher. if (BuildCompat.isAtLeastO()) { // Updates the app’s context with the code and resources of the // installed module. SplitInstallHelper.updateAppInfo(context) Handler().post { // Loads contents from the module using AssetManager val am = context.assets ... } } } } } }
Java
@Override public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { ... case SplitInstallSessionStatus.INSTALLED: // You need to perform the following only for Android Instant Apps // running on Android 8.0 (API level 26) and higher. if (BuildCompat.isAtLeastO()) { // Updates the app’s context with the code and resources of the // installed module. SplitInstallHelper.updateAppInfo(context); new Handler().post(new Runnable() { @Override public void run() { // Loads contents from the module using AssetManager AssetManager am = context.getAssets(); ... } }); } } } }
C/C++ लाइब्रेरी लोड करना
अगर आपको किसी ऐसे मॉड्यूल से C/C++ लाइब्रेरी लोड करनी हैं जिसे डिवाइस ने इंस्टैंट ऐप्लिकेशन में पहले से डाउनलोड किया है, तो SplitInstallHelper.loadLibrary(Context context, String libName)
का इस्तेमाल करें, जैसा कि यहां दिखाया गया है:
Kotlin
override fun onStateUpdate(state: SplitInstallSessionState) { if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Updates the app’s context as soon as a module is installed. val newContext = context.createPackageContext(context.packageName, 0) // To load C/C++ libraries from an installed module, use the following API // instead of System.load(). SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”) ... } } } }
Java
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 वेबव्यू का इस्तेमाल नहीं किया जा सकता जो वैकल्पिक मॉड्यूल से संसाधन या एसेट ऐक्सेस करता है. ऐसा इसलिए होता है, क्योंकि Android एपीआई लेवल 28 और उससे पहले के वर्शन पर, WebView और SplitCompat के बीच काम करने में समस्या आती है.
- Android
ApplicationInfo
के ऑब्जेक्ट, कॉन्टेंट या उन ऑब्जेक्ट को कैश मेमोरी में नहीं रखा जा सकता जिनमें वे आपके ऐप्लिकेशन में मौजूद हैं. आपको ऐप्लिकेशन के कॉन्टेक्स्ट से ज़रूरत के मुताबिक इन ऑब्जेक्ट को फ़ेच करना चाहिए. ऐसे ऑब्जेक्ट को कैश मेमोरी में सेव करने से, फ़ीचर मॉड्यूल इंस्टॉल करते समय ऐप्लिकेशन क्रैश हो सकता है.
इंस्टॉल किए गए मॉड्यूल मैनेज करना
यह देखने के लिए कि डिवाइस पर फ़िलहाल कौनसे सुविधा वाले मॉड्यूल इंस्टॉल हैं, SplitInstallManager.getInstalledModules()
को कॉल करें. इससे, इंस्टॉल किए गए मॉड्यूल के नामों का Set<String>
दिखेगा, जैसा कि नीचे दिखाया गया है.
Kotlin
val installedModules: Set<String> = splitInstallManager.installedModules
Java
Set<String> installedModules = splitInstallManager.getInstalledModules();
मॉड्यूल अनइंस्टॉल करना
SplitInstallManager.deferredUninstall(List<String> moduleNames)
को चालू करके, डिवाइस से मॉड्यूल अनइंस्टॉल करने का अनुरोध किया जा सकता है. इसके बारे में यहां बताया गया है.
Kotlin
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))
Java
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));
मॉड्यूल तुरंत अनइंस्टॉल नहीं होते. इसका मतलब है कि
डिवाइस, स्टोरेज में जगह बचाने के लिए ज़रूरत पड़ने पर उन्हें बैकग्राउंड में अनइंस्टॉल कर देता है.
पिछले सेक्शन में बताए गए तरीके से, SplitInstallManager.getInstalledModules()
को चालू करके और नतीजे की जांच करके इस बात की पुष्टि की जा सकती है कि डिवाइस ने कोई मॉड्यूल मिटा दिया है.
अन्य भाषाओं के संसाधन डाउनलोड करना
ऐप्लिकेशन बंडल की मदद से, डिवाइस सिर्फ़ वही कोड और संसाधन डाउनलोड करते हैं जो आपके ऐप्लिकेशन को चलाने के लिए ज़रूरी होते हैं. इसलिए, उपयोगकर्ता का डिवाइस सिर्फ़ आपके ऐप्लिकेशन के भाषा के ऐसे रिसॉर्स डाउनलोड करता है जो डिवाइस की सेटिंग में चुनी गई एक या उससे ज़्यादा भाषाओं से मेल खाते हैं.
अगर आपको अपने ऐप्लिकेशन को भाषा के अन्य संसाधनों का ऐक्सेस देना है, जैसे कि इन-ऐप्लिकेशन लैंग्वेज पिकर की सुविधा लागू करना, तो मांग पर उन्हें डाउनलोड करने के लिए, Play Feature Delivery लाइब्रेरी का इस्तेमाल करें. यह प्रोसेस, किसी सुविधा वाले मॉड्यूल को डाउनलोड करने की प्रोसेस से मिलती-जुलती है. इसकी जानकारी नीचे दी गई है.
Kotlin
// Captures the user’s preferred language and persists it // through the app’s SharedPreferences. sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply() ... // Creates a request to download and install additional language resources. val request = SplitInstallRequest.newBuilder() // Uses the addLanguage() method to include French language resources in the request. // Note that country codes are ignored. That is, if your app // includes resources for “fr-FR” and “fr-CA”, resources for both // country codes are downloaded when requesting resources for "fr". .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build() // Submits the request to install the additional language resources. splitInstallManager.startInstall(request)
Java
// Captures the user’s preferred language and persists it // through the app’s SharedPreferences. sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply(); ... // Creates a request to download and install additional language resources. SplitInstallRequest request = SplitInstallRequest.newBuilder() // Uses the addLanguage() method to include French language resources in the request. // Note that country codes are ignored. That is, if your app // includes resources for “fr-FR” and “fr-CA”, resources for both // country codes are downloaded when requesting resources for "fr". .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build(); // Submits the request to install the additional language resources. splitInstallManager.startInstall(request);
इस अनुरोध को किसी सुविधा मॉड्यूल के अनुरोध के तौर पर मैनेज किया जाता है. इसका मतलब है कि अनुरोध की स्थिति को मॉनिटर किया जा सकता है, जैसा कि आम तौर पर किया जाता है.
अगर आपके ऐप्लिकेशन को तुरंत, भाषा के अतिरिक्त संसाधनों की ज़रूरत नहीं पड़ती, तो बैकग्राउंड में ऐप्लिकेशन को इंस्टॉल किए जाने की तारीख आगे बढ़ाई जा सकती है, जैसा कि नीचे दिखाया गया है.
Kotlin
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
Java
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
भाषा के लिए डाउनलोड किए गए संसाधनों को ऐक्सेस करना
डाउनलोड की गई भाषा के रिसॉर्स का ऐक्सेस पाने के लिए, आपके ऐप्लिकेशन को हर एक गतिविधि के लिए, attachBaseContext()
तरीके में बताए गए SplitCompat.installActivity()
तरीके का इस्तेमाल करना होगा. इसके लिए, इन संसाधनों का ऐक्सेस ज़रूरी है. इसके बारे में नीचे बताया गया है.
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) SplitCompat.installActivity(this) }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); SplitCompat.installActivity(this); }
हर उस गतिविधि के लिए जिसे आपको अपने ऐप्लिकेशन के डाउनलोड किए गए भाषा के संसाधनों का इस्तेमाल करना है, बुनियादी संदर्भ को अपडेट करें और उसके Configuration
के ज़रिए एक नई स्थान-भाषा सेट करें:
Kotlin
override fun attachBaseContext(base: Context) { val configuration = Configuration() configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) val context = base.createConfigurationContext(configuration) super.attachBaseContext(context) SplitCompat.install(this) }
Java
@Override protected void attachBaseContext(Context base) { Configuration configuration = new Configuration(); configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))); Context context = base.createConfigurationContext(configuration); super.attachBaseContext(context); SplitCompat.install(this); }
इन बदलावों को लागू करने के लिए, आपको नई भाषा के इंस्टॉल होने और इस्तेमाल के लिए तैयार होने के बाद, अपनी गतिविधि फिर से बनानी होगी. Activity#recreate()
तरीके का इस्तेमाल किया जा सकता है.
Kotlin
when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Recreates the activity to load resources for the new language // preference. activity.recreate() } ... }
Java
switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: // Recreates the activity to load resources for the new language // preference. activity.recreate(); ... }
भाषा के अन्य संसाधनों को अनइंस्टॉल करना
फ़ीचर मॉड्यूल की तरह ही, दूसरे संसाधनों को किसी भी समय अनइंस्टॉल किया जा सकता है. अनइंस्टॉल करने का अनुरोध करने से पहले, यह पता लगाएं कि फ़िलहाल कौनसी भाषाएं इंस्टॉल हैं. इसके लिए, यह तरीका अपनाएं.
Kotlin
val installedLanguages: Set<String> = splitInstallManager.installedLanguages
Java
Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();
इसके बाद, यह तय किया जा सकता है कि deferredLanguageUninstall()
तरीके का इस्तेमाल करके कौनसी भाषाएं अनइंस्टॉल करनी हैं, जैसा कि यहां दिखाया गया है.
Kotlin
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
Java
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
स्थानीय तौर पर टेस्ट मॉड्यूल इंस्टॉल
Play Feature Delivery Library आपको Play Store से कनेक्ट किए बिना, स्थानीय तौर पर अपने ऐप्लिकेशन के लिए ये काम करने की क्षमता की जांच करने की सुविधा देती है:
- मॉड्यूल इंस्टॉल का अनुरोध करें और उन्हें मॉनिटर करें.
- इंस्टॉल करने में आने वाली गड़बड़ियां मैनेज करना.
- मॉड्यूल ऐक्सेस करने के लिए
SplitCompat
का इस्तेमाल करें.
इस पेज पर, टेस्टिंग के लिए इस्तेमाल किए जाने वाले डिवाइस पर, ऐप्लिकेशन के अलग-अलग APKs को डिप्लॉय करने का तरीका बताया गया है. इससे Play Feature Delivery, Play Store से मॉड्यूल का अनुरोध करने, उन्हें डाउनलोड करने, और इंस्टॉल करने के लिए, उन APKs का अपने-आप इस्तेमाल कर पाता है.
हालांकि, आपको अपने ऐप्लिकेशन के लॉजिक में कोई बदलाव करने की ज़रूरत नहीं है, लेकिन आपको ये ज़रूरी शर्तें पूरी करनी होंगी:
bundletool
का नया वर्शन डाउनलोड और इंस्टॉल करें. आपको अपने ऐप्लिकेशन के बंडल से, इंस्टॉल किए जा सकने वाले APK का नया सेट बनाने के लिएbundletool
की ज़रूरत होगी.
APK का सेट बनाना
अगर आपने अब तक ऐसा नहीं किया है, तो अपने ऐप्लिकेशन के अलग-अलग APK बनाएं. इसके लिए, यह तरीका अपनाएं:
- इनमें से किसी एक तरीके का इस्तेमाल करके, अपने ऐप्लिकेशन के लिए ऐप्लिकेशन बंडल बनाएं:
- Android ऐप्लिकेशन बंडल बनाने और उस पर हस्ताक्षर करने के लिए, Android Studio और Gradle के लिए Android प्लग इन का इस्तेमाल करें.
- कमांड लाइन से अपना ऐप्लिकेशन बंडल बनाएं.
सभी डिवाइस कॉन्फ़िगरेशन के लिए, एपीके का एक सेट जनरेट करने के लिए,
bundletool
का इस्तेमाल करें. इसके लिए, यह कमांड इस्तेमाल करें:bundletool build-apks --local-testing --bundle my_app.aab --output my_app.apks
--local-testing
फ़्लैग में आपके APK के मेनिफ़ेस्ट में मौजूद मेटा-डेटा शामिल होता है. इसकी मदद से, Play Feature Delivery लाइब्रेरी को यह पता चलता है कि वे लोकल स्प्लिट APKs का इस्तेमाल करके, सुविधाओं वाले मॉड्यूल इंस्टॉल करने की जांच करने के लिए, Play Store से कनेक्ट किए बिना ही
ऐप्लिकेशन इंस्टॉल कर सकते हैं.
अपने ऐप्लिकेशन को डिवाइस पर डिप्लॉय करें
--local-testing
फ़्लैग का इस्तेमाल करके APK का सेट बनाने के बाद,
अपने ऐप्लिकेशन का बेस वर्शन इंस्टॉल करने और अन्य APK को डिवाइस के लोकल स्टोरेज में ट्रांसफ़र करने के लिए, bundletool
का इस्तेमाल करें. इन दोनों कार्रवाइयों को करने के लिए, यह कमांड इस्तेमाल करें:
bundletool install-apks --apks my_app.apks
अब जब आपका ऐप्लिकेशन शुरू होता है और किसी सुविधा वाले मॉड्यूल को डाउनलोड और इंस्टॉल करने के लिए उपयोगकर्ता फ़्लो पूरा होता है, तो Play की सुविधा डिलीवरी लाइब्रेरी उन APKs का इस्तेमाल करती है जिन्हें bundletool
डिवाइस के लोकल स्टोरेज में ट्रांसफ़र किया गया है.
नेटवर्क की गड़बड़ी को सिम्युलेट करना
Play Store से मॉड्यूल इंस्टॉल करने की प्रोसेस को सिम्युलेट करने के लिए, Play Feature Delivery लाइब्रेरी
में, मॉड्यूल का अनुरोध करने के लिए
SplitInstallManager
के अलावा एक विकल्प का इस्तेमाल
FakeSplitInstallManager
किया जाता है. APK का सेट बनाने और उसे टेस्ट डिवाइस पर डिप्लॉय करने के लिए, --local-testing
फ़्लैग के साथ bundletool
का इस्तेमाल करने पर, इसमें मेटाडेटा शामिल होता है. यह मेटाडेटा, Play की सुविधा डिलीवरी लाइब्रेरी को निर्देश देता है कि वह आपके ऐप्लिकेशन के एपीआई कॉल को अपने-आप स्विच कर दे, ताकि SplitInstallManager
के बजाय FakeSplitInstallManager
को ट्रिगर किया जा सके.
FakeSplitInstallManager
में एक बूलियन फ़्लैग होता है. इसे चालू करके, अगली बार आपके ऐप्लिकेशन से मॉड्यूल इंस्टॉल करने का अनुरोध करने पर, नेटवर्क की गड़बड़ी को सिम्युलेट किया जा सकता है. अपने टेस्ट में FakeSplitInstallManager
को ऐक्सेस करने के लिए, FakeSplitInstallManagerFactory
का इस्तेमाल करके इसका एक इंस्टेंस पाएं, जैसा कि नीचे दिखाया गया है:
Kotlin
// Creates an instance of FakeSplitInstallManager with the app's context. val fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context) // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true)
Java
// 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);