Android ऐप का बैकएंड कैसे बनाएं?

Back4app एंड्रॉइड ऐप कवर

इस लेख में, हम एंड्रॉइड — जो सबसे लोकप्रिय ऑपरेटिंग सिस्टम में से एक है — के बारे में चर्चा करेंगे। हम एंड्रॉइड डेवलपमेंट के फायदे और नुकसान, मोबाइल एप्लीकेशन के लिए बैकएंड विकल्पों पर नज़र डालेंगे, और आपको अपना खुद का मोबाइल बैकएंड बनाना सिखाएंगे।

Contents

मुख्य बिंदु

  • एंड्रॉइड का प्रभुत्व: एंड्रॉइड, एक ओपन-सोर्स OS होने के नाते, लगभग 70% मोबाइल डिवाइस पर चलता है और इसके तीन बिलियन से अधिक सक्रिय उपयोगकर्ता हैं।
  • ऐप्स के लिए बैकएंड विकल्प: मोबाइल ऐप बैकएंड के लिए, डेवलपर्स इंफ्रास्ट्रक्चर ऐज़ अ सर्विस (IaaS), प्लेटफ़ॉर्म ऐज़ अ सर्विस (PaaS), या बैकएंड ऐज़ अ सर्विस (BaaS) का चयन कर सकते हैं।
  • अपना बैकएंड बनाने के चरण: हम आपको बताएँगे कि BaaS प्लेटफ़ॉर्म का इस्तेमाल करके एंड्रॉइड बैकएंड कैसे बनाया जा सकता है, और लेख के अंत में सोर्स कोड भी साझा करेंगे।

एंड्रॉइड क्या है?

एंड्रॉइड एक मुफ्त और ओपन-सोर्स लिनक्स-आधारित ऑपरेटिंग सिस्टम है। इसे मुख्य रूप से स्मार्टफ़ोन और टैबलेट जैसे मोबाइल डिवाइस के लिए डिज़ाइन किया गया था, लेकिन अब यह स्मार्ट टीवी, एंबेडेड सिस्टम, गेमिंग कंसोल आदि में भी उपयोग किया जाता है।

एंड्रॉइड का विकास 2003 में Android Inc. द्वारा शुरू हुआ था। शुरुआत में कंपनी डिजिटल कैमरों के लिए एक ऑपरेटिंग सिस्टम बनाना चाहती थी, लेकिन जल्दी ही एक बड़े बाज़ार तक पहुँचने के लिए मोबाइल OS विकास की ओर रुख कर लिया गया।

2005 में, Google ने कंपनी को उसके कर्मचारियों सहित अधिग्रहित कर लिया। 2008 में एंड्रॉइड का पहला संस्करण जारी किया गया था।

हालाँकि एंड्रॉइड ओपन-सोर्स है, लेकिन अधिकांश मोबाइल डिवाइस Google के स्वामित्व वाले संस्करण पर चलते हैं। इस संस्करण में Google Chrome, YouTube, Google TV और Gmail जैसी सॉफ़्टवेयर सेवाएँ पहले से आती हैं।

एंड्रॉइड में शानदार कस्टमाइज़ेशन विकल्प होने की वजह से कई निर्माता अपने ब्रांड को बेहतर ढंग से पेश करने के लिए एंड्रॉइड को अलग तरीके से कस्टमाइज़ करते हैं। यही कारण है कि OnePlus का एंड्रॉइड, Pixel के एंड्रॉइड से दिखने में काफ़ी अलग होता है।

एंड्रॉइड 2013 से अब तक सबसे लोकप्रिय ऑपरेटिंग सिस्टम रहा है। यह लगभग 70% मोबाइल डिवाइस पर चलता है और इसके तीन बिलियन से अधिक मासिक सक्रिय उपयोगकर्ता हैं।

इसके अलावा, Google Play Store पर आपको तीन मिलियन से ज़्यादा मोबाइल एप्लीकेशन तक पहुँच मिलती है। आगे पढ़ें और जानें कि एंड्रॉइड ऐप के लिए बैकएंड कैसे बनाया जाए।

एंड्रॉइड डेवलपमेंट के फायदे

आइए एंड्रॉइड डेवलपमेंट के कुछ लाभों पर नज़र डालते हैं:

क्रॉस प्लेटफॉर्म

एंड्रॉइड के लिए डेवलपमेंट करके, आप अनेक प्रकार के डिवाइस को टार्गेट कर सकते हैं। इनमें मोबाइल फोन, वियरेबल्स, स्मार्ट टीवी, गेमिंग कंसोल आदि शामिल हैं। अगर आपको मोबाइल ऐप कोड करना आता है, तो वियरेबल या स्मार्ट टीवी ऐप बनाना भी आपके लिए मुश्किल नहीं होगा।

विशाल बाज़ार

जैसा कि पहले बताया गया, एंड्रॉइड की मार्केट शेयर 70% है, जबकि iOS 30% पर है। एंड्रॉइड ऐप डेवलप करके आप स्वचालित रूप से बड़े यूज़र आधार तक पहुँच बना सकते हैं।

इसके अलावा, एंड्रॉइड ऐप कम निवेश और उच्च रिटर्न ऑन इन्वेस्टमेंट के लिए जाने जाते हैं। iOS की तरह यहाँ वार्षिक डेवलपर शुल्क भी नहीं लगता।

कस्टमाइज़ेशन

दूसरे ऑपरेटिंग सिस्टम की तुलना में एंड्रॉइड डिवाइस बहुत अधिक कस्टमाइज़ेबल होते हैं। आप अपनी कल्पना के अनुसार लगभग हर चीज़ बदल सकते हैं।

साथ ही, एंड्रॉइड में किसी भी थर्ड-पार्टी सर्विस के साथ अपने ऐप को आसानी से इंटीग्रेट करने की सुविधा भी मौजूद है।

कम्युनिटी

एंड्रॉइड को ओपन-सोर्स डेवलपर्स के विशाल समुदाय का समर्थन प्राप्त है। इसके अलावा, इसमें Android Studio, ADB और Logcat जैसे कई डेवलपर-फ्रेंडली टूल हैं, जिनकी मदद से आप आसानी से ऐप बना सकते हैं।

यदि कभी आप अटकते हैं, तो GitHub, StackOverflow, Reddit, और अन्य एंड्रॉइड-केंद्रित कम्युनिटी जैसे कई प्लेटफॉर्म पर मदद मिल सकती है।

एंड्रॉइड डेवलपमेंट की सीमाएँ

यहाँ एंड्रॉइड डेवलपमेंट से जुड़ी कुछ कमियाँ दी गई हैं:

सुरक्षा

एंड्रॉइड iOS की तुलना में कम सुरक्षित है और कड़े सुरक्षा प्रोटोकॉल का पालन नहीं करता। क्योंकि एंड्रॉइड ओपन-सोर्स है, सुरक्षा खामियाँ साप्ताहिक आधार पर सामने आ सकती हैं। इससे हैकरों को इन खामियों का फ़ायदा उठाने का मौका मिल जाता है, इससे पहले कि इन्हें पैच किया जाए।

एंड्रॉइड डिवाइस को रूट भी किया जा सकता है, जिससे सुपरयूज़र एक्सेस मिल जाती है। हालाँकि इससे आपका डिवाइस अधिक शक्तिशाली बन सकता है, लेकिन यह जोखिम भरा है क्योंकि कुछ बिल्ट-इन सुरक्षा उपाय निष्क्रिय हो जाते हैं।

जटिलता

एंड्रॉइड डिवाइस विभिन्न आकारों और विशेषताओं में आते हैं, जो एक तरह से शानदार है, लेकिन अनेक प्रकार के डिवाइस के लिए एंड्रॉइड ऐप डेवलप करना चुनौतीपूर्ण हो सकता है।

आपको सुनिश्चित करना होगा कि आपका ऐप अधिकतम डिवाइस के साथ संगत हो। इसके लिए आपको रेस्पॉन्सिव डिज़ाइन, अलग-अलग डिवाइस के हार्डवेयर आदि पर ध्यान देना पड़ेगा।

प्रीमियम ऐप्स

Google Play Store पर प्रीमियम ऐप्स उतने सफल नहीं होते जितने App Store पर होते हैं। यह कोई راز नहीं है कि एंड्रॉइड उपयोगकर्ता iOS उपयोगकर्ताओं की तुलना में ऐप्स पर कम खर्च करते हैं। यदि आप प्रीमियम-फ़र्स्ट एप्लिकेशन बना रहे हैं, तो एंड्रॉइड को दूसरा विकल्प मानना बेहतर होगा।

एंड्रॉइड ऐप्स के लिए बैकएंड विकल्प

एंड्रॉइड ऐप्स के लिए सबसे अच्छा बैकएंड क्या है? मोबाइल एप्लीकेशन के बैकएंड को आप अपनी खुद की इंफ्रास्ट्रक्चर पर या क्लाउड सर्विसेज़ में होस्ट कर सकते हैं। मोबाइल बैकएंड के लिए सबसे लोकप्रिय क्लाउड कंप्यूटिंग मॉडल ये हैं:

  1. इंफ्रास्ट्रक्चर ऐज़ अ सर्विस (IaaS)
  2. प्लेटफ़ॉर्म ऐज़ अ सर्विस (PaaS)
  3. बैकएंड ऐज़ अ सर्विस (BaaS)

प्रत्येक विकल्प अलग-अलग अमूर्त स्तर (abstraction layers) को कवर करता है, जैसा कि नीचे दी गई इमेज में दिखाया गया है।

IaaS vs PaaS vs BaaS Abstraction Layers

आइए प्रत्येक विकल्प को विस्तार से समझें, ताकि आप अपनी बैकएंड ऐप के लिए सबसे उपयुक्त क्लाउड मॉडल चुन सकें।

इंफ्रास्ट्रक्चर ऐज़ अ सर्विस (IaaS)

इंफ्रास्ट्रक्चर ऐज़ अ सर्विस (IaaS) क्लाउड कंप्यूटिंग का सबसे कम अमूर्त मॉडल है। इस मॉडल में, वेंडर यूज़र्स को वर्चुअलाइज़्ड संसाधन जैसे सर्वर, नेटवर्किंग, स्टोरेज और ऑपरेटिंग सिस्टम उच्च-स्तरीय APIs या सहज डैशबोर्ड के माध्यम से उपलब्ध कराता है।

IaaS की सबसे बड़ी विशेषता यह है कि यह उपयोगकर्ताओं को उनकी पूरी इंफ्रास्ट्रक्चर पर पूर्ण नियंत्रण देता है। IaaS सबसे लचीला और स्केलेबल मॉडल है, लेकिन इसे मैनेज करना सबसे मुश्किल भी है। यदि आप इस विकल्प का चुनाव करते हैं, तो संभवतः आपको एक या दो SysAdmin की ज़रूरत होगी।

IaaS के कुछ उदाहरण हैं Amazon Web Services, Google Cloud Platform और Azure

प्लेटफ़ॉर्म ऐज़ अ सर्विस (PaaS)

प्लेटफ़ॉर्म ऐज़ अ सर्विस (PaaS) एक क्लाउड कंप्यूटिंग मॉडल है, जिसे उपयोगकर्ताओं को ऐप डेवलप, मैनेज और डिप्लॉय करने में मदद करने के लिए डिज़ाइन किया गया है।

इंफ्रास्ट्रक्चर उपलब्ध कराने के साथ-साथ, PaaS में ऐप को डेवलप, कस्टमाइज़ और टेस्ट करने के लिए उपयोगी टूल भी शामिल होते हैं।

PaaS का उपयोग करके, आप अपने सॉफ़्टवेयर और यूज़र एक्सपीरियंस पर ध्यान केंद्रित कर सकते हैं, और बुनियादी इंफ्रास्ट्रक्चर की चिंता नहीं करनी पड़ेगी।

इसके अतिरिक्त, PaaS आपके ऐप को मांग के अनुसार स्केल करने, बैकअप लेने आदि का ध्यान रखता है। इसकी कमियाँ यह हैं कि इसमें नियंत्रण कम होता है, वेंडर लॉक-इन का जोखिम रहता है, और लागत थोड़ी अधिक हो सकती है।

सबसे लोकप्रिय PaaS प्लेटफ़ॉर्म्स में Heroku, Render और Digital Ocean App Platform शामिल हैं।

बैकएंड ऐज़ अ सर्विस (BaaS)

बैकएंड ऐज़ अ सर्विस (BaaS) डेवलपमेंट के बैकएंड हिस्से को स्वचालित करके एक पूर्ण विकसित बैकएंड समाधान उपलब्ध कराता है।

BaaS की विशेषताओं में यूज़र मैनेजमेंट, डेटाबेस, ऑथेंटिकेशन, सोशल इंटीग्रेशन, पुश नोटिफिकेशन, APIs, SDKs और बहुत कुछ शामिल है।

BaaS आपको IaaS और PaaS दोनों के फायदे देता है, साथ ही अतिरिक्त सुविधाएँ भी प्रदान करता है। जो टीमें BaaS का उपयोग करती हैं, वे आमतौर पर अपने प्रोडक्ट को तेज़ी से रिलीज़ करती हैं, इंजीनियरिंग लागत कम करती हैं और बेहतर सॉफ़्टवेयर बनाती हैं।

BaaS की कमियों में कम नियंत्रण और कस्टमाइज़ेशन के विकल्प शामिल हैं, साथ ही यदि प्लेटफ़ॉर्म ओपन-सोर्स नहीं है, तो वेंडर लॉक-इन की संभावना भी रहती है।

BaaS के उदाहरणों में Back4app, AWS Amplify और Firebase शामिल हैं।

एंड्रॉइड ऐप के लिए बैकएंड कैसे बनाया जाए?

इस लेख के इस भाग में, हम देखेंगे कि Back4app आधारित बैकएंड ऐप कैसे बनाया जाए और इसे एंड्रॉइड ऐप्लिकेशन से कैसे कनेक्ट किया जाए।

जरूरी शर्तें (Prerequisites)

Back4app क्या है?

Back4app आधुनिक ऐप्लिकेशन के लिए बैकएंड बनाने और डेवलपमेंट प्रोसेस को तेज़ करने का एक बेहतरीन प्लेटफ़ॉर्म है।

यह यूज़र मैनेजमेंट, रियल-टाइम डेटाबेस, सोशल इंटीग्रेशन, क्लाउड कोड फ़ंक्शंस, पुश नोटिफिकेशन, API और बहुत कुछ जैसी सर्वर-साइड सुविधाओं से सुसज्जित आता है!

Back4app का उपयोग करके, आप अपने बैकएंड के अधिकांश काम को आउटसोर्स कर सकते हैं और अपने ऐप के महत्वपूर्ण पहलुओं पर ध्यान केंद्रित कर सकते हैं, तथा एंड्रॉइड ऐप बैकएंड डेवलपमेंट को तेज़ कर सकते हैं।

इससे आपको अपने बैकएंड की आंतरिक इंफ्रास्ट्रक्चर, सर्वर, स्केलिंग, रखरखाव आदि से निपटने की ज़रूरत नहीं पड़ेगी।

सबसे महत्वपूर्ण बात, Back4app एक मुफ्त टियर भी प्रदान करता है, जो प्लेटफ़ॉर्म का प्रयोग और परीक्षण करने के लिए बहुत अच्छा विकल्प है। जब आपका ऐप बड़ा होता है, तब आप मासिक शुल्क वाले प्रीमियम प्लान्स में अपग्रेड कर सकते हैं।

प्रोजेक्ट का परिचय

इस लेख में, हम एक साधारण नोट्स ऐप बनाएँगे। यह ऐप उपयोगकर्ताओं को नोट्स ऐड, एडिट और डिलीट करने की सुविधा देगा। नोट्स Back4app डेटाबेस में स्टोर किए जाएँगे और Parse SDK के माध्यम से मैनेज होंगे।

हम इस ऐप को Kotlin प्रोग्रामिंग लैंग्वेज का उपयोग करके बनाएँगे। UI के लिए, हम Jetpack Compose — एंड्रॉइड का आधुनिक UI टूलकिट — का प्रयोग करेंगे।

Back4app एंड्रॉइड नोट्स ऐप

Back4app ऐप बनाएँ

एंड्रॉइड ऐप के लिए बैकएंड बनाने का पहला चरण Back4app अकाउंट होना है। यदि आपके पास नहीं है, तो साइन अप कर लें।

Back4app अकाउंट में लॉग इन करते ही आपको ऐप व्यू पर रीडायरेक्ट किया जाएगा। “Build new app” पर क्लिक करके नई ऐप बनाने की प्रक्रिया शुरू करें।

Back4app Build New App

Back4app प्लेटफ़ॉर्म दो समाधान प्रदान करता है:

  1. बैकएंड ऐज़ अ सर्विस (BaaS) – एक मज़बूत बैकएंड समाधान
  2. कंटेनर्स ऐज़ अ सर्विस (CaaS) – कंटेनर्स (विशेषकर वेब एप्लिकेशन) को मैनेज करने के लिए प्लेटफ़ॉर्म

चूँकि हम मोबाइल ऐप के लिए बैकएंड बना रहे हैं, इसलिए हम “Backend as a Service” को चुनेंगे।

Back4app BaaS Solution

अपनी ऐप को कोई अच्छा-सा नाम दें, “NoSQL” को डेटाबेस के रूप में चुनें, और “Create” पर क्लिक करें। यह एंड्रॉइड ऐप का बैकएंड बनाने के लिए एक महत्वपूर्ण कदम है।

Back4app को आपकी ऐप के लिए आवश्यक सभी चीज़ें तैयार करने में थोड़ा समय लगेगा। इसमें डेटाबेस, यूज़र मैनेजमेंट, स्केलिंग, कॉन्फ़िगरेशन आदि शामिल हैं। जैसे ही आपकी ऐप तैयार हो जाएगी, आपको इसकी डेटाबेस व्यू पर रीडायरेक्ट कर दिया जाएगा।

Back4app Database View

डेटाबेस डिज़ाइन करें

आगे बढ़ते हैं और डेटाबेस डिज़ाइन करते हैं। यह एंड्रॉइड ऐप के लिए बैकएंड डेवलप करने के लिए ज़रूरी चरण है।

क्योंकि हम एक साधारण नोट्स ऐप बना रहे हैं, हमें केवल एक ही क्लास की ज़रूरत होगी। “Create a class” पर क्लिक करें, इस क्लास को Note नाम दें, “Public Read and Write” सक्षम करें और “Create class & add columns” पर क्लिक करें।

Back4app Create Database Class

इसके बाद, नई बनी क्लास में निम्नलिखित तीन फ़ील्ड जोड़ें:

+-------------+-------------+--------------------+----------+
| Data type   | Name        | Default value      | Required |
+-------------+-------------+--------------------+----------+
| String      | icon        | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+
| String      | title       | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+
| String      | content     | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+

अंत में, “Add row” बटन पर क्लिक करें और अपने डेटाबेस में कुछ नमूना डेटा डालें। यदि आपके पास कोई आइडिया नहीं है, तो आप इस डेटा डंप को भी इम्पोर्ट कर सकते हैं।

Back4app Populate Database

बहुत बढ़िया! बैकएंड का यह हिस्सा अब तैयार है।

फ़्रंटएंड कोड करें

इस लेख के इस भाग में, हम एक नई एंड्रॉइड ऐप को बूटस्ट्रैप करेंगे, ViewModel सेटअप करेंगे, UI इंप्लीमेंट करेंगे, Parse SDK इंस्टॉल व कॉन्फ़िगर करेंगे और अंत में Back4app रियल-टाइम डेटाबेस से डेटा फ़ेच करेंगे।

प्रोजेक्ट इनिशियलाइज़ करें

जैसा कि जरूरी शर्तों में बताया गया है, निम्न चरणों को पूरा करने के लिए आपके सिस्टम में Android Studio इंस्टॉल होना चाहिए। यदि यह इंस्टॉल नहीं है, तो इसे यहाँ से डाउनलोड करें।

सबसे पहले Android Studio खोलें और “New Project” बटन पर क्लिक करें।

Android Studio Index

अब “Empty Activity” प्रोजेक्ट टेम्प्लेट चुनें और “Next” पर क्लिक करें।

प्रोजेक्ट बनाने के लिए आपको एक नाम और पैकेज नेम देना होगा। सुझाव है कि प्रोजेक्ट का नाम AndroidApp रखें और पैकेज नेम के लिए रिवर्स डोमेन नेम का प्रयोग करें।

सभी सेटिंग करने के बाद “Finish” पर क्लिक करें।

Android Studio Project Settings

Android Studio को आवश्यक चीज़ों को तैयार करने में लगभग दो मिनट लगेंगे, जिसमें प्रोजेक्ट फ़ाइल स्ट्रक्चर बनाना, Gradle सेटअप, डिपेंडेंसी इंस्टॉल आदि शामिल हैं।

प्रोजेक्ट तैयार होने पर, MainActivity.kt पर जाएँ और उसकी सामग्री को निम्न कोड से बदल दें:

// app/src/main/java.<your_package_name>/MainActivity.kt

package <your.package.name>

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background,
                ) {
                    Text(text = "Back4app rocks!", fontSize = 18.sp)
                }
            }
        }
    }
}

ध्यान दें कि जहाँ भी <your_package_name> हो, वहाँ अपनी वास्तविक पैकेज नेम डालें।

अंत में, हरे प्ले बटन या Shift + F10 दबाकर ऐप रन करने का प्रयास करें। यदि सब सही है, तो एम्यूलेटर शुरू होगा और स्क्रीन पर “Back4app rocks” मैसेज दिखाई देगा।

Android First App

ViewModel

हम अपने ऐप का ग्लोबल स्टेट मैनेज करने के लिए ViewModel का उपयोग करेंगे। लेकिन उससे पहले, हमें Note नाम की एक डेटा क्लास बनानी होगी, जिसमें Back4app डेटाबेस में मौजूद वही ऐट्रीब्यूट्स हों।

Note नाम से एक डेटा क्लास बनाएँ:

// app/src/main/java.<your_package_name>/Note.kt

package <your.package.name>

data class Note(
    var objectId: String? = null,
    var icon: String,
    var title: String,
    var content: String,
) {
    companion object {
        fun generateObjectId(): String {
            val chars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
            return (1..10).map { chars.random() }.joinToString("")
        }
    }
}
  1. हमने generateObjectId() नाम का एक स्टैटिक मेथड परिभाषित किया है, जो Parse-जैसे ऑब्जेक्ट IDs जेनरेट करता है।
  2. objectId को नल योग्य (nullable) रखा गया है ताकि हम यह मान सकें कि अगर objectId == null, तो ऑब्जेक्ट अभी डेटाबेस में सेव नहीं हुआ है।

अगले चरण में, AppViewModel नाम की एक क्लास बनाएँ और इसमें निम्न कोड डालें:

// app/src/main/java.<your_package_name>/AppViewModel.kt

package <your.package.name>

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class AppViewModel : ViewModel() {
    val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf(
        "7IggsqFAKt" to Note(
            objectId = "7IggsqFAKt",
            icon = "\uD83D\uDE80",
            title = "Deploy app",
            content = "Go ahead and deploy your backend to Back4app.",
        ),
        "eFRNm0hTat" to Note(
            objectId = "eFRNm0hTat",
            icon = "\uD83C\uDFA8",
            title = "Design website",
            content = "Design the website for the conference.",
        ),
        "uC7hTQmG5F" to Note(
            objectId = "uC7hTQmG5F",
            icon = "\uD83D\uDC42",
            title = "Attend meeting",
            content = "Attend meeting with the team to discuss the conference.",
        ),
    ))

    companion object {
        @Volatile
        private var instance: AppViewModel? = null

        fun getInstance(): AppViewModel {
            return instance ?: synchronized(this) {
                instance ?: AppViewModel().also { instance = it }
            }
        }
    }
}
  1. हमने Compose के MutableState का उपयोग किया है ताकि डेटा बदलने पर UI अपडेट हो सके।
  2. MutableState एक Map का होस्ट करता है, जो objectId और Note को मैप करता है, और हमने इसे डिफ़ॉल्ट रूप से कुछ डाटा से भर दिया है।
  3. सुनिश्चित करने के लिए कि AppViewModel का सिर्फ़ एक ही इंस्टेंस मौजूद हो, हमने singleton pattern का उपयोग किया है।

अब हम अपनी ऐक्टिविटी में AppViewModel.getInstance() के माध्यम से AppViewModel के इंस्टेंस तक पहुँच पाएँगे।

मुख्य ऐक्टिविटी (Main Activity)

अब MainActivity.kt की सामग्री को बदलकर, नोट्स को प्रदर्शित करने की व्यवस्था करें:

// app/src/main/java.<your_package_name>/MainActivity.kt

package <your.package.name>

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    private val viewModel = AppViewModel.getInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val context = this as Context

        setContent {
            MainActivityContent(
                viewModel = viewModel,
                onNoteListItemClick = {
                    // TODO: Open note edit form
                },
                onNoteAddClick = {
                    // TODO: Open note create form
                },
            )
        }
    }
}

@Composable
fun MainActivityContent(
    viewModel: AppViewModel,
    onNoteListItemClick: (note: Note) -> Unit,
    onNoteAddClick: () -> Unit,
) {
    val notes = viewModel.notes.value
    MaterialTheme {
        Scaffold(
            topBar = { TopAppBar(title = { Text("My Notes") }) },
            floatingActionButton = {
                ExtendedFloatingActionButton(
                    onClick = { onNoteAddClick() },
                    icon = { Icon(Icons.Filled.Add, contentDescription = "Add") },
                    text = { Text("Add") }
                )
            },
        ) { contentPadding ->
            Box(modifier = Modifier.padding(contentPadding)) {
                NoteList(notes, onNoteListItemClick = { onNoteListItemClick(it) })
            }
        }
    }
}

@Composable
fun NoteListItem(note: Note, onNoteListItemClick: (note: Note) -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = { onNoteListItemClick(note) })
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(text = note.icon, fontSize = 32.sp, modifier = Modifier.size(48.dp))
        Spacer(modifier = Modifier.width(8.dp))
        Column {
            Text(text = note.title, fontSize = 18.sp)
            Spacer(modifier = Modifier.height(4.dp))
            Text(
                text = note.content,
                fontSize = 14.sp,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
            )
        }
    }
}

@Composable
fun NoteList(notes: Map<String, Note>, onNoteListItemClick: (note: Note) -> Unit) {
    LazyColumn {
        items(notes.entries.toList()) { (_, note) ->
            NoteListItem(note = note, onNoteListItemClick = onNoteListItemClick)
        }
    }
}
  1. notes अब AppViewModel से फ़ेच हो रही हैं।
  2. हमने क्लिक ईवेंट्स को Composable फ़ंक्शंस में परिभाषित करने की बजाय पैरामीटर के रूप में पास किया है।
  3. हमने Compose का उपयोग करके UI डिजाइन किया है। UI को और बेहतर बनाने के लिए MaterialTheme और Scaffold लेआउट का प्रयोग किया है।

यदि आप अब ऐप को रिबिल्ड करते हैं, तो स्क्रीन पर “हार्ड-कोडेड” नोट्स की लिस्ट दिखाई देगी।

Back4app एंड्रॉइड नोट्स ऐप लिस्ट

नोट फ़ॉर्म ऐक्टिविटी

इस सेक्शन में, हम एक नई ऐक्टिविटी जोड़ेंगे, जिससे यूज़र नोट्स को जोड़ (ऐड) और संपादित (एडिट) कर सकें।

पहले FormActivity नाम की क्लास बनाएँ और इसमें निम्न कोड डालें:

// app/src/main/java.<your_package_name>/FormActivity.kt

package <your.package.name>

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp

class FormActivity : ComponentActivity() {
    private val viewModel = AppViewModel.getInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val objectId = intent.getStringExtra("objectId")
        val note = if (objectId !== null) viewModel.notes.value[objectId] else null

        setContent {
            FormActivityContent(
                note,
                onNoteAddClick = { icon: String, title: String, content: String ->
                    if (note !== null) return@FormActivityContent
                    val newNote = Note(
                        icon = icon,
                        title = title,
                        content = content,
                    )
                    newNote.objectId = Note.generateObjectId()
                    viewModel.notes.value += (newNote.objectId!! to newNote)
                    finish()
                },
                onNoteSaveClick = { icon: String, title: String, content: String ->
                    if (note === null) return@FormActivityContent
                    val updatedNote = note.copy()
                    updatedNote.icon = icon
                    updatedNote.title = title
                    updatedNote.content = content
                    viewModel.notes.value += (updatedNote.objectId!! to updatedNote)
                    finish()
                },
                onNoteDeleteClick = {
                    if (note === null) return@FormActivityContent
                    viewModel.notes.value = viewModel.notes.value.filter {
                        it.value.objectId != note.objectId
                    }
                    finish()
                },
            )
        }
    }
}

@Composable
fun FormActivityContent(
    note: Note?,
    onNoteAddClick: (icon: String, title: String, content: String) -> Unit,
    onNoteSaveClick: (icon: String, title: String, content: String) -> Unit,
    onNoteDeleteClick: () -> Unit,
) {
    MaterialTheme {
        Scaffold(
            topBar = {
                TopAppBar(title = { Text(note?.let { "Edit Note" } ?: ("Add Note")) })
            },
            floatingActionButton = {
                if (note !== null) {
                    ExtendedFloatingActionButton(
                        onClick = { onNoteDeleteClick() },
                        icon = { Icon(Icons.Filled.Delete, "Delete") },
                        text = { Text("Delete") },
                    )
                }
            },
        ) { contentPadding ->
            Box(modifier = Modifier.padding(contentPadding)) {
                NoteForm(note = note, onNoteSave = { icon, title, content ->
                    if (note === null) {
                        onNoteAddClick(icon, title, content)
                    } else {
                        onNoteSaveClick(icon, title, content)
                    }
                })
            }
        }
    }
}

@Composable
fun NoteForm(
    note: Note?,
    onNoteSave: (icon: String, title: String, content: String) -> Unit
) {
    var icon by remember { mutableStateOf(TextFieldValue(note?.icon ?: "")) }
    var title by remember { mutableStateOf(TextFieldValue(note?.title ?: "")) }
    var content by remember { mutableStateOf(TextFieldValue(note?.content ?: "")) }
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        TextField(
            label = { Text(text = "Icon") },
            value = icon,
            onValueChange = { icon = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        TextField(
            label = { Text(text = "Title") },
            value = title,
            onValueChange = { title = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        TextField(
            label = { Text(text = "Content") },
            value = content,
            onValueChange = { content = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = { onNoteSave(icon.text, title.text, content.text) },
            Modifier.fillMaxWidth()
        ) {
            Text(text = "Save")
        }
    }
}
  1. यह फ़ॉर्म नोट को ऐड और एडिट दोनों के लिए काम करता है। हम objectId == null की तुलना करके ऐक्शन निर्धारित करते हैं। यदि null है, तो यह “ऐड” ऐक्शन है, अन्यथा “एडिट” ऐक्शन।
  2. यदि objectId !== null है, तो हम note को स्टेट से फ़ेच करके फ़ॉर्म में भरते हैं।
  3. Compose के MutableState को सही से काम करने के लिए, हमने इसकी सामग्री को इनम्यूटेबल माना है। यही कारण है कि हमने कभी-कभी सामग्री को कॉपी किया है बजाय सीधे बदलने के।
  4. Compose फ़ॉर्म स्टेट हैंडल करने के लिए हमने mutableStateOf() का उपयोग किया है।

अब AndroidManifest.xml के application टैग में FormActivity को रजिस्टर करें:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application>
        <!-- ... -->
        <activity android:name=".FormActivity"/>
    </application>

</manifest>

अंत में, MainActivity.kt में onNoteListItemClick और onNoteAddClick के अंदर एक नया Intent बनाएँ:

// app/src/main/java.<your_package_name>/MainActivity.kt

class MainActivity : ComponentActivity() {
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        setContent {
            MainActivityContent(
                viewModel = viewModel,
                onNoteListItemClick = {
                    // triggers the edit action, since `objectId` is provided
                    val intent = Intent(context, FormActivity::class.java)
                    intent.putExtra("objectId", it.objectId)
                    context.startActivity(intent)
                },
                onNoteAddClick = {
                    // triggers the add action, since no `objectId` is present
                    val intent = Intent(context, FormActivity::class.java)
                    context.startActivity(intent)
                },
            )
        }
    }
}

फ़ाइल के ऊपर Intent को इम्पोर्ट करना न भूलें:

import android.content.Intent

यदि आप अब ऐप को रिबिल्ड करेंगे, तो नोट्स ऐड करने, उन्हें एडिट करने और डिलीट करने का विकल्प वाला एक काम करता हुआ ऐप आपके पास होगा।

एकमात्र समस्या यह है कि ऐप रीस्टार्ट करने पर स्टेट रीसेट हो जाता है (जैसा कि शुरुआत में “हार्ड-कोडेड” नोट्स थे) ।

अगले सेक्शन में, हम ऐप को Back4app बैकएंड से कनेक्ट करेंगे। इससे हमारा डेटा स्थायी रूप से सेव हो जाएगा और कई डिवाइसों पर सिंक भी हो पाएगा।

Android Notes App Edit Preview

Parse SDK इंस्टॉल करें

जैसा कि आप जानते हैं, Back4app Parse प्लेटफ़ॉर्म पर आधारित है। यदि हमें Back4app डेटाबेस या Back4app से किसी भी तरह का इंटरेक्शन करना है, तो हमें Parse SDK इंस्टॉल करना होगा।

सबसे पहले, settings.gradle में JitPack रिपॉज़िटरी जोड़ें:

// settings.gradle

pluginManagement {
    repositories {
        // ...
        maven { url "https://jitpack.io" }
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        // ...
        maven { url "https://jitpack.io" }
    }
}

इसके बाद, ऐप-स्तरीय build.gradle में Android Parse SDK जोड़ें:

// app/build.gradle

dependencies {
    // ...
    implementation "com.github.parse-community.Parse-SDK-Android:parse:4.2.0"
}

Gradle सेटिंग्स को सिंक करें और सुनिश्चित करें कि कोई त्रुटि न हो।

Parse SDK कॉन्फ़िगर करें

Back4app बैकएंड से कनेक्ट होने के लिए, आपको Parse SDK को अपना ऐप्लिकेशन आईडी और क्लाइंट की देनी होगी। ये क्रेडेंशियल्स प्राप्त करने के लिए अपने Back4app ऐप में जाएँ और साइडबार में “App Settings > Security & Keys” चुनें।

फिर उन्हें strings.xml में नीचे दिखाए अनुसार डालें:

<!-- app/src/main/res/values/strings.xml -->

<resources>
    <string name="app_name">back4app-android-app</string>
    <string name="back4app_server_url">https://parseapi.back4app.com/</string>
    <string name="back4app_app_id">your_parse_app_id</string>
    <string name="back4app_client_key">your_parse_client_key</string>
</resources>

ध्यान दें कि your_parse_app_id और your_parse_client_key को अपने वास्तविक क्रेडेंशियल से बदलें।

इसके बाद, AndroidManifest.xml में इंटरनेट एक्सेस सक्षम करने और क्रेडेंशियल मेटाडेटा अटैच करने के लिए निम्न परिवर्तन करें:

<!-- app/src/main/AndroidManifest.xml -->

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- ये दो परमिशन इंटरनेट एक्सेस सक्षम करते हैं -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application>
        <!-- ... -->

        <!-- नया जोड़ा गया मेटाडेटा -->
        <meta-data
            android:name="com.parse.SERVER_URL"
            android:value="@string/back4app_server_url" />
        <meta-data
            android:name="com.parse.APPLICATION_ID"
            android:value="@string/back4app_app_id" />
        <meta-data
            android:name="com.parse.CLIENT_KEY"
            android:value="@string/back4app_client_key" />
    </application>

</manifest>

अंत में, Parse को इनिशियलाइज़ करना होगा। यह सुनिश्चित करने के लिए कि Parse किसी भी ऐक्टिविटी से पहले इनिशियलाइज़ हो, हम Application क्लास से इनहेरिट करने वाली एक नई क्लास App बनाएँगे।

App.kt बनाएँ और Parse को इस तरह इनिशियलाइज़ करें:

// app/src/main/java/<your_package_name>/App.kt

package <your.package.name>

import android.app.Application
import com.parse.Parse

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        Parse.initialize(
            Parse.Configuration.Builder(this)
                .applicationId(getString(R.string.back4app_app_id))
                .clientKey(getString(R.string.back4app_client_key))
                .server(getString(R.string.back4app_server_url))
                .build()
        )
    }
}

इसके बाद, AndroidManifest.xml में App क्लास को रजिस्टर करें:

<!-- app/src/main/AndroidManifest.xml -->

<application
    android:name=".App"
    ...
>
    <!-- ... -->
</application>

एक बार फिर ऐप को रिबिल्ड करें और Logcat विंडो में देखें कि कोई त्रुटि तो नहीं है। अगर त्रुटि नहीं आती, तो समझिए कि Back4app से कनेक्शन सफल है।

Back4app से नोट्स लोड करें

अंत में, हमारा ऐप लगभग तैयार है। अब हम Back4app डेटाबेस से नोट्स लोड करके देखेंगे कि Parse का उपयोग कैसे किया जाता है।

सबसे पहले AppViewModel में जाएँ। वहाँ मौजूद मैप से डेटा हटा दें और init ब्लॉक जोड़ें:

// app/src/main/java/<your_package_name>/AppViewModel.kt

package <your.package.name>

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class AppViewModel : ViewModel() {
    val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf())

    init {
        val query = com.parse.ParseQuery.getQuery<com.parse.ParseObject>("Note")
        query.orderByDescending("createdAt")
        query.findInBackground { notes, e ->
            if (e == null) {
                for (parseNote in notes) {
                    val note = Note(
                        objectId = parseNote.objectId,
                        icon = parseNote.getString("icon")!!,
                        title = parseNote.getString("title")!!,
                        content = parseNote.getString("content")!!,
                    )
                    this.notes.value += (note.objectId!! to note)
                }
            } else {
                println("Error: ${e.message}")
            }
        }
    }

    companion object {
        // ...
    }
}

उपरोक्त कोड Parse SDK का उपयोग करके नोट्स को डेटाबेस से फ़ेच करता है, उन्हें Note डेटा क्लास में बदलता है और मैप में सेव कर देता है।

अब Note में तीन नए मेथड जोड़ें:

// app/src/main/java/<your_package_name>/Note.kt

package <your.package.name>

import com.parse.ParseObject
import com.parse.ParseQuery

data class Note(
    var objectId: String? = null,
    var icon: String,
    var title: String,
    var content: String,
) {
    fun addToParse(callback: (objectId: String) -> Unit) {
        if (objectId !== null) throw Exception("Note is already saved to Parse!")

        val parseNote = ParseObject("Note")
        parseNote.put("icon", icon)
        parseNote.put("title", title)
        parseNote.put("content", content)

        parseNote.saveInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            objectId = parseNote.objectId
            callback(parseNote.objectId)
        }
    }

    fun updateToParse(callback: (objectId: String) -> Unit) {
        if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")

        val query = ParseQuery.getQuery<ParseObject>("Note")
        val parseNote = query.get(objectId)
        parseNote.put("icon", icon)
        parseNote.put("title", title)
        parseNote.put("content", content)

        parseNote.saveInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            callback(parseNote.objectId)
        }
    }

    fun deleteFromParse(callback: () -> Unit) {
        if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")

        val query = ParseQuery.getQuery<ParseObject>("Note")
        val parseNote = query.get(objectId)
        parseNote.deleteInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            callback()
        }
    }
}
  1. addToParse() नए नोट को Parse सर्वर पर सेव करता है। सफलता पर उस नोट का यूनिक आइडेंटिफ़ायर (objectId) संभाल कर कॉलबैक को सूचित करता है।
  2. updateToParse() पहले से मौजूद नोट की जानकारी को Parse सर्वर पर अपडेट करता है। सफल होने पर कॉलबैक को सूचित करता है।
  3. deleteFromParse() पहले से सेव किए गए नोट को Parse सर्वर से डिलीट करता है। सफल होने पर यह कॉलबैक को सूचित करता है।

अंत में, FormActivity में onNoteAddClick, onNoteSaveClick और onNoteDeleteClick को अपडेट करें ताकि वे इन नए मेथड्स का उपयोग कर सकें:

// app/src/main/java.<your_package_name>/NoteFormActivity.kt

class FormActivity : ComponentActivity() {
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        setContent {
            FormActivityContent(
                note,
                onNoteAddClick = { icon: String, title: String, content: String ->
                    if (note !== null) return@FormActivityContent
                    val newNote = Note(
                        icon = icon,
                        title = title,
                        content = content,
                    )
                    newNote.addToParse {
                        viewModel.notes.value += (it to newNote)
                        finish()
                    }
                },
                onNoteSaveClick = { icon: String, title: String, content: String ->
                    if (note === null) return@FormActivityContent
                    val updatedNote = note.copy()
                    updatedNote.icon = icon
                    updatedNote.title = title
                    updatedNote.content = content
                    updatedNote.updateToParse {
                        viewModel.notes.value += (it to updatedNote)
                        finish()
                    }
                },
                onNoteDeleteClick = {
                    if (note === null) return@FormActivityContent
                    viewModel.notes.value = viewModel.notes.value.filter {
                        it.value.objectId != note.objectId
                    }
                    note.deleteFromParse {
                        finish()
                    }
                },
            )
        }
    }
}

बस हो गया!

अब आपका ऐप पूरी तरह से काम कर रहा है और Back4app बैकएंड से सिंक हो चुका है। नोट्स में बदलाव करें और देखें कि ये बदलाव आपके Back4app डेटाबेस व्यू में रिफ्लेक्ट हो रहे हैं या नहीं।

निष्कर्ष

इस लेख में, हमने एक मोबाइल बैकएंड बनाया और उसे अपनी एंड्रॉइड ऐप से कनेक्ट किया। बैकएंड के लिए हमने Back4app के BaaS सॉल्यूशन का उपयोग किया, जबकि फ़्रंटएंड पर Kotlin और Jetpack Compose इस्तेमाल किया।

अब तक, आपको मोबाइल बैकएंड की मूल बातें समझ में आ गई होंगी और आप अपना खुद का बैकएंड बनाने में सक्षम होंगे। अंतिम सोर्स कोड देखने के लिए back4app-android-app रिपोजिटरी देखें।


Leave a reply

Your email address will not be published.