इन्फ़ॉर्मेशन आर्किटेक्चर

Android 8.0 में, सेटिंग ऐप्लिकेशन के लिए एक नया जानकारी आर्किटेक्चर जोड़ा गया है. इससे, सेटिंग को व्यवस्थित करने का तरीका आसान हो गया है. साथ ही, उपयोगकर्ताओं को अपने Android डिवाइसों को पसंद के मुताबिक बनाने के लिए, सेटिंग को तुरंत ढूंढने में आसानी हुई है. Android 9 में कुछ सुधार किए गए हैं, ताकि सेटिंग में ज़्यादा सुविधाएं मिल सकें और उन्हें आसानी से लागू किया जा सके.

उदाहरण और सोर्स

फ़िलहाल, सेटिंग के ज़्यादातर पेजों को नए फ़्रेमवर्क का इस्तेमाल करके लागू किया गया है. DisplaySettings एक अच्छा उदाहरण है:packages/apps/Settings/src/com/android/settings/DisplaySettings.java

अहम कॉम्पोनेंट के लिए फ़ाइल पाथ यहां दिए गए हैं:

  • CategoryKey: packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
  • DashboardFragmentRegistry: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
  • DashboardFragment: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
  • AbstractPreferenceController: frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (Android 9 में जोड़ा गया): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

लागू करना

डिवाइस बनाने वाली कंपनियों को, सेटिंग की मौजूदा जानकारी के स्ट्रक्चर में बदलाव करने और ज़रूरत के हिसाब से सेटिंग के अतिरिक्त पेज जोड़ने का सुझाव दिया जाता है. इससे पार्टनर की खास सुविधाओं को शामिल किया जा सकता है. प्राथमिकताओं को लेगसी पेज (SettingsPreferencePage के तौर पर लागू किया गया) से नए पेज (DashboardFragment का इस्तेमाल करके लागू किया गया) पर ले जाना मुश्किल हो सकता है. ऐसा हो सकता है कि लेगसी पेज की प्राथमिकता को PreferenceController के साथ लागू न किया गया हो.

इसलिए, किसी लेगसी पेज से किसी नए पेज पर प्राथमिकताएं ले जाते समय, आपको एक PreferenceController बनाना होगा और कोड को नए DashboardFragment में इंस्टैंशिएट करने से पहले, उसे कंट्रोलर में ले जाना होगा. PreferenceController को जिन एपीआई की ज़रूरत है उनके नाम और Javadoc में उनके बारे में जानकारी दी गई है.

हमारा सुझाव है कि हर PreferenceController के लिए यूनिट टेस्ट जोड़ें. अगर बदलाव AOSP को सबमिट किया जाता है, तो यूनिट टेस्ट करना ज़रूरी है. Robolectric पर आधारित टेस्ट लिखने के तरीके के बारे में ज़्यादा जानने के लिए, readme फ़ाइल packages/apps/Settings/tests/robotests/README.md देखें.

प्लग इन-स्टाइल इन्फ़ॉर्मेशन आर्किटेक्चर

सेटिंग के हर आइटम को प्राथमिकता के तौर पर लागू किया जाता है. किसी प्राथमिकता को एक पेज से दूसरे पेज पर आसानी से ले जाया जा सकता है.

एक से ज़्यादा सेटिंग को आसानी से एक से दूसरी जगह ले जाने के लिए, Android 8.0 में प्लग इन स्टाइल का होस्ट फ़्रैगमेंट जोड़ा गया है. इसमें सेटिंग आइटम होते हैं. सेटिंग आइटम को प्लग इन स्टाइल वाले कंट्रोलर के तौर पर मॉडल किया जाता है. इसलिए, सेटिंग पेज को एक होस्ट फ़्रैगमेंट और कई सेटिंग कंट्रोलर से बनाया जाता है.

DashboardFragment

DashboardFragment, प्लग इन-स्टाइल के प्रॉपर्टी कंट्रोलर का होस्ट है. फ़्रैगमेंट, PreferenceFragment से इनहेरिट करता है. साथ ही, इसमें स्टैटिक और डाइनैमिक, दोनों तरह की प्राथमिकता सूचियों को बड़ा करने और अपडेट करने के लिए हुक होते हैं.

स्टैटिक सेटिंग

स्टैटिक प्राथमिकता सूची को एक्सएमएल में <Preference> टैग का इस्तेमाल करके तय किया जाता है. DashboardFragment लागू करने के लिए, getPreferenceScreenResId() तरीके का इस्तेमाल करके यह तय किया जाता है कि किस एक्सएमएल फ़ाइल में, दिखाने के लिए प्राथमिकताओं की स्टैटिक सूची शामिल है.

डाइनैमिक प्राथमिकताएं

डाइनैमिक आइटम, इंटेंट वाली टाइल को दिखाता है, जिससे बाहरी या अंदरूनी ऐक्टिविटी शुरू होती है. आम तौर पर, इंटेंट से किसी दूसरे सेटिंग पेज पर पहुंचा जाता है. उदाहरण के लिए, सेटिंग के होम पेज पर मौजूद "Google" सेटिंग आइटम, डाइनैमिक आइटम है. डाइनैमिक आइटम, AndroidManifest में तय किए जाते हैं (इसके बारे में नीचे बताया गया है). साथ ही, इन्हें FeatureProvider ( DashboardFeatureProvider के तौर पर तय किया गया) के ज़रिए लोड किया जाता है.

स्टैटिक तौर पर कॉन्फ़िगर की गई सेटिंग की तुलना में, डाइनैमिक सेटिंग ज़्यादा हेवी होती हैं. इसलिए, आम तौर पर डेवलपर को सेटिंग को स्टैटिक तौर पर लागू करना चाहिए. हालांकि, डाइनैमिक सेटिंग तब काम की हो सकती है, जब इनमें से कोई भी बात सही हो:

  • सेटिंग को सीधे तौर पर Settings ऐप्लिकेशन में लागू नहीं किया गया है. जैसे, OEM/कैरियर ऐप्लिकेशन की लागू की गई सेटिंग को इंजेक्ट करना.
  • यह सेटिंग, सेटिंग के होम पेज पर दिखेगी.
  • आपके पास सेटिंग के लिए पहले से ही कोई गतिविधि है और आपको अतिरिक्त स्टैटिक कॉन्फ़िगरेशन लागू नहीं करना है.

किसी गतिविधि को डाइनैमिक सेटिंग के तौर पर कॉन्फ़िगर करने के लिए, यह तरीका अपनाएं:

  • गतिविधि में इंटेंट-फ़िल्टर जोड़कर, गतिविधि को डाइनैमिक सेटिंग के तौर पर मार्क करें.
  • सेटिंग ऐप्लिकेशन को बताएं कि वह किस कैटगरी का है. कैटगरी एक कॉन्स्टेंट है, जिसे CategoryKey में तय किया गया है.
  • ज़रूरी नहीं: सेटिंग दिखने पर, खास जानकारी वाला टेक्स्ट जोड़ें.

यहां DisplaySettings के लिए, सेटिंग ऐप्लिकेशन से लिया गया एक उदाहरण दिया गया है.

<activity android:name="Settings$DisplaySettingsActivity"
                   android:label="@string/display_settings"
                   android:icon="@drawable/ic_settings_display">
             <!-- Mark the activity as a dynamic setting -->
              <intent-filter>
                     <action android:name="com.android.settings.action.IA_SETTINGS" />
              </intent-filter>
             <!-- Tell Settings app which category it belongs to -->
              <meta-data android:name="com.android.settings.category"
                     android:value="com.android.settings.category.ia.homepage" />
             <!-- Add a summary text when the setting is displayed -->
              <meta-data android:name="com.android.settings.summary"
                     android:resource="@string/display_dashboard_summary"/>
             </activity>

रेंडर करने के समय, फ़्रैगमेंट AndroidManifest में बताई गई स्टैटिक एक्सएमएल और डाइनैमिक सेटिंग, दोनों से प्राथमिकताओं की सूची मांगेगा. PreferenceController को Java कोड या एक्सएमएल में तय किया गया हो, DashboardFragment हर सेटिंग को मैनेज करने के लॉजिक को PreferenceController के ज़रिए मैनेज करता है. इस बारे में यहां बताया गया है. इसके बाद, उन्हें यूज़र इंटरफ़ेस (यूआई) में, अलग-अलग तरह की सूची के तौर पर दिखाया जाता है.

PreferenceController

इस सेक्शन में बताया गया है कि Android 9 और Android 8.x में PreferenceController को लागू करने के तरीके अलग-अलग हैं.

Android 9 रिलीज़ में PreferenceController

PreferenceController में, प्राथमिकता के साथ इंटरैक्ट करने के लिए सभी लॉजिक होते हैं. जैसे, दिखाना, अपडेट करना, खोज को इंडेक्स करना वगैरह.

PreferenceController के इंटरफ़ेस को BasePreferenceController के तौर पर परिभाषित किया गया है. उदाहरण के लिए, packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java में कोड देखें

BasePreferenceController के कई सबक्लास हैं. हर सबक्लास, किसी खास यूज़र इंटरफ़ेस (यूआई) स्टाइल से मैप होता है. Settings ऐप्लिकेशन में, डिफ़ॉल्ट रूप से यह स्टाइल काम करता है. उदाहरण के लिए, TogglePreferenceController में एक एपीआई है जो सीधे तौर पर यह मैप करता है कि उपयोगकर्ता को टॉगल पर आधारित प्राथमिकता वाले यूज़र इंटरफ़ेस (यूआई) के साथ कैसे इंटरैक्ट करना चाहिए.

BasePreferenceController में getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(), जैसे एपीआई हैं. हर एपीआई के बारे में ज़्यादा जानकारी देने वाला दस्तावेज़, इंटरफ़ेस क्लास में मौजूद होता है.

BasePreferenceController (और TogglePreferenceController जैसे इसके सबक्लास) को लागू करने पर यह पाबंदी है कि कंस्ट्रक्टर हस्ताक्षर, इनमें से किसी एक से मेल खाना चाहिए:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

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

DashboardFragment, स्क्रीन पर PreferenceController की सूची रखता है. फ़्रैगमेंट के onCreate() में, getAvailabilityStatus() तरीके के लिए सभी कंट्रोलर को कॉल किया जाता है. अगर यह सही वैल्यू दिखाता है, तो डिसप्ले लॉजिक को प्रोसेस करने के लिए displayPreference() को कॉल किया जाता है. getAvailabilityStatus() सेटिंग फ़्रेमवर्क को यह बताना भी ज़रूरी है कि खोज के दौरान कौनसे आइटम उपलब्ध हैं.

Android 8.x रिलीज़ में PreferenceController

PreferenceController में, प्राथमिकता के साथ इंटरैक्ट करने के लिए सभी लॉजिक होते हैं. जैसे, दिखाना, अपडेट करना, खोज को इंडेक्स करना वगैरह.

प्राथमिकता के इंटरैक्शन के हिसाब से, PreferenceController के इंटरफ़ेस में एपीआई isAvailable(), displayPreference(), handlePreferenceTreeClicked() वगैरह होते हैं. इंटरफ़ेस क्लास में, हर एपीआई के बारे में ज़्यादा जानकारी वाला दस्तावेज़ मिल सकता है.

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

DashboardFragment, स्क्रीन पर PreferenceControllers की सूची रखता है. फ़्रैगमेंट के onCreate() में, isAvailable() मेथड के लिए सभी कंट्रोलर को कॉल किया जाता है. अगर यह सही वैल्यू दिखाता है, तो डिसप्ले लॉजिक को प्रोसेस करने के लिए displayPreference() को कॉल किया जाता है.

DashboardFragment का इस्तेमाल करना

किसी प्राथमिकता को पेज A से पेज B पर ले जाना

अगर प्राथमिकता, ओरिजनल पेज की प्राथमिकता एक्सएमएल फ़ाइल में स्टैटिक तौर पर दी गई है, तो अपनी Android रिलीज़ के लिए, स्टैटिक तरीके से ट्रांसफ़र करने का तरीका यहां दिया गया है. इसके अलावा, अपनी Android रिलीज़ के लिए, डाइनैमिक तरीके से माइग्रेट करने का तरीका अपनाएं.

Android 9 में स्टैटिक मूव

  1. ओरिजनल पेज और डेस्टिनेशन पेज के लिए, प्राथमिकता वाली एक्सएमएल फ़ाइलें ढूंढें. आपको यह जानकारी, पेज के getPreferenceScreenResId() तरीके से मिल सकती है.
  2. ओरिजनल पेज के एक्सएमएल से प्राथमिकता हटाएं.
  3. डेस्टिनेशन पेज के एक्सएमएल में प्राथमिकता जोड़ें.
  4. मूल पेज के Java लागू करने से, इस प्राथमिकता के लिए PreferenceController हटाएं. आम तौर पर, यह createPreferenceControllers() में होता है. कंट्रोलर को सीधे तौर पर एक्सएमएल में एलान किया जा सकता है.

    ध्यान दें: ऐसा हो सकता है कि प्राथमिकता में PreferenceController न हो.

  5. डेस्टिनेशन पेज के createPreferenceControllers() में PreferenceController को इंस्टैंशिएट करें. अगर PreferenceController को पुराने पेज में एक्सएमएल में तय किया गया है, तो इसे नए पेज के लिए भी एक्सएमएल में तय करें.

Android 9 में डाइनैमिक मूव

  1. पता लगाएं कि ओरिजनल और डेस्टिनेशन पेज, किस कैटगरी के होस्ट हैं. यह जानकारी DashboardFragmentRegistry में देखी जा सकती है.
  2. वह AndroidManifest.xml फ़ाइल खोलें जिसमें वह सेटिंग है जिसे आपको एक से दूसरी जगह ले जाना है. इसके बाद, इस सेटिंग को दिखाने वाली गतिविधि की एंट्री ढूंढें.
  3. com.android.settings.category के लिए गतिविधि की मेटाडेटा वैल्यू को नए पेज की कैटगरी कुंजी पर सेट करें.

Android 8.x रिलीज़ में स्टैटिक मूव

  1. ओरिजनल पेज और डेस्टिनेशन पेज के लिए, प्राथमिकता वाली एक्सएमएल फ़ाइलें ढूंढें.
  2. आपको यह जानकारी, पेज के getPreferenceScreenResId() तरीके से मिल सकती है.
  3. ओरिजनल पेज के एक्सएमएल में से प्राथमिकता हटाएं.
  4. डेस्टिनेशन पेज के एक्सएमएल में प्राथमिकता जोड़ें.
  5. मूल पेज के Java लागू करने के तरीके में, इस प्राथमिकता के लिए PreferenceController हटाएं. आम तौर पर, यह getPreferenceControllers() में होता है.
  6. ध्यान दें: ऐसा हो सकता है कि प्राथमिकता में PreferenceController न हो.

  7. डेस्टिनेशन पेज के getPreferenceControllers() में PreferenceController को इंस्टैंशिएट करें.

Android 8.x रिलीज़ में डाइनैमिक मूव

  1. पता लगाएं कि ओरिजनल और डेस्टिनेशन पेज, किस कैटगरी के होस्ट हैं. यह जानकारी DashboardFragmentRegistry में देखी जा सकती है.
  2. वह AndroidManifest.xml फ़ाइल खोलें जिसमें वह सेटिंग है जिसे आपको एक से दूसरी जगह ले जाना है. इसके बाद, इस सेटिंग की जानकारी देने वाली गतिविधि की एंट्री ढूंढें.
  3. com.android.settings.category के लिए गतिविधि की मेटाडेटा वैल्यू बदलें और वैल्यू पॉइंट को नए पेज की कैटगरी कुंजी पर सेट करें.

किसी पेज में नई प्राथमिकता बनाना

अगर प्राथमिकता, ओरिजनल पेज की प्राथमिकता एक्सएमएल फ़ाइल में स्टैटिक तौर पर दी गई है, तो नीचे दिया गया स्टैटिक तरीका अपनाएं. अगर ऐसा नहीं है, तो डाइनैमिक प्रोसेस अपनाएं.

स्टैटिक प्राथमिकता बनाना

  1. पेज के लिए प्राथमिकता एक्सएमएल फ़ाइलें ढूंढें. आपको यह जानकारी, पेज के getPreferenceScreenResId() तरीके से मिल सकती है.
  2. एक्सएमएल में एक नया Preference आइटम जोड़ें. पक्का करें कि उसमें यूनीक android:key हो.
  3. पेज के getPreferenceControllers() तरीके में, इस प्राथमिकता के लिए कोई PreferenceController तय करें.
    • Android 8.x और Android 9 में, पेज के createPreferenceControllers() तरीके में इस प्राथमिकता के लिए PreferenceController को इंस्टैंशिएट करें. हालांकि, Android 9 में ऐसा करना ज़रूरी नहीं है.

      अगर यह प्राथमिकता पहले से ही दूसरी जगहों पर मौजूद थी, तो हो सकता है कि उसके लिए पहले से ही कोई PreferenceController मौजूद हो. नया PreferenceController बनाए बिना, उसका फिर से इस्तेमाल किया जा सकता है.

    • Android 9 से, प्राथमिकता के बगल में एक्सएमएल में PreferenceController का एलान करने का विकल्प चुना जा सकता है. उदाहरण के लिए:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>

डाइनैमिक प्राथमिकता बनाना

  1. पता लगाएं कि ओरिजनल और डेस्टिनेशन पेज, किस कैटगरी के होस्ट हैं. यह जानकारी DashboardFragmentRegistry में देखी जा सकती है.
  2. AndroidManifest में नई गतिविधि बनाना
  3. सेटिंग तय करने के लिए, नई गतिविधि में ज़रूरी मेटाडेटा जोड़ें. com.android.settings.category के लिए मेटाडेटा की वैल्यू को, पहले चरण में बताई गई वैल्यू पर सेट करें.

एक नया पेज बनाएं

  1. DashboardFragment से इनहेरिट करके नया फ़्रैगमेंट बनाएं.
  2. DashboardFragmentRegistry में इसकी कैटगरी तय करें.

    ध्यान दें: यह चरण ज़रूरी नहीं है. अगर आपको इस पेज पर कोई डाइनैमिक प्राथमिकता नहीं चाहिए, तो आपको कैटगरी कुंजी देने की ज़रूरत नहीं है.

  3. इस पेज के लिए ज़रूरी सेटिंग जोड़ने के लिए, यह तरीका अपनाएं. ज़्यादा जानकारी के लिए, लागू करना सेक्शन देखें.

पुष्टि करें

  • सेटिंग में जाकर, Robolectric टेस्ट चलाएं. सभी मौजूदा और नए टेस्ट पास होने चाहिए.
  • सेटिंग को बनाएं और इंस्टॉल करें. इसके बाद, जिस पेज में बदलाव करना है उसे मैन्युअल तरीके से खोलें. पेज तुरंत अपडेट हो जाना चाहिए.