Android के लिए, तेज़ी से बार-बार बदलाव करके डेवलपमेंट करना
इस पेज पर बताया गया है कि bazel mobile-install
, Android के लिए बार-बार होने वाले डेवलपमेंट को ज़्यादा तेज़ कैसे बनाता है. इसमें, ऐप्लिकेशन इंस्टॉल करने के पारंपरिक तरीके की चुनौतियों के मुकाबले, इस तरीके के फ़ायदों के बारे में बताया गया है.
खास जानकारी
किसी Android ऐप्लिकेशन में छोटे-छोटे बदलावों को बहुत जल्दी इंस्टॉल करने के लिए, यह तरीका अपनाएं:
- आपको जिस ऐप्लिकेशन को इंस्टॉल करना है उसके
android_binary
नियम पर जाएं. proguard_specs
एट्रिब्यूट को हटाकर, ProGuard को बंद करें.multidex
एट्रिब्यूट कोnative
पर सेट करें.dex_shards
एट्रिब्यूट को10
पर सेट करें.- ART (न कि Dalvik) पर काम करने वाले अपने डिवाइस को यूएसबी से कनेक्ट करें और उस पर यूएसबी डिबगिंग की सुविधा चालू करें.
bazel mobile-install :your_target
चलाएं. ऐप्लिकेशन को चालू करने में थोड़ा समय लगेगा सामान्य से धीमा.- कोड या Android संसाधनों में बदलाव करें.
bazel mobile-install --incremental :your_target
चलाएं.- ज़्यादा इंतज़ार न करने का आनंद लें.
Bazel के लिए कमांड लाइन के कुछ विकल्प, जो काम के हो सकते हैं:
--adb
बेज़ल को बताता है कि किस adb बाइनरी का इस्तेमाल करना है--adb_arg
का इस्तेमाल,adb
की कमांड लाइन में अतिरिक्त आर्ग्युमेंट जोड़ने के लिए किया जा सकता है. इसका एक फ़ायदा यह है कि अगर आपके वर्कस्टेशन से एक से ज़्यादा डिवाइस कनेक्ट हैं, तो यह चुना जा सकता है कि आपको किस डिवाइस पर ऐप्लिकेशन इंस्टॉल करना है:bazel mobile-install --adb_arg=-s --adb_arg=<SERIAL> :your_target
--start_app
ऐप्लिकेशन को अपने-आप शुरू करता है
अगर आपको नहीं पता कि ब्रैंड का नाम सही है या नहीं, तो उदाहरण देखें या हमसे संपर्क करें.
परिचय
डेवलपर के टूलचेन का सबसे अहम एट्रिब्यूट, स्पीड है: कोड में बदलाव करने और उसे एक सेकंड में चलने के बीच का फ़र्क़ बहुत ज़्यादा है. साथ ही, आपको यह जानने के लिए मिनटों या कभी-कभी घंटों तक इंतज़ार करना पड़ता है कि आपके बदलावों से आपको उम्मीद के मुताबिक नतीजे मिल रहे हैं या नहीं.
दुर्भाग्य से, .apk बनाने के लिए पारंपरिक Android टूलचेन कई मोनोलिथिक और क्रम से चलने वाले चरण हैं. साथ ही, इन सभी चरणों को पूरा करने के बाद ही एक Android ऐप्लिकेशन कैसे बनाते हैं. Google में, एक लाइन बनाने के लिए पांच मिनट तक इंतज़ार करना पड़ सकता है Google Maps जैसे बड़े प्रोजेक्ट में बदलाव नहीं हुआ है.
bazel mobile-install
, Android के लिए बार-बार डेवलपमेंट करने की सुविधा देता है.
जिसमें बदलाव की काट-छांट, वर्क शार्डिंग, और चालाकी से हेर-फेर किए गए फ़ेरबदल किए गए वीडियो का इस्तेमाल किया जाता है
Android की इंटरनल सुविधाएं, यानी कि आपके ऐप्लिकेशन के कोड में कोई बदलाव नहीं किया जाना चाहिए.
ऐप्लिकेशन को इंस्टॉल करने के पुराने तरीके में आने वाली समस्याएं
Android ऐप्लिकेशन बनाने में कुछ समस्याएं आती हैं. इनमें ये समस्याएं शामिल हैं:
डेक्सिंग. डिफ़ॉल्ट रूप से, "dx" बिल्ड में ठीक एक बार इस्तेमाल किया जाता है और इसका इस्तेमाल नहीं किया जाता पिछले बिल्ड से काम दोबारा इस्तेमाल करने का तरीका जानें: यह हर तरीके को फिर से बदल देता है, यहां तक कि हालांकि, सिर्फ़ एक तरीका बदला गया था.
डिवाइस पर डेटा अपलोड हो रहा है. adb, यूएसबी 2.0 की पूरी बैंडविड्थ इस्तेमाल नहीं करता और बड़े ऐप्लिकेशन को अपलोड होने में बहुत समय लग सकता है. यह पूरा ऐप्लिकेशन अपलोड किए गए वीडियो के छोटे हिस्से में ही बदलाव हुआ हो. उदाहरण के लिए, संसाधन या भी शामिल नहीं करना है. इसलिए, यह एक बड़ी समस्या हो सकती है.
नेटिव कोड में कंपाइल करना. Android L में ART को पेश किया गया था. यह Android का एक नया रनटाइम है. यह ऐप्लिकेशन को Dalvik की तरह, रनटाइम के दौरान कंपाइल करने के बजाय, पहले से कंपाइल करता है. इससे, लंबे समय तक इंस्टॉल किए जाने की लागत में ऐप्लिकेशन ज़्यादा तेज़ी से इंस्टॉल हो जाते हैं समय. यह उपयोगकर्ताओं के लिए एक अच्छा विकल्प है, क्योंकि वे आम तौर पर कोई ऐप्लिकेशन इंस्टॉल करते हैं उसे कई बार इस्तेमाल कर लें, लेकिन ऐप्लिकेशन का डेवलपमेंट धीमा हो जाता है, क्योंकि ऐप्लिकेशन कई बार इंस्टॉल होता है और हर वर्शन ज़्यादा से ज़्यादा बार चलता है.
bazel mobile-install
को अपनाने का तरीका
bazel mobile-install
इनमें सुधार करता है:
शार्ड डेक्सिंग. ऐप्लिकेशन का Java कोड बनाने के बाद, Basel ने ऐप्लिकेशन की क्लास को बेहतर बनाया है फ़ाइलों को करीब-करीब बराबर साइज़ वाले हिस्सों में बांटती हैं और
dx
को अलग से शुरू करती हैं उन्हें.dx
को उन शर्ड पर ट्रिगर नहीं किया जाता जो पिछले बिल्ड के बाद से नहीं बदले हैं.इंक्रीमेंटल फ़ाइल ट्रांसफ़र. Android के संसाधन, .dex फ़ाइलें, और नेटिव विज्ञापन लाइब्रेरी को मुख्य .apk से हटा दिया जाता है और उन्हें एक अलग मोबाइल-इंस्टॉल डायरेक्ट्री में डालें. इसकी मदद से, पूरे ऐप्लिकेशन को फिर से इंस्टॉल किए बिना, कोड और Android के संसाधनों को अलग-अलग अपडेट किया जा सकता है. इसलिए, फ़ाइलों को ट्रांसफ़र करने में कम समय लगता है और डिवाइस पर सिर्फ़ उन .dex फ़ाइलों को फिर से कंपाइल किया जाता है जिनमें बदलाव किया गया है.
.apk के बाहर से ऐप्लिकेशन के कुछ हिस्से लोड करना. एक छोटा स्टब ऐप्लिकेशन .apk में डालें जो Android संसाधन, Java कोड और नेटिव कोड लोड करता है पर क्लिक करें, फिर नियंत्रण को असली ऐप. कुछ खास मामलों को छोड़कर, ऐप्लिकेशन पर यह जानकारी साफ़ तौर पर दी गई होती है जिनकी जानकारी नीचे दी गई है.
डेटा को अलग-अलग हिस्सों में बांटकर डीकोड करना
शीयर की गई फ़ाइलों को इंडेक्स करना आसान है: .jar फ़ाइलें बन जाने के बाद, एक टूल उन्हें लगभग बराबर साइज़ की अलग-अलग .jar फ़ाइलों में बांट देता है. इसके बाद, पिछले बिल्ड के बाद बदली गई फ़ाइलों पर dx
को लागू करता है. वह तर्क जो
यह तय करता है कि Android के लिए कौन से शार्ड को डेक्स करना विशिष्ट नहीं है: यह बस
बेज़ल का जनरल चेंज प्रिनिंग एल्गोरिदम.
शर्डिंग एल्गोरिदम के पहले वर्शन में, .class फ़ाइलों को अंग्रेज़ी के वर्णमाला के क्रम में लगाया जाता था. इसके बाद, सूची को बराबर साइज़ के हिस्सों में बांटा जाता था. हालांकि, यह तरीका सबसे सही नहीं था: अगर किसी क्लास को जोड़ा या हटाया जाता था (यहां तक कि नेस्ट की गई या बिना नाम वाली क्लास को भी), तो इसके बाद अंग्रेज़ी के वर्णमाला के क्रम में मौजूद सभी क्लास एक स्थान आगे या पीछे हो जाती थीं. इस वजह से, उन शर्ड को फिर से इंडेक्स करना पड़ता था. इसलिए, अलग-अलग क्लास के बजाय, Java के पैकेज को शेयर करने का फ़ैसला लिया गया. हालांकि, अब भी इन विज्ञापनों का असर यदि कोई नया पैकेज जोड़ा या निकाला जाता है तो कई शार्ड को नष्ट करना, लेकिन यह बहुत कम होता है एकल क्लास को जोड़ने या हटाने से ज़्यादा होता है.
android_binary.dex_shards
एट्रिब्यूट का इस्तेमाल करके, BUILD फ़ाइल से स्HARD की संख्या कंट्रोल की जाती है. आम तौर पर, Bazel अपने-आप यह तय कर लेता है कि कितने शर्ड सबसे सही हैं. हालांकि, फ़िलहाल Bazel को किसी भी कार्रवाई को पूरा करने से पहले, कार्रवाइयों का सेट (उदाहरण के लिए, बिल्ड के दौरान लागू किए जाने वाले निर्देश) पता होना चाहिए. इसलिए, यह शर्ड की सबसे सही संख्या तय नहीं कर सकता, क्योंकि यह नहीं जानता कि ऐप्लिकेशन में आखिर में कितनी Java क्लास होंगी. आम तौर पर, जितने ज़्यादा शर्ड होंगे, बिल्ड और इंस्टॉलेशन उतना ही तेज़ होगा. हालांकि, ऐप्लिकेशन को शुरू होने में ज़्यादा समय लगेगा, क्योंकि डाइनैमिक लिंकर को ज़्यादा काम करना होगा. बेहतर बिंदु आमतौर पर 10 से 50 शार्ड के बीच होता है.
इंक्रीमेंटल फ़ाइल ट्रांसफ़र
ऐप्लिकेशन बनाने के बाद, अगला चरण उसे इंस्टॉल करना है. इंस्टॉलेशन के लिए, ये चरण अपनाएं:
- .apk इंस्टॉल करना (आम तौर पर,
adb install
का इस्तेमाल करना) - .dex फ़ाइलें, Android संसाधन, और स्थानीय लाइब्रेरी मोबाइल-इंस्टॉल डायरेक्ट्री
पहले चरण में, ज़्यादा बढ़ोतरी नहीं होती: ऐप्लिकेशन या तो इंस्टॉल होता है या नहीं. फ़िलहाल, Bazel यह तय करने के लिए उपयोगकर्ता पर निर्भर करता है कि उसे --incremental
कमांड लाइन विकल्प के ज़रिए यह चरण पूरा करना चाहिए या नहीं. ऐसा इसलिए, क्योंकि यह सभी मामलों में यह तय नहीं कर सकता कि यह ज़रूरी है या नहीं.
दूसरे चरण में, बिल्ड से ऐप्लिकेशन की फ़ाइलों की तुलना, डिवाइस पर मौजूद मेनिफ़ेस्ट फ़ाइल से की जाती है. इस फ़ाइल में, डिवाइस पर मौजूद ऐप्लिकेशन की फ़ाइलों और उनके चेकसम की सूची होती है. नई फ़ाइलें डिवाइस पर अपलोड की जाती हैं, बदली गई फ़ाइलों को अपडेट किया जाता है, और हटाई गई फ़ाइलों को डिवाइस से मिटा दिया जाता है. अगर मेनिफ़ेस्ट मौजूद नहीं है, तो यह माना जाता है कि हर फ़ाइल को अपलोड करना ज़रूरी है.
ध्यान दें कि इंक्रीमेंटल इंस्टॉलेशन एल्गोरिदम को डिवाइस पर फ़ाइल बदल रहा है, लेकिन मेनिफ़ेस्ट में उसका चेकसम नहीं बदल रहा. यह काम कर सका फ़ाइलों के चेकसम की गणना करके, हालांकि, इंस्टॉल करने में लगने वाले समय को बढ़ाना ज़रूरी नहीं था.
स्टब ऐप्लिकेशन
स्टब ऐप्लिकेशन की मदद से डेक्स, नेटिव कोड, और
डिवाइस पर मौजूद mobile-install
डायरेक्ट्री से, Android के संसाधन इकट्ठा किए जाते हैं.
असल में लोड होने की प्रोसेस, BaseDexClassLoader
को सब-क्लास करके लागू की जाती है और यह
इस तकनीक के बारे में पुख्ता सबूत मौजूद हैं. यह ऐप्लिकेशन की किसी भी क्लास के लोड होने से पहले होता है, ताकि APK में मौजूद किसी भी ऐप्लिकेशन क्लास को डिवाइस पर मौजूद mobile-install
डायरेक्ट्री में रखा जा सके. इससे उन्हें adb install
के बिना अपडेट किया जा सकता है.
ऐसा ऐप्लिकेशन की किसी भी क्लास के लोड होने से पहले करना ज़रूरी है, ताकि किसी भी ऐप्लिकेशन क्लास को .apk में शामिल न करना पड़े. इसका मतलब है कि उन क्लास में बदलाव करने के लिए, उन्हें फिर से पूरी तरह से इंस्टॉल करना होगा.
ऐसा करने के लिए, AndroidManifest.xml
में बताई गई Application
क्लास को स्टब ऐप्लिकेशन से बदलें. यह
ऐप्लिकेशन के शुरू होने पर कंट्रोल करता है और क्लास लोड करने वाले टूल और
कम से कम समय में सही तरीके से रिसोर्स मैनेजर (इसका कंस्ट्रक्टर)
Android फ़्रेमवर्क के अंदरूनी हिस्सों पर Java का प्रतिबिंब.
स्टब ऐप्लिकेशन, मोबाइल-इंस्टॉल की मदद से इंस्टॉल की गई नेटिव लाइब्रेरी को किसी दूसरी जगह पर कॉपी भी करता है. ऐसा करना ज़रूरी है, क्योंकि डाइनैमिक लिंकर को फ़ाइलों पर X
बिट सेट करने की ज़रूरत होती है. ऐसा किसी ऐसी जगह के लिए नहीं किया जा सकता जिसे नॉन-रूट adb
ऐक्सेस कर सकता है.
ये सभी काम करने के बाद, स्टब ऐप्लिकेशन असल Application
क्लास को इंस्टैंशिएट करता है. साथ ही, Android फ़्रेमवर्क में अपने सभी रेफ़रंस को असल ऐप्लिकेशन में बदल देता है.
नतीजे
परफ़ॉर्मेंस
आम तौर पर, bazel mobile-install
की मदद से, छोटे बदलाव के बाद बड़े ऐप्लिकेशन बनाने और इंस्टॉल करने में चार से 10 गुना ज़्यादा तेज़ी आती है.
नीचे दी गई संख्याओं का हिसाब Google के कुछ प्रॉडक्ट के लिए लगाया गया है:
हालांकि, यह इस बात पर निर्भर करता है कि बदलाव किस तरह का है: किसी बेस लाइब्रेरी में बदलाव करने के बाद, फिर से कंपाइल करने में ज़्यादा समय लगता है.
सीमाएं
स्टब ऐप्लिकेशन की जो चालें चलती हैं वे हर मामले में काम नहीं करतीं. नीचे दिए गए मामले उन मामलों को हाइलाइट करते हैं जहां यह उम्मीद के मुताबिक काम नहीं करता:
जब
Context
कोApplication
क्लास में कास्ट किया जाता हैContentProvider#onCreate()
. इस तरीके का इस्तेमाल, आवेदन करने के दौरान किया जाता है स्टार्ट होने से पहले हमेंApplication
के इंस्टेंस को बदलने का मौका नहीं मिलता क्लास है, इसलिएContentProvider
अब भी स्टब ऐप्लिकेशन का रेफ़रंस देगा में होती है. शायद, यह कोई गड़बड़ी नहीं है, क्योंकि आपContext
को इस तरह से डाउनग्रेड करना था, लेकिन ऐसा लगता है कि कुछ ही दिनों में ऐसा होता है ऐप्लिकेशन है.bazel mobile-install
से इंस्टॉल किए गए रिसॉर्स, सिर्फ़ ऐप्लिकेशन में ही उपलब्ध होते हैं. अगरPackageManager#getApplicationResources()
की मदद से अन्य ऐप्लिकेशन रिसॉर्स ऐक्सेस करते हैं, तो ये रिसॉर्स, इंक्रीमेंटल इंस्टॉल के बजाय, पिछले इंस्टॉल से होंगे.वे डिवाइस जिन पर ART नहीं चल रहा है. जब स्टब ऐप्लिकेशन इन डिवाइसों पर सही से काम करता है Froyo और बाद में, Delvik को एक बग मिला, जिससे उन्हें लगता है कि ऐप्लिकेशन अगर इसका कोड किसी खास स्थान में एकाधिक .dex फ़ाइलों पर वितरित किया गया है, तो यह गलत है मामलों में, उदाहरण के लिए, जब किसी खास तरीका है. जब तक आपका ऐप्लिकेशन इन गड़बड़ियों से नहीं जुड़ा है, तब तक यह Dalvik के साथ भी काम करेगा. हालांकि, ध्यान दें कि हमारा मकसद Android के पुराने वर्शन के लिए सहायता उपलब्ध कराना नहीं है