Google Play की ज़रूरी शर्त है कि उपयोगकर्ताओं के डाउनलोड किए गए कंप्रेस किए गए APK का साइज़ 100 एमबी से ज़्यादा न हो. ज़्यादातर ऐप्लिकेशन के लिए, यह जगह ऐप्लिकेशन के सभी कोड और ऐसेट के लिए काफ़ी होती है. हालांकि, कुछ ऐप्लिकेशन को हाई-फ़िडेलिटी ग्राफ़िक, मीडिया फ़ाइलों या अन्य बड़ी ऐसेट के लिए ज़्यादा स्टोरेज की ज़रूरत होती है. पहले, अगर आपके ऐप्लिकेशन का कंप्रेस किया गया डाउनलोड साइज़ 100 एमबी से ज़्यादा होता था, तो उपयोगकर्ता के ऐप्लिकेशन खोलने पर आपको अतिरिक्त संसाधनों को खुद होस्ट और डाउनलोड करना पड़ता था. अतिरिक्त फ़ाइलों को होस्ट और उपलब्ध कराने में ज़्यादा खर्च आ सकता है. साथ ही, उपयोगकर्ता अनुभव भी अक्सर अच्छा नहीं होता. इस प्रोसेस को आपके लिए आसान बनाने और उपयोगकर्ताओं के लिए बेहतर बनाने के लिए, Google Play आपको दो बड़ी एक्सपैंशन फ़ाइलें अटैच करने की अनुमति देता है. ये फ़ाइलें, आपके APK के साथ काम करती हैं.
Google Play, आपके ऐप्लिकेशन के लिए एक्सपैंशन फ़ाइलें होस्ट करता है. साथ ही, उन्हें डिवाइस पर उपलब्ध कराता है. इसके लिए, आपसे कोई शुल्क नहीं लिया जाता. एक्सपैंशन फ़ाइलों को डिवाइस की शेयर की गई स्टोरेज लोकेशन (एसडी कार्ड या यूएसबी का माउंट किया जा सकने वाला हिस्सा; इसे "बाहरी" स्टोरेज भी कहा जाता है) में सेव किया जाता है. यहां से आपका ऐप्लिकेशन इन्हें ऐक्सेस कर सकता है. ज़्यादातर डिवाइसों पर, Google Play APK डाउनलोड करते समय ही एक या उससे ज़्यादा एक्सपैंशन फ़ाइलें डाउनलोड कर लेता है. इसलिए, जब उपयोगकर्ता पहली बार आपका ऐप्लिकेशन खोलता है, तो उसके पास वे सभी फ़ाइलें होती हैं जिनकी उसे ज़रूरत होती है. हालांकि, कुछ मामलों में आपके ऐप्लिकेशन को शुरू होने पर, Google Play से फ़ाइलें डाउनलोड करनी होंगी.
अगर आपको एक्सपैंशन फ़ाइलों का इस्तेमाल नहीं करना है और आपके ऐप्लिकेशन का कंप्रेस किया गया डाउनलोड साइज़ 100 एमबी से ज़्यादा है, तो आपको अपने ऐप्लिकेशन को Android ऐप्लिकेशन बंडल का इस्तेमाल करके अपलोड करना चाहिए. इससे, कंप्रेस किए गए डाउनलोड साइज़ को 500 एमबी तक रखा जा सकता है. इसके अलावा, ऐप्लिकेशन बंडल का इस्तेमाल करने से, APK जनरेट करने और साइन करने का काम Google Play को सौंप दिया जाता है. इसलिए, लोग ऑप्टिमाइज़ किए गए APK डाउनलोड करते हैं. इनमें सिर्फ़ वही कोड और संसाधन होते हैं जिनकी ज़रूरत आपके ऐप्लिकेशन को चलाने के लिए होती है. आपको कई APK या एक्सपैंशन फ़ाइलें बनाने, साइन करने, और मैनेज करने की ज़रूरत नहीं होती. साथ ही, लोगों को छोटे और ज़्यादा ऑप्टिमाइज़ किए गए डाउनलोड मिलते हैं.
खास जानकारी
Google Play Console का इस्तेमाल करके, हर बार APK अपलोड करते समय, आपके पास APK में एक या दो एक्सपैंशन फ़ाइलें जोड़ने का विकल्प होता है. हर फ़ाइल का साइज़ ज़्यादा से ज़्यादा दो जीबी हो सकता है. साथ ही, यह किसी भी फ़ॉर्मैट में हो सकती है. हालांकि, हमारा सुझाव है कि डाउनलोड के दौरान बैंडविथ बचाने के लिए, कंप्रेस की गई फ़ाइल का इस्तेमाल करें. हर एक्सपैंशन फ़ाइल की भूमिका अलग होती है:
- मुख्य एक्सपैंशन फ़ाइल, आपके ऐप्लिकेशन के लिए ज़रूरी अतिरिक्त संसाधनों की प्राइमरी एक्सपैंशन फ़ाइल होती है.
- पैच एक्सपैंशन फ़ाइल को अपलोड करना ज़रूरी नहीं है. इसका इस्तेमाल, मुख्य एक्सपैंशन फ़ाइल में छोटे अपडेट करने के लिए किया जाता है.
एक्सपैंशन फ़ाइलों का इस्तेमाल अपनी ज़रूरत के हिसाब से किया जा सकता है. हालांकि, हमारा सुझाव है कि मुख्य एक्सपैंशन फ़ाइल में मुख्य ऐसेट शामिल हों और इसे कभी-कभार ही अपडेट किया जाना चाहिए. पैच एक्सपैंशन फ़ाइल छोटी होनी चाहिए और इसे "पैच कैरियर" के तौर पर इस्तेमाल किया जाना चाहिए. इसे हर मुख्य रिलीज़ के साथ या ज़रूरत के हिसाब से अपडेट किया जाना चाहिए.
हालांकि, अगर आपके ऐप्लिकेशन के अपडेट के लिए सिर्फ़ नई पैच एक्सपैंशन फ़ाइल की ज़रूरत है, तब भी आपको मेनिफ़ेस्ट में अपडेट किए गए versionCode के साथ नया APK अपलोड करना होगा. (Play Console में, किसी मौजूदा APK में एक्सपैंशन फ़ाइल अपलोड करने की अनुमति नहीं है.)
ध्यान दें: पैच एक्सपैंशन फ़ाइल, मुख्य एक्सपैंशन फ़ाइल की तरह ही होती है. इसलिए, हर फ़ाइल को अपनी ज़रूरत के हिसाब से इस्तेमाल किया जा सकता है.
फ़ाइल के नाम का फ़ॉर्मैट
अपलोड की जाने वाली हर एक्सपैंशन फ़ाइल, आपके चुने हुए किसी भी फ़ॉर्मैट (ZIP, PDF, MP4 वगैरह) में हो सकती है. JOBB टूल का इस्तेमाल करके, संसाधनों की फ़ाइलों के सेट और उस सेट के लिए बाद के पैच को एन्कैप्सुलेट और एन्क्रिप्ट (सुरक्षित) किया जा सकता है. फ़ाइल टाइप चाहे जो भी हो, Google Play उन्हें ओपेक बाइनरी ब्लॉब मानता है. साथ ही, फ़ाइलों का नाम बदलने के लिए इस स्कीम का इस्तेमाल करता है:
[main|patch].<expansion-version>.<package-name>.obb
इस स्कीम में तीन कॉम्पोनेंट हैं:
mainयाpatch- इससे पता चलता है कि फ़ाइल, मुख्य एक्सपैंशन फ़ाइल है या पैच एक्सपैंशन फ़ाइल. हर APK के लिए, सिर्फ़ एक मुख्य फ़ाइल और एक पैच फ़ाइल हो सकती है.
<expansion-version>- यह एक पूर्णांक है. यह उस APK के वर्शन कोड से मेल खाता है जिससे एक्सपैंशन पहली बार जुड़ा था. यह ऐप्लिकेशन की
android:versionCodeवैल्यू से मेल खाता है."पहली बार" पर इसलिए ज़ोर दिया गया है, क्योंकि Play Console में अपलोड की गई एक्सपैंशन फ़ाइल को नए APK के साथ फिर से इस्तेमाल किया जा सकता है. हालांकि, एक्सपैंशन फ़ाइल का नाम नहीं बदलता. यह वही नाम रहता है जो आपने फ़ाइल को पहली बार अपलोड करते समय दिया था.
<package-name>- आपके ऐप्लिकेशन के पैकेज का Java-स्टाइल वाला नाम.
उदाहरण के लिए, मान लें कि आपके APK का वर्शन 314159 है और आपके पैकेज का नाम com.example.app है. अगर आपने मुख्य विस्तार फ़ाइल अपलोड की है, तो फ़ाइल का नाम बदलकर यह हो जाएगा:
main.314159.com.example.app.obb
सेव करने की जगह
जब Google Play आपके डिवाइस पर एक्सपैंशन फ़ाइलें डाउनलोड करता है, तो वह उन्हें सिस्टम के शेयर किए गए स्टोरेज की जगह पर सेव करता है. यह पक्का करने के लिए कि ये फ़ाइलें ठीक से काम करें, आपको एक्सपैंशन फ़ाइलों को मिटाना, उनका नाम बदलना या उन्हें किसी दूसरी जगह पर ले जाना नहीं चाहिए. अगर आपके ऐप्लिकेशन को Google Play से ही डाउनलोड करना है, तो आपको फ़ाइलें उसी जगह पर सेव करनी होंगी.
getObbDir() तरीके से, आपकी एक्सपैंशन फ़ाइलों के लिए खास जगह की जानकारी मिलती है. यह जानकारी इस फ़ॉर्म में होती है:
<shared-storage>/Android/obb/<package-name>/
<shared-storage>, शेयर किए गए स्टोरेज स्पेस का पाथ है. यहgetExternalStorageDirectory()से उपलब्ध है.<package-name>आपके ऐप्लिकेशन के पैकेज का Java-स्टाइल वाला नाम है. यहgetPackageName()से उपलब्ध है.
इस डायरेक्ट्री में, हर ऐप्लिकेशन के लिए दो से ज़्यादा एक्सपैंशन फ़ाइलें नहीं होती हैं.
एक मुख्य एक्सपैंशन फ़ाइल होती है और दूसरी पैच एक्सपैंशन फ़ाइल (अगर ज़रूरी हो). नई एक्सपैंशन फ़ाइलों के साथ ऐप्लिकेशन को अपडेट करने पर, पिछले वर्शन बदल जाते हैं. Android 4.4 (एपीआई लेवल 19) के बाद से, ऐप्लिकेशन बाहरी स्टोरेज की अनुमति के बिना OBB एक्सपैंशन फ़ाइलें पढ़ सकते हैं. हालांकि, Android 6.0 (एपीआई लेवल 23) और उसके बाद के वर्शन के कुछ वर्शन में अब भी अनुमति की ज़रूरत होती है. इसलिए, आपको ऐप्लिकेशन मेनिफ़ेस्ट में READ_EXTERNAL_STORAGE अनुमति का एलान करना होगा. साथ ही, रनटाइम के दौरान इस तरह से अनुमति मांगनी होगी:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Android 6 और इसके बाद के वर्शन के लिए, रनटाइम के दौरान बाहरी स्टोरेज की अनुमति का अनुरोध करना ज़रूरी है. हालांकि, Android के कुछ वर्शन में ओबीबी फ़ाइलों को पढ़ने के लिए अनुमति की ज़रूरत नहीं होती. नीचे दिए गए कोड स्निपेट में बताया गया है कि बाहरी स्टोरेज से डेटा पढ़ने की अनुमति मांगने से पहले, यह कैसे पता लगाया जा सकता है कि ऐप्लिकेशन के पास डेटा पढ़ने का ऐक्सेस है या नहीं:
Kotlin
val obb = File(obb_filename) var open_failed = false try { BufferedReader(FileReader(obb)).also { br -> ReadObbFile(br) } } catch (e: IOException) { open_failed = true } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission() }
Java
File obb = new File(obb_filename); boolean open_failed = false; try { BufferedReader br = new BufferedReader(new FileReader(obb)); open_failed = false; ReadObbFile(br); } catch (IOException e) { open_failed = true; } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission(); }
अगर आपको अपनी एक्सपैंशन फ़ाइलों का कॉन्टेंट अनपैक करना है, तो बाद में न तो OBB एक्सपैंशन फ़ाइलों को मिटाएं और न ही अनपैक किए गए डेटा को उसी डायरेक्ट्री में सेव करें. आपको अनपैक की गई फ़ाइलों को getExternalFilesDir() में बताई गई डायरेक्ट्री में सेव करना चाहिए. हालांकि, अगर हो सके, तो ऐसे एक्सपैंशन फ़ाइल फ़ॉर्मैट का इस्तेमाल करें जिससे आपको डेटा को अनपैक करने के बजाय, सीधे फ़ाइल से डेटा पढ़ने की अनुमति मिले. उदाहरण के लिए, हमने एक लाइब्रेरी प्रोजेक्ट उपलब्ध कराया है. इसे APK Expansion Zip Library कहा जाता है. यह आपके डेटा को सीधे ZIP फ़ाइल से पढ़ता है.
चेतावनी: एपीके फ़ाइलों के उलट, शेयर किए गए स्टोरेज में सेव की गई किसी भी फ़ाइल को उपयोगकर्ता और अन्य ऐप्लिकेशन पढ़ सकते हैं.
अहम जानकारी: अगर आपको मीडिया फ़ाइलों को ZIP फ़ाइल में पैक करना है, तो ऑफ़सेट और अवधि कंट्रोल (जैसे कि MediaPlayer.setDataSource() और SoundPool.load()) के साथ फ़ाइलों पर मीडिया चलाने के लिए कॉल का इस्तेमाल किया जा सकता है. इसके लिए, आपको ZIP फ़ाइल को अनपैक करने की ज़रूरत नहीं है. इसके लिए, आपको ZIP पैकेज बनाते समय मीडिया फ़ाइलों को कंप्रेस नहीं करना चाहिए. उदाहरण के लिए, zip टूल का इस्तेमाल करते समय, आपको -n विकल्प का इस्तेमाल करना चाहिए. इससे उन फ़ाइल सफ़िक्स के बारे में बताया जा सकता है जिन्हें कंप्रेस नहीं किया जाना चाहिए:
zip -n .mp4;.ogg main_expansion media_files
डाउनलोड करने की प्रोसेस
ज़्यादातर मामलों में, Google Play आपके डिवाइस पर APK डाउनलोड करते समय ही, एक्सपैंशन फ़ाइलें डाउनलोड और सेव कर लेता है. हालांकि, कुछ मामलों में Google Play, एक्सपैंशन फ़ाइलें डाउनलोड नहीं कर पाता. इसके अलावा, ऐसा भी हो सकता है कि उपयोगकर्ता ने पहले से डाउनलोड की गई एक्सपैंशन फ़ाइलें मिटा दी हों. इन स्थितियों को मैनेज करने के लिए, आपके ऐप्लिकेशन में यह सुविधा होनी चाहिए कि मुख्य गतिविधि शुरू होने पर, वह Google Play से मिले यूआरएल का इस्तेमाल करके फ़ाइलें डाउनलोड कर सके.
बड़े लेवल पर, डाउनलोड करने की प्रोसेस इस तरह दिखती है:
- उपयोगकर्ता, Google Play से आपका ऐप्लिकेशन इंस्टॉल करने का विकल्प चुनता है.
- अगर Google Play, एक्सपैंशन फ़ाइलें डाउनलोड कर पाता है (ज़्यादातर डिवाइसों के लिए ऐसा ही होता है), तो वह उन्हें APK के साथ डाउनलोड कर लेता है.
अगर Google Play, एक्सपैंशन फ़ाइलें डाउनलोड नहीं कर पाता है, तो वह सिर्फ़ APK डाउनलोड करता है.
- जब उपयोगकर्ता आपका ऐप्लिकेशन लॉन्च करे, तो आपके ऐप्लिकेशन को यह जांच करनी चाहिए कि एक्सपैंशन फ़ाइलें पहले से ही डिवाइस पर सेव हैं या नहीं.
- अगर हां, तो आपका ऐप्लिकेशन इस्तेमाल के लिए तैयार है.
- अगर नहीं, तो आपके ऐप्लिकेशन को Google Play से एक्सपैंशन फ़ाइलें, एचटीटीपी पर डाउनलोड करनी होंगी. आपके ऐप्लिकेशन को Google Play की ऐप्लिकेशन लाइसेंसिंग सेवा का इस्तेमाल करके, Google Play क्लाइंट को अनुरोध भेजना होगा. यह सेवा, हर एक्सपैंशन फ़ाइल के लिए नाम, फ़ाइल का साइज़, और यूआरएल के साथ जवाब देती है. इस जानकारी की मदद से, फ़ाइलें डाउनलोड की जा सकती हैं. इसके बाद, उन्हें सही स्टोरेज लोकेशन में सेव किया जा सकता है.
चेतावनी: अगर आपका ऐप्लिकेशन शुरू होने पर, डिवाइस में फ़ाइलें मौजूद नहीं हैं, तो यह ज़रूरी है कि आप Google Play से फ़ाइलें डाउनलोड करने के लिए ज़रूरी कोड शामिल करें. एक्सपेंशन फ़ाइलें डाउनलोड करने के बारे में नीचे दिए गए सेक्शन में बताया गया है. हमने आपके लिए एक लाइब्रेरी उपलब्ध कराई है. इससे इस प्रोसेस को बहुत आसान बनाया जा सकता है. साथ ही, यह लाइब्रेरी, सेवा से डाउनलोड करने की प्रोसेस को पूरा करती है. इसके लिए, आपको बहुत कम कोड लिखना पड़ता है.
डेवलपमेंट चेकलिस्ट
अपने ऐप्लिकेशन के साथ एक्सपैंशन फ़ाइलों का इस्तेमाल करने के लिए, आपको ये काम करने होंगे:
- सबसे पहले यह तय करें कि क्या आपके ऐप्लिकेशन के कंप्रेस किए गए डाउनलोड साइज़ का 100 एमबी से ज़्यादा होना ज़रूरी है. स्टोरेज की जगह कीमती होती है. इसलिए, आपको डाउनलोड करने के लिए उपलब्ध कुल साइज़ को जितना हो सके उतना कम रखना चाहिए. अगर आपका ऐप्लिकेशन, अलग-अलग स्क्रीन डेंसिटी के लिए ग्राफ़िक ऐसेट के कई वर्शन उपलब्ध कराने के लिए 100 एमबी से ज़्यादा स्टोरेज इस्तेमाल करता है, तो इसके बजाय कई APK पब्लिश करें. इनमें से हर APK में सिर्फ़ उन स्क्रीन के लिए ज़रूरी ऐसेट शामिल हों जिन्हें वह टारगेट करता है. Google Play पर पब्लिश करते समय, सबसे अच्छे नतीजे पाने के लिए Android ऐप्लिकेशन बंडल अपलोड करें. इसमें आपके ऐप्लिकेशन का कंपाइल किया गया पूरा कोड और संसाधन शामिल होते हैं. हालांकि, APK जनरेट करने और साइन करने की प्रोसेस को Google Play पर बाद के लिए छोड़ दिया जाता है.
- तय करें कि आपको अपने ऐप्लिकेशन के किन संसाधनों को APK से अलग करना है. इसके बाद, उन्हें एक फ़ाइल में पैकेज करें, ताकि उन्हें मुख्य एक्सपैंशन फ़ाइल के तौर पर इस्तेमाल किया जा सके.
आम तौर पर, मुख्य एक्सपैंशन फ़ाइल को अपडेट करते समय, आपको सिर्फ़ दूसरी पैच एक्सपैंशन फ़ाइल का इस्तेमाल करना चाहिए. हालांकि, अगर आपके संसाधन, मुख्य एक्सपैंशन फ़ाइल के लिए तय की गई 2 जीबी की सीमा से ज़्यादा हैं, तो बाकी ऐसेट के लिए पैच फ़ाइल का इस्तेमाल किया जा सकता है.
- अपने ऐप्लिकेशन को इस तरह से डेवलप करें कि वह डिवाइस के शेयर किए गए स्टोरेज लोकेशन में मौजूद आपकी एक्सपैंशन फ़ाइलों के संसाधनों का इस्तेमाल करे.
ध्यान रखें कि आपको एक्सपैंशन फ़ाइलों को मिटाना, दूसरी जगह ले जाना या उनका नाम नहीं बदलना चाहिए.
अगर आपके ऐप्लिकेशन के लिए किसी खास फ़ॉर्मैट की ज़रूरत नहीं है, तो हमारा सुझाव है कि आप अपनी एक्सपैंशन फ़ाइलों के लिए ZIP फ़ाइलें बनाएं. इसके बाद, APK Expansion Zip Library का इस्तेमाल करके उन्हें पढ़ें.
- अपने ऐप्लिकेशन की मुख्य ऐक्टिविटी में ऐसा लॉजिक जोड़ें जो यह जांच करे कि स्टार्टअप के दौरान, डिवाइस पर एक्सपैंशन फ़ाइलें मौजूद हैं या नहीं. अगर फ़ाइलें डिवाइस पर नहीं हैं, तो Google Play की ऐप्लिकेशन लाइसेंसिंग सेवा का इस्तेमाल करके, एक्सपैंशन फ़ाइलों के यूआरएल का अनुरोध करें. इसके बाद, उन्हें डाउनलोड करके सेव करें.
हमारा सुझाव है कि डाउनलोड करने के तरीके को लागू करने के लिए, डाउनलोडर लाइब्रेरी का इस्तेमाल करें. इससे आपको कम कोड लिखना पड़ेगा और डाउनलोड के दौरान उपयोगकर्ताओं को बेहतर अनुभव मिलेगा.
अगर लाइब्रेरी का इस्तेमाल करने के बजाय, डाउनलोड करने की अपनी सेवा बनाई जाती है, तो ध्यान रखें कि आपको एक्सपैंशन फ़ाइलों का नाम नहीं बदलना चाहिए. साथ ही, उन्हें सही स्टोरेज लोकेशन में सेव करना चाहिए.
ऐप्लिकेशन डेवलप करने के बाद, एक्सपैंशन फ़ाइलों को टेस्ट करने के लिए दी गई गाइड का पालन करें.
नियम और सीमाएं
Play Console का इस्तेमाल करके ऐप्लिकेशन अपलोड करते समय, APK एक्सपैंशन फ़ाइलें जोड़ने की सुविधा उपलब्ध होती है. पहली बार ऐप्लिकेशन अपलोड करते समय या एक्सपैंशन फ़ाइलों का इस्तेमाल करने वाले ऐप्लिकेशन को अपडेट करते समय, आपको इन नियमों और सीमाओं के बारे में पता होना चाहिए:
- हर एक्सपैंशन फ़ाइल का साइज़ 2 जीबी से ज़्यादा नहीं होना चाहिए.
- Google Play से अपनी एक्सपैंशन फ़ाइलें डाउनलोड करने के लिए, उपयोगकर्ता ने Google Play से आपका ऐप्लिकेशन डाउनलोड किया हो. अगर ऐप्लिकेशन को किसी दूसरे तरीके से इंस्टॉल किया गया है, तो Google Play आपकी एक्सपैंशन फ़ाइलों के यूआरएल नहीं देगा.
- ऐप्लिकेशन से डाउनलोड करने पर, Google Play हर फ़ाइल के लिए एक यूआरएल देता है. यह यूआरएल, हर डाउनलोड के लिए अलग होता है. साथ ही, यह यूआरएल आपके ऐप्लिकेशन को मिलने के कुछ समय बाद ही खत्म हो जाता है.
- अगर आपको अपने ऐप्लिकेशन को नए APK से अपडेट करना है या एक ही ऐप्लिकेशन के लिए कई APK अपलोड करने हैं, तो आपके पास उन एक्सपैंशन फ़ाइलों को चुनने का विकल्प होता है जिन्हें आपने पिछले APK के लिए अपलोड किया था. एक्सपेंशन फ़ाइल का नाम नहीं बदलता. यह उस वर्शन को बनाए रखता है जो उस APK को मिला था जिससे फ़ाइल को मूल रूप से जोड़ा गया था.
- अगर अलग-अलग डिवाइसों के लिए अलग-अलग एक्सपैंशन फ़ाइलें उपलब्ध कराने के लिए, एक से ज़्यादा APK के साथ एक्सपैंशन फ़ाइलों का इस्तेमाल किया जाता है, तो आपको अब भी हर डिवाइस के लिए अलग-अलग APK अपलोड करने होंगे. ऐसा इसलिए, ताकि हर APK के लिए एक यूनीक
versionCodeवैल्यू दी जा सके और अलग-अलग फ़िल्टर तय किए जा सकें. - सिर्फ़ एक्सपैंशन फ़ाइलों में बदलाव करके, अपने ऐप्लिकेशन को अपडेट नहीं किया जा सकता. ऐप्लिकेशन को अपडेट करने के लिए, आपको नया APK अपलोड करना होगा. अगर आपके बदलाव सिर्फ़ एक्सपैंशन फ़ाइलों में मौजूद ऐसेट से जुड़े हैं, तो
versionCode(और शायदversionName) में बदलाव करके, अपने APK को अपडेट किया जा सकता है. - अपनी
obb/डायरेक्ट्री में कोई और डेटा सेव न करें. अगर आपको कुछ डेटा अनपैक करना है, तो उसेgetExternalFilesDir()में बताई गई जगह पर सेव करें. .obbएक्सपैंशन फ़ाइल को न तो मिटाएं और न ही उसका नाम बदलें. हालांकि, अपडेट करते समय ऐसा किया जा सकता है. ऐसा करने से, Google Play या आपका ऐप्लिकेशन, एक्सपैंशन फ़ाइल को बार-बार डाउनलोड करेगा.- एक्सपैंशन फ़ाइल को मैन्युअल तरीके से अपडेट करते समय, आपको पिछली एक्सपैंशन फ़ाइल मिटानी होगी.
एक्सपैंशन फ़ाइलें डाउनलोड करना
ज़्यादातर मामलों में, Google Play आपके डिवाइस पर APK इंस्टॉल या अपडेट करते समय ही, एक्सपैंशन फ़ाइलें डाउनलोड और सेव कर देता है. इस तरह, जब आपका ऐप्लिकेशन पहली बार लॉन्च होता है, तब एक्सपैंशन फ़ाइलें उपलब्ध होती हैं. हालांकि, कुछ मामलों में आपके ऐप्लिकेशन को एक्सपैंशन फ़ाइलें खुद डाउनलोड करनी होंगी. इसके लिए, उसे Google Play की ऐप्लिकेशन लाइसेंसिंग सेवा से मिले जवाब में दिए गए यूआरएल से फ़ाइलों का अनुरोध करना होगा.
एक्सपैंशन फ़ाइलें डाउनलोड करने के लिए, आपको इस बुनियादी लॉजिक का इस्तेमाल करना होगा:
- जब आपका ऐप्लिकेशन शुरू हो, तब शेयर किए गए स्टोरेज की जगह (
Android/obb/<package-name>/डायरेक्ट्री में) पर एक्सपैंशन फ़ाइलें खोजें.- अगर एक्सपैंशन फ़ाइलें मौजूद हैं, तो आपको कुछ और करने की ज़रूरत नहीं है. आपका ऐप्लिकेशन काम करना जारी रख सकता है.
- अगर एक्सपैंशन फ़ाइलें मौजूद नहीं हैं, तो:
- अपने ऐप्लिकेशन की एक्सपैंशन फ़ाइल के नाम, साइज़, और यूआरएल पाने के लिए, Google Play की ऐप्लिकेशन के लाइसेंस का इस्तेमाल करके अनुरोध करें.
- Google Play से मिले यूआरएल का इस्तेमाल करके, एक्सपैंशन फ़ाइलें डाउनलोड करें और उन्हें सेव करें. आपको फ़ाइलों को शेयर की गई स्टोरेज लोकेशन (
Android/obb/<package-name>/) में सेव करना ज़रूरी है. साथ ही, Google Play के जवाब में दिए गए फ़ाइल के नाम का इस्तेमाल करें.ध्यान दें: Google Play, आपकी एक्सपैंशन फ़ाइलों के लिए जो यूआरएल देता है वह हर डाउनलोड के लिए अलग होता है. साथ ही, हर यूआरएल आपके ऐप्लिकेशन को मिलने के कुछ समय बाद ही खत्म हो जाता है.
अगर आपका ऐप्लिकेशन मुफ़्त है (पैसे चुकाकर डाउनलोड किया जाने वाला ऐप्लिकेशन नहीं है), तो हो सकता है कि आपने ऐप्लिकेशन लाइसेंसिंग सेवा का इस्तेमाल न किया हो. इसे मुख्य रूप से इसलिए डिज़ाइन किया गया है, ताकि आप अपने ऐप्लिकेशन के लिए लाइसेंसिंग से जुड़ी नीतियों को लागू कर सकें. साथ ही, यह पक्का कर सकें कि उपयोगकर्ता के पास आपके ऐप्लिकेशन को इस्तेमाल करने का अधिकार है. इसका मतलब है कि उसने Google Play पर इसके लिए सही तरीके से पेमेंट किया है. एक्सपेंशन फ़ाइल की सुविधा को बेहतर बनाने के लिए, लाइसेंसिंग सेवा को बेहतर बनाया गया है. इससे आपके ऐप्लिकेशन को जवाब मिल पाएगा. इस जवाब में, Google Play पर होस्ट की गई आपके ऐप्लिकेशन की एक्सपैंशन फ़ाइलों का यूआरएल शामिल होगा. इसलिए, भले ही आपका ऐप्लिकेशन लोगों के लिए मुफ़्त हो, लेकिन APK की एक्सपैंशन फ़ाइलों का इस्तेमाल करने के लिए, आपको लाइसेंस की पुष्टि करने वाली लाइब्रेरी (एलवीएल) को शामिल करना होगा. अगर आपका ऐप्लिकेशन बिना किसी शुल्क के उपलब्ध है, तो आपको लाइसेंस की पुष्टि करने की सुविधा लागू करने की ज़रूरत नहीं है. आपको सिर्फ़ लाइब्रेरी की ज़रूरत होगी, ताकि वह ऐसा अनुरोध कर सके जिससे आपकी एक्सपैंशन फ़ाइलों का यूआरएल वापस मिल सके.
ध्यान दें: भले ही, आपका ऐप्लिकेशन मुफ़्त हो या नहीं, Google Play सिर्फ़ तब एक्सपैंशन फ़ाइल के यूआरएल दिखाता है, जब उपयोगकर्ता ने आपका ऐप्लिकेशन Google Play से लिया हो.
एलवीएल के अलावा, आपको कोड के एक ऐसे सेट की ज़रूरत होती है जो एचटीटीपी कनेक्शन पर एक्सपैंशन फ़ाइलों को डाउनलोड करता है और उन्हें डिवाइस के शेयर किए गए स्टोरेज में सही जगह पर सेव करता है. इस प्रोसेस को अपने ऐप्लिकेशन में लागू करते समय, आपको इन बातों का ध्यान रखना चाहिए:
- ऐसा हो सकता है कि डिवाइस में, एक्सपैंशन फ़ाइलों के लिए ज़रूरी जगह न हो. इसलिए, आपको डाउनलोड शुरू करने से पहले यह जांच करनी चाहिए. अगर ज़रूरी जगह नहीं है, तो उपयोगकर्ता को इसकी सूचना दें.
- फ़ाइलें बैकग्राउंड में चलने वाली सेवा में डाउनलोड होनी चाहिए, ताकि उपयोगकर्ता के इंटरैक्शन में रुकावट न आए. साथ ही, डाउनलोड पूरा होने तक उपयोगकर्ता आपके ऐप्लिकेशन को छोड़ सके.
- अनुरोध और डाउनलोड के दौरान कई तरह की गड़बड़ियां हो सकती हैं. आपको इन्हें ठीक तरीके से ठीक करना होगा.
- डाउनलोड के दौरान नेटवर्क कनेक्टिविटी बदल सकती है. इसलिए, आपको ऐसे बदलावों को मैनेज करना चाहिए. अगर डाउनलोड में रुकावट आती है, तो जब भी हो सके, डाउनलोड फिर से शुरू करें.
- बैकग्राउंड में डाउनलोड होने के दौरान, आपको एक सूचना दिखानी चाहिए. इसमें डाउनलोड की प्रोग्रेस दिखनी चाहिए. साथ ही, डाउनलोड पूरा होने पर उपयोगकर्ता को सूचना मिलनी चाहिए. इसके अलावा, सूचना को चुनने पर उपयोगकर्ता को वापस आपके ऐप्लिकेशन पर ले जाना चाहिए.
इस काम को आपके लिए आसान बनाने के लिए, हमने डाउनलोडर लाइब्रेरी बनाई है. यह लाइसेंसिंग सेवा के ज़रिए, एक्सपैंशन फ़ाइल के यूआरएल का अनुरोध करती है, एक्सपैंशन फ़ाइलें डाउनलोड करती है, और ऊपर दी गई सभी कार्रवाइयां करती है. साथ ही, यह आपकी गतिविधि को रोकने और डाउनलोड फिर से शुरू करने की अनुमति भी देती है. Downloader Library और कुछ कोड हुक को अपने ऐप्लिकेशन में जोड़ने पर, एक्सपैंशन फ़ाइलों को डाउनलोड करने का लगभग सारा काम पहले से ही कोड किया जा चुका होता है. इसलिए, हम आपको Downloader Library का इस्तेमाल करने का सुझाव देते हैं. इससे आपको कम मेहनत करनी पड़ेगी और उपयोगकर्ताओं को बेहतर अनुभव मिलेगा. यहां दिए गए सेक्शन में, लाइब्रेरी को अपने ऐप्लिकेशन में इंटिग्रेट करने का तरीका बताया गया है.
अगर आपको Google Play के यूआरएल का इस्तेमाल करके, एक्सपैंशन फ़ाइलें डाउनलोड करने के लिए अपना खुद का समाधान तैयार करना है, तो आपको लाइसेंस का अनुरोध करने के लिए, ऐप्लिकेशन के लाइसेंस से जुड़े दस्तावेज़ में दिए गए निर्देशों का पालन करना होगा. इसके बाद, जवाब में मौजूद अतिरिक्त जानकारी से, एक्सपैंशन फ़ाइल के नाम, साइज़, और यूआरएल वापस पाएं. आपको लाइसेंसिंग की नीति के तौर पर, APKExpansionPolicy क्लास का इस्तेमाल करना चाहिए. यह क्लास, लाइसेंस की पुष्टि करने वाली लाइब्रेरी में शामिल होती है. यह क्लास, लाइसेंसिंग सेवा से एक्सपैंशन फ़ाइल के नाम, साइज़, और यूआरएल कैप्चर करती है..
डाउनलोडर लाइब्रेरी के बारे में जानकारी
हमारा सुझाव है कि आप अपने ऐप्लिकेशन के साथ APK की एक्सपैंशन फ़ाइलों का इस्तेमाल करें. साथ ही, कम मेहनत में उपयोगकर्ताओं को बेहतर अनुभव देने के लिए, Downloader Library का इस्तेमाल करें. यह Google Play APK Expansion Library पैकेज में शामिल होती है. यह लाइब्रेरी, बैकग्राउंड में चलने वाली सेवा में आपकी एक्सपैंशन फ़ाइलें डाउनलोड करती है. साथ ही, डाउनलोड के स्टेटस के बारे में उपयोगकर्ता को सूचना दिखाती है, नेटवर्क कनेक्टिविटी के बंद होने की समस्या को ठीक करती है, और जब भी संभव हो, डाउनलोड को फिर से शुरू करती है. इसके अलावा, यह लाइब्रेरी और भी कई काम करती है.
Downloader Library का इस्तेमाल करके, एक्सपैंशन फ़ाइलें डाउनलोड करने की सुविधा लागू करने के लिए, आपको ये काम करने होंगे:
- खास
Serviceसबक्लास औरBroadcastReceiverसबक्लास को बढ़ाएं. इन दोनों के लिए, आपको सिर्फ़ कुछ लाइनों का कोड लिखना होगा. - अपनी मुख्य गतिविधि में कुछ लॉजिक जोड़ें. इससे यह पता चलेगा कि एक्सपैंशन फ़ाइलें पहले ही डाउनलोड हो चुकी हैं या नहीं. अगर ऐसा नहीं हुआ है, तो डाउनलोड करने की प्रोसेस शुरू करें और प्रोग्रेस यूज़र इंटरफ़ेस (यूआई) दिखाएं.
- अपनी मुख्य गतिविधि में कुछ तरीकों के साथ एक कॉलबैक इंटरफ़ेस लागू करें. यह इंटरफ़ेस, डाउनलोड की प्रोग्रेस के बारे में अपडेट पाता है.
यहां दिए गए सेक्शन में, Downloader Library का इस्तेमाल करके ऐप्लिकेशन सेट अप करने का तरीका बताया गया है.
डाउनलोडर लाइब्रेरी का इस्तेमाल करने की तैयारी करना
Downloader Library का इस्तेमाल करने के लिए, आपको SDK Manager से दो पैकेज डाउनलोड करने होंगे. साथ ही, अपने ऐप्लिकेशन में सही लाइब्रेरी जोड़नी होंगी.
सबसे पहले, Android SDK Manager खोलें (Tools > SDK Manager). इसके बाद, Appearance & Behavior > System Settings > Android SDK में जाकर, एसडीके टूल टैब चुनें. यहां से, ये आइटम चुने और डाउनलोड किए जा सकते हैं:
- Google Play Licensing Library पैकेज
- Google Play APK Expansion Library पैकेज
लाइसेंस की पुष्टि करने वाली लाइब्रेरी और Downloader Library के लिए, नया लाइब्रेरी मॉड्यूल बनाएं. हर लाइब्रेरी के लिए:
- फ़ाइल > नया > नया मॉड्यूल को चुनें.
- नया मॉड्यूल बनाएं विंडो में, Android लाइब्रेरी चुनें. इसके बाद, आगे बढ़ें चुनें.
- ऐप्लिकेशन/लाइब्रेरी का नाम डालें. जैसे, "Google Play License Library" और "Google Play Downloader Library". इसके बाद, एसडीके का कम से कम लेवल चुनें. फिर, हो गया को चुनें.
- फ़ाइल > प्रोजेक्ट का स्ट्रक्चर चुनें.
- प्रॉपर्टी टैब चुनें. इसके बाद, लाइब्रेरी
रिपॉज़िटरी में,
<sdk>/extras/google/डायरेक्ट्री से लाइब्रेरी डालें.play_licensing/लाइसेंस की पुष्टि करने वाली लाइब्रेरी के लिए याplay_apk_expansion/downloader_library/डाउनलोडर लाइब्रेरी के लिए. - नया मॉड्यूल बनाने के लिए, ठीक है को चुनें.
ध्यान दें: Downloader Library, License Verification Library पर निर्भर करती है. लाइसेंस की पुष्टि करने वाली लाइब्रेरी को, डाउनलोडर लाइब्रेरी की प्रोजेक्ट प्रॉपर्टी में जोड़ना न भूलें.
इसके अलावा, कमांड लाइन से अपने प्रोजेक्ट को अपडेट करके, लाइब्रेरी शामिल करें:
- डायरेक्ट्री को
<sdk>/tools/डायरेक्ट्री में बदलें. - अपने प्रोजेक्ट में LVL और Downloader Library, दोनों को जोड़ने के लिए,
--libraryविकल्प के साथandroid update projectको एक्ज़ीक्यूट करें. उदाहरण के लिए:android update project --path ~/Android/MyApp \ --library ~/android_sdk/extras/google/market_licensing \ --library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
लाइसेंस की पुष्टि करने वाली लाइब्रेरी और डाउनलोडर लाइब्रेरी, दोनों को अपने ऐप्लिकेशन में जोड़ने पर, Google Play से एक्सपैंशन फ़ाइलें डाउनलोड करने की सुविधा को तुरंत इंटिग्रेट किया जा सकेगा. एक्सपेंशन फ़ाइलों के लिए चुना गया फ़ॉर्मैट और शेयर किए गए स्टोरेज से उन्हें पढ़ने का तरीका, एक अलग प्रोसेस है. आपको इसे अपने ऐप्लिकेशन की ज़रूरतों के हिसाब से तय करना चाहिए.
अहम जानकारी: APK Expansion पैकेज में एक सैंपल ऐप्लिकेशन शामिल होता है. इसमें बताया गया है कि किसी ऐप्लिकेशन में Downloader Library का इस्तेमाल कैसे किया जाता है. यह सैंपल, APK Expansion पैकेज में उपलब्ध APK Expansion Zip Library नाम की तीसरे पक्ष की लाइब्रेरी का इस्तेमाल करता है. अगर आपको अपनी एक्सपैंशन फ़ाइलों के लिए ZIP फ़ाइलों का इस्तेमाल करना है, तो हमारा सुझाव है कि आप अपने ऐप्लिकेशन में APK Expansion Zip Library भी जोड़ें. ज़्यादा जानकारी के लिए, APK Expansion Zip Library का इस्तेमाल करना के बारे में नीचे दिया गया सेक्शन देखें.
उपयोगकर्ता की अनुमतियां तय करना
एक्सपैंशन फ़ाइलें डाउनलोड करने के लिए, Downloader Library को कई अनुमतियों की ज़रूरत होती है. आपको इन अनुमतियों के बारे में, अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में बताना होगा. ये हैं:
<manifest ...> <!-- Required to access Google Play Licensing --> <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> <!-- Required to download files from Google Play --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required to poll the state of the network connection and respond to changes --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Required to check whether Wi-Fi is enabled --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!-- Required to read and write the expansion files on shared storage --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
ध्यान दें: डिफ़ॉल्ट रूप से, Downloader Library के लिए एपीआई लेवल 4 की ज़रूरत होती है. हालांकि, APK Expansion Zip Library के लिए एपीआई लेवल 5 की ज़रूरत होती है.
डाउनलोडर सेवा लागू करना
बैकग्राउंड में डाउनलोड करने के लिए, Downloader Library अपना Service सब-क्लास उपलब्ध कराती है. इसे DownloaderService कहा जाता है. आपको इसे एक्सटेंड करना चाहिए. एक्सपैंशन फ़ाइलें डाउनलोड करने के अलावा, DownloaderService ये काम भी करता है:
- यह कुकी,
BroadcastReceiverको रजिस्टर करती है. यह कुकी, डिवाइस के नेटवर्क कनेक्शन में होने वाले बदलावों (CONNECTIVITY_ACTIONब्रॉडकास्ट) को सुनती है. ऐसा इसलिए किया जाता है, ताकि ज़रूरत पड़ने पर डाउनलोड को रोका जा सके. जैसे, कनेक्शन न होने की वजह से और कनेक्शन मिलने पर डाउनलोड को फिर से शुरू किया जा सके. - यह कुकी,
RTC_WAKEUPअलार्म को शेड्यूल करती है, ताकि सेवा बंद होने पर डाउनलोड को फिर से शुरू किया जा सके. - यह एक कस्टम
Notificationबनाता है, जो डाउनलोड की प्रोसेस और किसी भी गड़बड़ी या स्थिति में हुए बदलावों को दिखाता है. - इससे आपके ऐप्लिकेशन को डाउनलोड को मैन्युअल तरीके से रोकने और फिर से शुरू करने की अनुमति मिलती है.
- यह फ़ंक्शन, यह पुष्टि करता है कि शेयर की गई मेमोरी माउंट की गई है और उपलब्ध है. साथ ही, यह भी पुष्टि करता है कि फ़ाइलें पहले से मौजूद नहीं हैं और उनमें ज़रूरत के मुताबिक जगह है. यह सभी पुष्टि, एक्सपैंशन फ़ाइलें डाउनलोड करने से पहले की जाती है. अगर इनमें से कोई भी शर्त पूरी नहीं होती है, तो उपयोगकर्ता को इसकी सूचना दी जाती है.
आपको बस अपने ऐप्लिकेशन में एक ऐसी क्लास बनानी होगी जो DownloaderService क्लास को एक्सटेंड करती हो. साथ ही, ऐप्लिकेशन के बारे में जानकारी देने के लिए, तीन तरीकों को बदलें:
getPublicKey()- इससे एक स्ट्रिंग मिलती है. यह आपके पब्लिशर खाते के लिए, Base64-एन्कोड की गई आरएसए सार्वजनिक कुंजी होती है. यह Play Console के प्रोफ़ाइल पेज पर उपलब्ध होती है. इसके बारे में जानने के लिए, लाइसेंसिंग के लिए सेटअप करना लेख पढ़ें.
getSALT()- इसे रैंडम बाइट का एक ऐसा कलेक्शन देना होगा जिसका इस्तेमाल लाइसेंसिंग
Policy,Obfuscatorबनाने के लिए करता है. सॉल्ट यह पक्का करता है कि आपकी धुंधली की गईSharedPreferencesफ़ाइल, जिसमें लाइसेंसिंग डेटा सेव किया गया है, वह यूनीक होगी और उसे खोजा नहीं जा सकेगा. getAlarmReceiverClassName()- यह आपके ऐप्लिकेशन में मौजूद
BroadcastReceiverका क्लास नेम दिखाता है. इस क्लास को अलार्म मिलता है, जिससे पता चलता है कि डाउनलोड को फिर से शुरू करना है. ऐसा तब हो सकता है, जब डाउनलोडर सेवा अचानक बंद हो जाए.
उदाहरण के लिए, यहां DownloaderService को लागू करने का पूरा तरीका बताया गया है:
Kotlin
// You must use the public key belonging to your publisher account const val BASE64_PUBLIC_KEY = "YourLVLKey" // You should also modify this salt val SALT = byteArrayOf( 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 ) class SampleDownloaderService : DownloaderService() { override fun getPublicKey(): String = BASE64_PUBLIC_KEY override fun getSALT(): ByteArray = SALT override fun getAlarmReceiverClassName(): String = SampleAlarmReceiver::class.java.name }
Java
public class SampleDownloaderService extends DownloaderService { // You must use the public key belonging to your publisher account public static final String BASE64_PUBLIC_KEY = "YourLVLKey"; // You should also modify this salt public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 }; @Override public String getPublicKey() { return BASE64_PUBLIC_KEY; } @Override public byte[] getSALT() { return SALT; } @Override public String getAlarmReceiverClassName() { return SampleAlarmReceiver.class.getName(); } }
सूचना: आपको BASE64_PUBLIC_KEY वैल्यू को अपडेट करना होगा, ताकि वह आपके पब्लिशर खाते से जुड़ी सार्वजनिक कुंजी हो. आपको यह कुंजी, Developer Console में अपनी प्रोफ़ाइल की जानकारी में मिलेगी. डाउनलोड की जांच करते समय भी यह ज़रूरी है.
अपनी मेनिफ़ेस्ट फ़ाइल में सेवा के बारे में जानकारी देना न भूलें:
<app ...> <service android:name=".SampleDownloaderService" /> ... </app>
अलार्म रिसीवर लागू करना
फ़ाइल डाउनलोड करने की प्रोसेस पर नज़र रखने और ज़रूरत पड़ने पर डाउनलोड को फिर से शुरू करने के लिए, DownloaderService एक RTC_WAKEUP अलार्म शेड्यूल करता है. यह अलार्म, आपके ऐप्लिकेशन में मौजूद BroadcastReceiver को Intent डिलीवर करता है. आपको BroadcastReceiver को इस तरह से तय करना होगा कि वह Downloader Library से किसी एपीआई को कॉल करे. यह एपीआई, डाउनलोड की स्थिति की जांच करता है और ज़रूरत पड़ने पर उसे फिर से शुरू करता है.
DownloaderClientMarshaller.startDownloadServiceIfRequired() को कॉल करने के लिए, आपको सिर्फ़ onReceive() वाले तरीके को ओवरराइड करना होगा.
उदाहरण के लिए:
Kotlin
class SampleAlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired( context, intent, SampleDownloaderService::class.java ) } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } } }
Java
public class SampleAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, SampleDownloaderService.class); } catch (NameNotFoundException e) { e.printStackTrace(); } } }
ध्यान दें कि यह वह क्लास है जिसके लिए आपको अपनी सेवा के getAlarmReceiverClassName() तरीके में नाम दिखाना होगा (पिछला सेक्शन देखें).
अपनी मेनिफ़ेस्ट फ़ाइल में रिसीवर का एलान करना न भूलें:
<app ...> <receiver android:name=".SampleAlarmReceiver" /> ... </app>
डाउनलोड शुरू किया जा रहा है
आपके ऐप्लिकेशन में मौजूद मुख्य गतिविधि (वह गतिविधि जो लॉन्चर आइकॉन से शुरू होती है) यह पुष्टि करने के लिए ज़िम्मेदार होती है कि डिवाइस पर एक्सपैंशन फ़ाइलें पहले से मौजूद हैं या नहीं. अगर वे मौजूद नहीं हैं, तो उन्हें डाउनलोड करने की प्रोसेस शुरू की जाती है.
Downloader Library का इस्तेमाल करके डाउनलोड शुरू करने के लिए, यह तरीका अपनाना ज़रूरी है:
- देखें कि फ़ाइलें डाउनलोड हुई हैं या नहीं.
Downloader Library में, इस प्रोसेस में मदद करने के लिए
Helperक्लास में कुछ एपीआई शामिल हैं:getExpansionAPKFileName(Context, c, boolean mainFile, int versionCode)doesFileExist(Context c, String fileName, long fileSize)
उदाहरण के लिए, Apk Expansion पैकेज में दिए गए सैंपल के तौर पर मिले ऐप्लिकेशन में, यह देखने के लिए कि डिवाइस पर एक्सपैंशन फ़ाइलें पहले से मौजूद हैं या नहीं, गतिविधि के
onCreate()मैथड में यहां दिया गया मैथड कॉल किया जाता है:Kotlin
fun expansionFilesDelivered(): Boolean { xAPKS.forEach { xf -> Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion).also { fileName -> if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false } } return true }
Java
boolean expansionFilesDelivered() { for (XAPKFile xf : xAPKS) { String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion); if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false; } return true; }
इस मामले में, हर
XAPKFileऑब्जेक्ट में, जानी-पहचानी एक्सपैंशन फ़ाइल का वर्शन नंबर और फ़ाइल साइज़ होता है. साथ ही, यह भी होता है कि क्या यह मुख्य एक्सपैंशन फ़ाइल है. (ज़्यादा जानकारी के लिए, सैंपल ऐप्लिकेशन कीSampleDownloaderActivityक्लास देखें.)अगर यह तरीका 'गलत' दिखाता है, तो ऐप्लिकेशन को डाउनलोड करना शुरू करना होगा.
- स्टैटिक तरीके
DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent notificationClient, Class<?> serviceClass)को कॉल करके, डाउनलोड शुरू करें.यह तरीका इन पैरामीटर का इस्तेमाल करता है:
context: आपके ऐप्लिकेशन काContext.notificationClient: मुख्य गतिविधि शुरू करने के लिएPendingIntent. इसका इस्तेमालNotificationमें किया जाता है.DownloaderServiceइसे डाउनलोड की प्रोग्रेस दिखाने के लिए बनाता है. जब उपयोगकर्ता सूचना चुनता है, तो सिस्टम यहां दिए गएPendingIntentको शुरू करता है. साथ ही, उसे वह ऐक्टिविटी खोलनी चाहिए जिसमें डाउनलोड की प्रोग्रेस दिखती है. आम तौर पर, यह वही ऐक्टिविटी होती है जिसने डाउनलोड शुरू किया था.serviceClass:DownloaderServiceको लागू करने के लिएClassऑब्जेक्ट. सेवा शुरू करने और ज़रूरी होने पर डाउनलोड शुरू करने के लिए यह ऑब्जेक्ट ज़रूरी है.
यह तरीका एक पूर्णांक दिखाता है. इससे पता चलता है कि डाउनलोड करना ज़रूरी है या नहीं. ये वैल्यू इस्तेमाल की जा सकती हैं:
NO_DOWNLOAD_REQUIRED: यह तब दिखता है, जब फ़ाइलें पहले से मौजूद हों या डाउनलोड पहले से जारी हो.LVL_CHECK_REQUIRED: यह तब दिखता है, जब एक्सपैंशन फ़ाइल के यूआरएल पाने के लिए, लाइसेंस की पुष्टि करना ज़रूरी हो.DOWNLOAD_REQUIRED: यह तब दिखता है, जब एक्सपैंशन फ़ाइल के यूआरएल पहले से पता हों, लेकिन उन्हें डाउनलोड न किया गया हो.
LVL_CHECK_REQUIREDऔरDOWNLOAD_REQUIREDका व्यवहार एक जैसा होता है. आम तौर पर, आपको इनके बारे में चिंता करने की ज़रूरत नहीं होती.startDownloadServiceIfRequired()को कॉल करने वाली मुख्य गतिविधि में, यह आसानी से देखा जा सकता है कि जवाबNO_DOWNLOAD_REQUIREDहै या नहीं. अगर जवाबNO_DOWNLOAD_REQUIREDके अलावा कुछ और है, तो Downloader Library डाउनलोड शुरू कर देती है. आपको गतिविधि के यूज़र इंटरफ़ेस (यूआई) को अपडेट करना चाहिए, ताकि डाउनलोड की प्रोग्रेस दिख सके. इसके बारे में अगले चरण में बताया गया है. अगर जवाब हैNO_DOWNLOAD_REQUIRED, तो इसका मतलब है कि फ़ाइलें उपलब्ध हैं और आपका ऐप्लिकेशन शुरू हो सकता है.उदाहरण के लिए:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { val pendingIntent = // Build an Intent to start this activity from the Notification Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP }.let { notifierIntent -> PendingIntent.getActivity( this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT ) } // Start the download service (if required) val startResult: Int = DownloaderClientMarshaller.startDownloadServiceIfRequired( this, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return } // If the download wasn't necessary, fall through to start the app } startApp() // Expansion files are available, start the app }
Java
@Override public void onCreate(Bundle savedInstanceState) { // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { // Build an Intent to start this activity from the Notification Intent notifierIntent = new Intent(this, MainActivity.getClass()); notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); ... PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return; } // If the download wasn't necessary, fall through to start the app } startApp(); // Expansion files are available, start the app }
- जब
startDownloadServiceIfRequired()वाला तरीका,NO_DOWNLOAD_REQUIREDके अलावा कोई और वैल्यू दिखाता है, तबDownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class<?> downloaderService)को कॉल करकेIStubका इंस्टेंस बनाएं.IStub, डाउनलोड करने वाले व्यक्ति की गतिविधि को डाउनलोडर सेवा से जोड़ता है, ताकि उसे डाउनलोड की प्रोग्रेस के बारे में कॉलबैक मिल सकें.CreateStub()को कॉल करकेIStubको इंस्टैंशिएट करने के लिए, आपको इसेIDownloaderClientइंटरफ़ेस औरDownloaderServiceके लागू करने का तरीका पास करना होगा. डाउनलोड की प्रोग्रेस पाने के बारे में अगले सेक्शन में,IDownloaderClientइंटरफ़ेस के बारे में बताया गया है. आम तौर पर, आपको इसे अपनीActivityक्लास में लागू करना चाहिए, ताकि डाउनलोड की स्थिति बदलने पर ऐक्टिविटी के यूज़र इंटरफ़ेस (यूआई) को अपडेट किया जा सके.हमारा सुझाव है कि आप
CreateStub()को कॉल करके, अपनी गतिविधि केonCreate()तरीके के दौरानIStubको इंस्टैंशिएट करें. ऐसा तब करें, जबstartDownloadServiceIfRequired()डाउनलोड शुरू कर दे.उदाहरण के लिए,
onCreate()के लिए दिए गए पिछले कोड के सैंपल में,onCreate()के नतीजे का जवाब इस तरह दिया जा सकता है:startDownloadServiceIfRequired()Kotlin
// Start the download service (if required) val startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( this@MainActivity, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService::class.java) // Inflate layout that shows download progress setContentView(R.layout.downloader_ui) return }
Java
// Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService.class); // Inflate layout that shows download progress setContentView(R.layout.downloader_ui); return; }
onCreate()तरीके के पूरा होने के बाद, आपकी गतिविधि कोonResume()पर कॉल मिलता है. इसके बाद, आपकोIStubपरconnect()को कॉल करना चाहिए. साथ ही, अपने ऐप्लिकेशन काContextपास करना चाहिए. इसके उलट, आपको अपनी गतिविधि केonStop()कॉलबैक मेंdisconnect()को कॉल करना चाहिए.Kotlin
override fun onResume() { downloaderClientStub?.connect(this) super.onResume() } override fun onStop() { downloaderClientStub?.disconnect(this) super.onStop() }
Java
@Override protected void onResume() { if (null != downloaderClientStub) { downloaderClientStub.connect(this); } super.onResume(); } @Override protected void onStop() { if (null != downloaderClientStub) { downloaderClientStub.disconnect(this); } super.onStop(); }
IStubपरconnect()को कॉल करने से, आपकी गतिविधिDownloaderServiceसे जुड़ जाती है. इससे आपकी गतिविधि कोIDownloaderClientइंटरफ़ेस के ज़रिए, डाउनलोड की स्थिति में हुए बदलावों के बारे में कॉलबैक मिलते हैं.
डाउनलोड की प्रोग्रेस की जानकारी पाना
डाउनलोड की प्रोग्रेस से जुड़े अपडेट पाने और DownloaderService के साथ इंटरैक्ट करने के लिए, आपको Downloader Library का IDownloaderClient इंटरफ़ेस लागू करना होगा.
आम तौर पर, डाउनलोड शुरू करने के लिए इस्तेमाल की जाने वाली गतिविधि को इस इंटरफ़ेस को लागू करना चाहिए, ताकि डाउनलोड की प्रोग्रेस दिखाई जा सके और सेवा को अनुरोध भेजे जा सकें.
IDownloaderClient के लिए ज़रूरी इंटरफ़ेस के तरीके ये हैं:
onServiceConnected(Messenger m)- अपनी गतिविधि में
IStubको इंस्टैंशिएट करने के बाद, आपको इस तरीके से कॉल मिलेगा. यहMessengerऑब्जेक्ट पास करता है, जोDownloaderServiceके आपके इंस्टेंस से कनेक्ट होता है. सेवा को अनुरोध भेजने के लिए, जैसे कि डाउनलोड रोकने और फिर से शुरू करने के लिए, आपकोDownloaderServiceMarshaller.CreateProxy()को कॉल करना होगा, ताकि सेवा से कनेक्ट किया गयाIDownloaderServiceइंटरफ़ेस मिल सके.लागू करने का सुझाया गया तरीका ऐसा दिखता है:
Kotlin
private var remoteService: IDownloaderService? = null ... override fun onServiceConnected(m: Messenger) { remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { downloaderClientStub?.messenger?.also { messenger -> onClientUpdated(messenger) } } }
Java
private IDownloaderService remoteService; ... @Override public void onServiceConnected(Messenger m) { remoteService = DownloaderServiceMarshaller.CreateProxy(m); remoteService.onClientUpdated(downloaderClientStub.getMessenger()); }
IDownloaderServiceऑब्जेक्ट के शुरू होने के बाद, डाउनलोडर सेवा को निर्देश भेजे जा सकते हैं. जैसे, डाउनलोड को रोकना (requestPauseDownload()) और फिर से शुरू करना (requestContinueDownload()). onDownloadStateChanged(int newState)- डाउनलोड की स्थिति में बदलाव होने पर, डाउनलोड सेवा इसे कॉल करती है. जैसे, डाउनलोड शुरू होने या पूरा होने पर.
newStateवैल्यू,IDownloaderClientक्लास केSTATE_*कॉन्स्टेंट में दी गई कई संभावित वैल्यू में से एक होगी.अपने उपयोगकर्ताओं को काम का मैसेज देने के लिए, हर स्थिति के लिए उससे जुड़ी स्ट्रिंग का अनुरोध किया जा सकता है. इसके लिए,
Helpers.getDownloaderStringResourceIDFromState()को कॉल करें. इससे Downloader Library के साथ बंडल की गई किसी एक स्ट्रिंग के लिए संसाधन का आईडी मिलता है. उदाहरण के लिए, "रोमिंग में होने की वजह से डाउनलोड रोक दिया गया है" स्ट्रिंग,STATE_PAUSED_ROAMINGसे मेल खाती है. onDownloadProgress(DownloadProgressInfo progress)- डाउनलोड सेवा, इस फ़ंक्शन को कॉल करके
DownloadProgressInfoऑब्जेक्ट डिलीवर करती है. इस ऑब्जेक्ट में, डाउनलोड की प्रोग्रेस के बारे में अलग-अलग तरह की जानकारी होती है. जैसे, डाउनलोड पूरा होने में लगने वाला अनुमानित समय, डाउनलोड की मौजूदा स्पीड, डाउनलोड की कुल प्रोग्रेस, और डाउनलोड की कुल साइज़. इससे, डाउनलोड की प्रोग्रेस दिखाने वाले यूज़र इंटरफ़ेस (यूआई) को अपडेट किया जा सकता है.
अहम जानकारी: डाउनलोड की प्रोग्रेस के यूज़र इंटरफ़ेस (यूआई) को अपडेट करने वाले इन कॉलबैक के उदाहरणों के लिए, Apk Expansion पैकेज के साथ दिए गए सैंपल के तौर पर मिले ऐप्लिकेशन में SampleDownloaderActivity देखें.
IDownloaderService इंटरफ़ेस के कुछ सार्वजनिक तरीके यहां दिए गए हैं, जो आपके काम आ सकते हैं:
requestPauseDownload()- इससे डाउनलोड रुक जाता है.
requestContinueDownload()- इससे डाउनलोड की प्रोसेस को फिर से शुरू किया जा सकता है.
setDownloadFlags(int flags)- यह कुकी, उपयोगकर्ता की उन नेटवर्क टाइप के लिए प्राथमिकताएं सेट करती है जिन पर फ़ाइलें डाउनलोड की जा सकती हैं. फ़िलहाल, एक फ़्लैग,
FLAGS_DOWNLOAD_OVER_CELLULAR, इस्तेमाल किया जा सकता है. हालांकि, अन्य फ़्लैग भी जोड़े जा सकते हैं. डिफ़ॉल्ट रूप से, यह फ़्लैग चालू नहीं होता है. इसलिए, उपयोगकर्ता को एक्सपैंशन फ़ाइलें डाउनलोड करने के लिए, वाई-फ़ाई से कनेक्ट होना ज़रूरी है. आपके पास उपयोगकर्ता को यह विकल्प देने की सुविधा होती है कि वह मोबाइल नेटवर्क पर डाउनलोड करने की सुविधा चालू कर सके. ऐसे में, इन नंबरों पर कॉल करें:Kotlin
remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { ... setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR) }
Java
remoteService .setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
APKExpansionPolicy का इस्तेमाल करना
अगर आपको Google Play Downloader Library का इस्तेमाल करने के बजाय, डाउनलोड करने की अपनी सेवा बनानी है, तो आपको लाइसेंस की पुष्टि करने वाली लाइब्रेरी में दिए गए APKExpansionPolicy का इस्तेमाल करना चाहिए. APKExpansionPolicy क्लास, Google Play License Verification Library में उपलब्ध ServerManagedPolicy क्लास से काफ़ी हद तक मिलती-जुलती है. हालांकि, इसमें APK विस्तार फ़ाइल के जवाब से जुड़ी अतिरिक्त जानकारी को हैंडल करने की सुविधा शामिल है.
ध्यान दें: अगर आपने पिछले सेक्शन में बताई गई Downloader Library का इस्तेमाल किया है, तो लाइब्रेरी, APKExpansionPolicy के साथ सभी इंटरैक्शन करती है. इसलिए, आपको इस क्लास का सीधे तौर पर इस्तेमाल करने की ज़रूरत नहीं है.
इस क्लास में ऐसे तरीके शामिल हैं जिनसे आपको उपलब्ध एक्सटेंशन फ़ाइलों के बारे में ज़रूरी जानकारी मिल सकती है:
getExpansionURLCount()getExpansionURL(int index)getExpansionFileName(int index)getExpansionFileSize(int index)
अगर Downloader Library का इस्तेमाल नहीं किया जा रहा है, तो APKExpansionPolicy का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, ऐप्लिकेशन में लाइसेंसिंग की सुविधा जोड़ना से जुड़ा दस्तावेज़ देखें. इसमें बताया गया है कि इस तरह की लाइसेंस नीति को कैसे लागू किया जाता है.
एक्सपैंशन फ़ाइल को पढ़ना
डिवाइस पर APK एक्सपैंशन फ़ाइलें सेव हो जाने के बाद, फ़ाइलों को पढ़ने का तरीका इस बात पर निर्भर करता है कि आपने किस तरह की फ़ाइल का इस्तेमाल किया है. खास जानकारी में बताए गए तरीके के मुताबिक, आपकी एक्सपैंशन फ़ाइलें किसी भी तरह की फ़ाइल हो सकती हैं. हालांकि, इनके नाम एक खास फ़ाइल नाम के फ़ॉर्मैट का इस्तेमाल करके बदले जाते हैं और इन्हें <shared-storage>/Android/obb/<package-name>/ में सेव किया जाता है.
फ़ाइलों को पढ़ने के तरीके से कोई फ़र्क़ नहीं पड़ता. आपको हमेशा यह देखना चाहिए कि बाहरी स्टोरेज से फ़ाइलें पढ़ी जा सकती हैं या नहीं. ऐसा हो सकता है कि उपयोगकर्ता ने यूएसबी के ज़रिए कंप्यूटर से स्टोरेज को माउंट किया हो या एसडी कार्ड को हटा दिया हो.
ध्यान दें: जब आपका ऐप्लिकेशन शुरू होता है, तब आपको हमेशा यह देखना चाहिए कि बाहरी स्टोरेज उपलब्ध है या नहीं. साथ ही, यह भी देखना चाहिए कि getExternalStorageState() को कॉल करके, उसे पढ़ा जा सकता है या नहीं. यह बाहरी स्टोरेज की स्थिति को दिखाने वाली कई संभावित स्ट्रिंग में से एक स्ट्रिंग दिखाता है. आपके ऐप्लिकेशन के लिए, रिटर्न वैल्यू MEDIA_MOUNTED होनी चाहिए, ताकि उसे पढ़ा जा सके.
फ़ाइलों के नाम पाना
खास जानकारी में बताए गए तरीके के मुताबिक, आपकी APK एक्सपैंशन फ़ाइलें, फ़ाइल के नाम के खास फ़ॉर्मैट का इस्तेमाल करके सेव की जाती हैं:
[main|patch].<expansion-version>.<package-name>.obb
अपनी एक्सपैंशन फ़ाइलों की जगह और नाम पाने के लिए, आपको getExternalStorageDirectory() और getPackageName() तरीकों का इस्तेमाल करके, अपनी फ़ाइलों का पाथ बनाना चाहिए.
यहां एक ऐसा तरीका बताया गया है जिसका इस्तेमाल करके, अपने ऐप्लिकेशन में एक ऐसी अरे पाई जा सकती है जिसमें आपकी दोनों एक्सपैंशन फ़ाइलों का पूरा पाथ मौजूद हो:
Kotlin
fun getAPKExpansionFiles(ctx: Context, mainVersion: Int, patchVersion: Int): Array<String> { val packageName = ctx.packageName val ret = mutableListOf<String>() if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { // Build the full path to the app's expansion files val root = Environment.getExternalStorageDirectory() val expPath = File(root.toString() + EXP_PATH + packageName) // Check that expansion file path exists if (expPath.exists()) { if (mainVersion > 0) { val strMainPath = "$expPath${File.separator}main.$mainVersion.$packageName.obb" val main = File(strMainPath) if (main.isFile) { ret += strMainPath } } if (patchVersion > 0) { val strPatchPath = "$expPath${File.separator}patch.$mainVersion.$packageName.obb" val main = File(strPatchPath) if (main.isFile) { ret += strPatchPath } } } } return ret.toTypedArray() }
Java
// The shared path to all app expansion files private final static String EXP_PATH = "/Android/obb/"; static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) { String packageName = ctx.getPackageName(); Vector<String> ret = new Vector<String>(); if (Environment.getExternalStorageState() .equals(Environment.MEDIA_MOUNTED)) { // Build the full path to the app's expansion files File root = Environment.getExternalStorageDirectory(); File expPath = new File(root.toString() + EXP_PATH + packageName); // Check that expansion file path exists if (expPath.exists()) { if ( mainVersion > 0 ) { String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb"; File main = new File(strMainPath); if ( main.isFile() ) { ret.add(strMainPath); } } if ( patchVersion > 0 ) { String strPatchPath = expPath + File.separator + "patch." + mainVersion + "." + packageName + ".obb"; File main = new File(strPatchPath); if ( main.isFile() ) { ret.add(strPatchPath); } } } } String[] retArray = new String[ret.size()]; ret.toArray(retArray); return retArray; }
अपने ऐप्लिकेशन Context
और एक्सपैंशन फ़ाइल के पसंदीदा वर्शन को पास करके, इस तरीके को कॉल किया जा सकता है.
एक्सपेंशन फ़ाइल के वर्शन नंबर का पता लगाने के कई तरीके हैं. इसका एक आसान तरीका यह है कि डाउनलोड शुरू होने पर, वर्शन को SharedPreferences फ़ाइल में सेव किया जाए. इसके लिए, APKExpansionPolicy क्लास के getExpansionFileName(int index) तरीके का इस्तेमाल करके, एक्सपैंशन फ़ाइल के नाम के बारे में क्वेरी करें. इसके बाद, जब आपको एक्सपैंशन फ़ाइल ऐक्सेस करनी हो, तब SharedPreferences फ़ाइल को पढ़कर वर्शन कोड पाया जा सकता है.
शेयर किए गए स्टोरेज से डेटा पढ़ने के बारे में ज़्यादा जानने के लिए, डेटा स्टोरेज से जुड़ा दस्तावेज़ देखें.
APK एक्सपैंशन ज़िप लाइब्रेरी का इस्तेमाल करना
Google Market Apk Expansion पैकेज में, APK Expansion Zip Library नाम की एक लाइब्रेरी शामिल होती है. यह <sdk>/extras/google/google_market_apk_expansion/zip_file/ में मौजूद होती है. यह एक वैकल्पिक लाइब्रेरी है. इससे आपको ZIP फ़ाइलों के तौर पर सेव की गई एक्सपैंशन फ़ाइलों को पढ़ने में मदद मिलती है. इस लाइब्रेरी का इस्तेमाल करके, वर्चुअल फ़ाइल सिस्टम के तौर पर अपनी ZIP फ़ाइलों से आसानी से संसाधन पढ़े जा सकते हैं.
APK एक्सपैंशन ZIP लाइब्रेरी में ये क्लास और एपीआई शामिल हैं:
APKExpansionSupport- एक्सपैंशन फ़ाइल के नाम और ZIP फ़ाइलों को ऐक्सेस करने के कुछ तरीके बताता है:
getAPKExpansionFiles()- ऊपर दिखाया गया वही तरीका, जो दोनों एक्सपैंशन फ़ाइलों का पूरा फ़ाइल पाथ दिखाता है.
getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion)- यह
ZipResourceFileदिखाता है. यह मुख्य फ़ाइल और पैच फ़ाइल, दोनों के योग को दिखाता है. इसका मतलब है कि अगर आपनेmainVersionऔरpatchVersion, दोनों को तय किया है, तो इससेZipResourceFileमिलता है. इससे सभी डेटा को पढ़ने का ऐक्सेस मिलता है. साथ ही, पैच फ़ाइल का डेटा मुख्य फ़ाइल में सबसे ऊपर मर्ज हो जाता है.
ZipResourceFile- यह शेयर किए गए स्टोरेज पर मौजूद ZIP फ़ाइल को दिखाता है. साथ ही, आपकी ZIP फ़ाइलों के आधार पर वर्चुअल फ़ाइल सिस्टम उपलब्ध कराने के लिए सभी काम करता है.
APKExpansionSupport.getAPKExpansionZipFile()का इस्तेमाल करके याZipResourceFileके साथ अपनी एक्सपैंशन फ़ाइल का पाथ पास करके, इंस्टेंस पाया जा सकता है. इस क्लास में कई काम के तरीके शामिल हैं. हालांकि, आम तौर पर आपको इनमें से ज़्यादातर को ऐक्सेस करने की ज़रूरत नहीं होती. इसके लिए, यहां दिए गए दो तरीके अपनाए जा सकते हैं:getInputStream(String assetPath)- ZIP फ़ाइल में मौजूद किसी फ़ाइल को पढ़ने के लिए,
InputStreamउपलब्ध कराता है.assetPath, ZIP फ़ाइल के कॉन्टेंट के रूट के हिसाब से, उस फ़ाइल का पाथ होना चाहिए जिसे आपको शामिल करना है. getAssetFileDescriptor(String assetPath)- ZIP फ़ाइल में मौजूद किसी फ़ाइल के लिए
AssetFileDescriptorउपलब्ध कराता है.assetPath, ZIP फ़ाइल के कॉन्टेंट के रूट के हिसाब से, उस फ़ाइल का पाथ होना चाहिए जिसे आपको शामिल करना है. यह कुछ Android API के लिए काम का है. इन API के लिएAssetFileDescriptorकी ज़रूरत होती है. जैसे, कुछMediaPlayerAPI.
APEZProvider- ज़्यादातर ऐप्लिकेशन को इस क्लास का इस्तेमाल करने की ज़रूरत नहीं होती. यह क्लास, एक
ContentProviderको तय करती है. यह कॉन्टेंट प्रोवाइडरUriके ज़रिए ZIP फ़ाइलों से डेटा को मार्शेल करती है, ताकि कुछ Android API के लिए फ़ाइल ऐक्सेस की सुविधा दी जा सके. इन Android API को मीडिया फ़ाइलों के लिएUriऐक्सेस की ज़रूरत होती है. उदाहरण के लिए, अगर आपकोVideoView.setVideoURI()के साथ कोई वीडियो चलाना है, तो यह सुविधा काम की है.
मीडिया फ़ाइलों को ZIP फ़ाइल में कंप्रेस नहीं किया जा रहा है
अगर मीडिया फ़ाइलों को सेव करने के लिए, विस्तार फ़ाइलों का इस्तेमाल किया जा रहा है, तो ZIP फ़ाइल की मदद से अब भी Android मीडिया प्लेयर के उन फ़ंक्शन का इस्तेमाल किया जा सकता है जो ऑफ़सेट और अवधि कंट्रोल करने की सुविधा देते हैं. जैसे, MediaPlayer.setDataSource() और SoundPool.load(). इसके लिए, ZIP पैकेज बनाते समय मीडिया फ़ाइलों को कंप्रेस न करें. उदाहरण के लिए, zip टूल का इस्तेमाल करते समय, आपको -n विकल्प का इस्तेमाल करना चाहिए. इससे उन फ़ाइल सफ़िक्स के बारे में बताया जा सकता है जिन्हें कंप्रेस नहीं किया जाना चाहिए:
zip -n .mp4;.ogg main_expansion media_files
किसी ZIP फ़ाइल से डेटा पढ़ना
APK एक्सपैंशन Zip लाइब्रेरी का इस्तेमाल करते समय, आम तौर पर ZIP फ़ाइल से किसी फ़ाइल को पढ़ने के लिए, इन चीज़ों की ज़रूरत होती है:
Kotlin
// Get a ZipResourceFile representing a merger of both the main and patch files val expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a merger of both the main and patch files ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
ऊपर दिए गए कोड से, आपकी मुख्य एक्सपैंशन फ़ाइल या पैच एक्सपैंशन फ़ाइल में मौजूद किसी भी फ़ाइल को ऐक्सेस किया जा सकता है. इसके लिए, दोनों फ़ाइलों से सभी फ़ाइलों के मर्ज किए गए मैप को पढ़ा जाता है. getAPKExpansionFile() तरीके का इस्तेमाल करने के लिए, आपको अपने ऐप्लिकेशन android.content.Context के साथ-साथ मुख्य एक्सपैंशन फ़ाइल और पैच एक्सपैंशन फ़ाइल, दोनों के लिए वर्शन नंबर देना होगा.
अगर आपको किसी खास एक्सपैंशन फ़ाइल से डेटा पढ़ना है, तो ZipResourceFile कंस्ट्रक्टर का इस्तेमाल करें. इसके लिए, आपको उस एक्सपैंशन फ़ाइल का पाथ देना होगा:
Kotlin
// Get a ZipResourceFile representing a specific expansion file val expansionFile = ZipResourceFile(filePathToMyZip) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a specific expansion file ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
अपनी एक्सपैंशन फ़ाइलों के लिए इस लाइब्रेरी का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, सैंपल ऐप्लिकेशन की SampleDownloaderActivity क्लास देखें. इसमें डाउनलोड की गई फ़ाइलों की पुष्टि करने के लिए अतिरिक्त कोड शामिल होता है. ध्यान दें कि अगर आपको इस सैंपल का इस्तेमाल करके, अपने ऐप्लिकेशन में एक्सपैंशन फ़ाइलें लागू करनी हैं, तो आपको xAPKS ऐरे में अपनी एक्सपैंशन फ़ाइलों का बाइट साइज़ बताना होगा.
एक्सपैंशन फ़ाइलों की जांच करना
अपना ऐप्लिकेशन पब्लिश करने से पहले, आपको दो चीज़ों की जांच करनी चाहिए: एक्सपैंशन फ़ाइलों को पढ़ना और फ़ाइलों को डाउनलोड करना.
फ़ाइलें पढ़ने की सुविधा की जांच की जा रही है
Google Play पर अपना ऐप्लिकेशन अपलोड करने से पहले, आपको यह जांच करनी चाहिए कि आपका ऐप्लिकेशन, शेयर किए गए स्टोरेज से फ़ाइलें पढ़ सकता है या नहीं. आपको बस इतना करना है कि डिवाइस के शेयर किए गए स्टोरेज में सही जगह पर फ़ाइलें जोड़ें और अपना ऐप्लिकेशन लॉन्च करें:
- अपने डिवाइस पर, शेयर किए गए स्टोरेज में सही डायरेक्ट्री बनाएं. Google Play इस डायरेक्ट्री में आपकी फ़ाइलें सेव करेगा.
उदाहरण के लिए, अगर आपके पैकेज का नाम
com.example.androidहै, तो आपको शेयर किए गए स्टोरेज स्पेस परAndroid/obb/com.example.android/डायरेक्ट्री बनानी होगी. शेयर किए गए स्टोरेज को माउंट करने के लिए, अपने टेस्ट के लिए डिवाइस को कंप्यूटर से कनेक्ट करें और इस डायरेक्ट्री को मैन्युअल तरीके से बनाएं. - एक्सपैंशन फ़ाइलों को उस डायरेक्ट्री में मैन्युअल तरीके से जोड़ें. पक्का करें कि आपने अपनी फ़ाइलों का नाम बदलकर, Google Play के फ़ाइल के नाम के फ़ॉर्मैट के हिसाब से कर दिया हो.
उदाहरण के लिए, फ़ाइल टाइप चाहे जो भी हो,
com.example.androidऐप्लिकेशन के लिए मुख्य एक्सपैंशन फ़ाइलmain.0300110.com.example.android.obbहोनी चाहिए. वर्शन कोड को अपनी पसंद के हिसाब से सेट किया जा सकता है. बस इन बातों का ध्यान रखें:- मुख्य एक्सपैंशन फ़ाइल हमेशा
mainसे शुरू होती है और पैच फ़ाइलpatchसे शुरू होती है. - पैकेज का नाम हमेशा उस APK से मेल खाता है जिससे फ़ाइल को Google Play पर अटैच किया गया है.
- मुख्य एक्सपैंशन फ़ाइल हमेशा
- अब एक्सपैंशन फ़ाइलें डिवाइस पर मौजूद हैं. इसलिए, अपने ऐप्लिकेशन को इंस्टॉल और चलाया जा सकता है, ताकि एक्सपैंशन फ़ाइलों की जांच की जा सके.
एक्सपेंशन फ़ाइलों को मैनेज करने के बारे में यहां कुछ रिमाइंडर दिए गए हैं:
.obbएक्सपैंशन फ़ाइलों को न तो मिटाएं और न ही उनका नाम बदलें. भले ही, आपने डेटा को किसी दूसरी जगह पर अनपैक कर दिया हो. ऐसा करने पर, Google Play (या आपका ऐप्लिकेशन) एक्सपैंशन फ़ाइल को बार-बार डाउनलोड करेगा.- अपनी
obb/डायरेक्ट्री में कोई और डेटा सेव न करें. अगर आपको कुछ डेटा अनपैक करना है, तो उसेgetExternalFilesDir()में बताई गई जगह पर सेव करें.
फ़ाइल डाउनलोड करने की सुविधा की जांच करना
जब आपका ऐप्लिकेशन पहली बार खुलता है, तो उसे कभी-कभी एक्सपैंशन फ़ाइलें मैन्युअल तरीके से डाउनलोड करनी पड़ती हैं. इसलिए, यह ज़रूरी है कि आप इस प्रोसेस की जांच करें. इससे यह पक्का किया जा सकेगा कि आपका ऐप्लिकेशन यूआरएल के लिए क्वेरी कर सकता है, फ़ाइलें डाउनलोड कर सकता है, और उन्हें डिवाइस में सेव कर सकता है.
मैन्युअल तरीके से डाउनलोड करने की प्रोसेस को लागू करने के लिए, अपने ऐप्लिकेशन को इंटरनल टेस्ट ट्रैक पर पब्लिश करें. इससे यह सिर्फ़ उन टेस्टर के लिए उपलब्ध होगा जिन्हें अनुमति मिली है. अगर सब कुछ ठीक से काम करता है, तो मुख्य ऐक्टिविटी शुरू होते ही आपके ऐप्लिकेशन को एक्सपैंशन फ़ाइलें डाउनलोड करना शुरू कर देना चाहिए.
ध्यान दें: पहले, पब्लिश न किए गए "ड्राफ़्ट" वर्शन को अपलोड करके, किसी ऐप्लिकेशन को टेस्ट किया जा सकता था. यह सुविधा अब काम नहीं करती. इसके बजाय, आपको इसे इंटरनल, क्लोज़्ड या ओपन टेस्टिंग ट्रैक पर पब्लिश करना होगा. ज़्यादा जानकारी के लिए, ड्राफ़्ट ऐप्लिकेशन अब काम नहीं करते लेख पढ़ें.
ऐप्लिकेशन अपडेट करना
Google Play पर एक्सपैंशन फ़ाइलों का इस्तेमाल करने का एक बड़ा फ़ायदा यह है कि आपको सभी ओरिजनल ऐसेट को फिर से डाउनलोड किए बिना, अपने ऐप्लिकेशन को अपडेट करने की सुविधा मिलती है. Google Play हर APK के साथ दो एक्सपैंशन फ़ाइलें उपलब्ध कराने की अनुमति देता है. इसलिए, दूसरी फ़ाइल का इस्तेमाल "पैच" के तौर पर किया जा सकता है. इससे अपडेट और नई ऐसेट उपलब्ध कराई जा सकती हैं. ऐसा करने से, मुख्य एक्सपैंशन फ़ाइल को फिर से डाउनलोड करने की ज़रूरत नहीं पड़ती. यह फ़ाइल बड़ी हो सकती है और उपयोगकर्ताओं के लिए इसका डाउनलोड महंगा पड़ सकता है.
टेक्निकल तौर पर, पैच एक्सपैंशन फ़ाइल, मुख्य एक्सपैंशन फ़ाइल जैसी ही होती है. Android सिस्टम और Google Play, दोनों ही आपकी मुख्य और पैच एक्सपैंशन फ़ाइलों के बीच असल पैचिंग नहीं करते हैं. आपके ऐप्लिकेशन के कोड में, ज़रूरी पैच अपने-आप लागू होने चाहिए.
अगर एक्सपैंशन फ़ाइलों के तौर पर ZIP फ़ाइलों का इस्तेमाल किया जाता है, तो Apk Expansion पैकेज में शामिल APK Expansion Zip Library में, आपकी पैच फ़ाइल को मुख्य एक्सपैंशन फ़ाइल के साथ मर्ज करने की सुविधा शामिल होती है.
ध्यान दें: अगर आपको सिर्फ़ पैच एक्सपैंशन फ़ाइल में बदलाव करने हैं, तब भी आपको APK अपडेट करना होगा. ऐसा करने पर ही Google Play, अपडेट कर पाएगा.
अगर आपको ऐप्लिकेशन में कोड बदलने की ज़रूरत नहीं है, तो आपको मेनिफ़ेस्ट में सिर्फ़ versionCode को अपडेट करना चाहिए.
जब तक Play Console में, APK से जुड़ी मुख्य एक्सपैंशन फ़ाइल में बदलाव नहीं किया जाता, तब तक जिन लोगों ने पहले आपका ऐप्लिकेशन इंस्टॉल किया था वे मुख्य एक्सपैंशन फ़ाइल डाउनलोड नहीं करेंगे. मौजूदा उपयोगकर्ताओं को सिर्फ़ अपडेट किया गया APK और नई पैच एक्सपैंशन फ़ाइल मिलती है. हालांकि, उन्हें पिछली मुख्य एक्सपैंशन फ़ाइल मिलती रहती है.
एक्सपेंशन फ़ाइलों के अपडेट से जुड़ी इन बातों का ध्यान रखें:
- आपके ऐप्लिकेशन के लिए, एक बार में सिर्फ़ दो एक्सपैंशन फ़ाइलें हो सकती हैं. एक मुख्य एक्सपैंशन फ़ाइल और एक पैच एक्सपैंशन फ़ाइल. किसी फ़ाइल को अपडेट करने के दौरान, Google Play पिछले वर्शन को मिटा देता है. मैन्युअल तरीके से अपडेट करने के दौरान, आपके ऐप्लिकेशन को भी ऐसा ही करना होगा.
- पैच एक्सपैंशन फ़ाइल जोड़ने पर, Android सिस्टम आपके ऐप्लिकेशन या मुख्य एक्सपैंशन फ़ाइल को पैच नहीं करता है. आपको अपने ऐप्लिकेशन को इस तरह से डिज़ाइन करना होगा कि वह पैच डेटा को सपोर्ट करे. हालांकि, Apk Expansion पैकेज में ZIP फ़ाइलों को एक्सपैंशन फ़ाइलों के तौर पर इस्तेमाल करने के लिए एक लाइब्रेरी शामिल होती है. यह लाइब्रेरी, पैच फ़ाइल के डेटा को मुख्य एक्सपैंशन फ़ाइल में मर्ज करती है, ताकि आप एक्सपैंशन फ़ाइल के सभी डेटा को आसानी से पढ़ सकें.