एक आसान विजेट बनाएं

Compose को आज़माएं
Android के लिए, Jetpack Compose को यूज़र इंटरफ़ेस (यूआई) टूलकिट के तौर पर इस्तेमाल करने का सुझाव दिया जाता है. Compose-style API का इस्तेमाल करके विजेट बनाने का तरीका जानें.

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

संगीत विजेट का उदाहरण
पहली इमेज. संगीत विजेट का उदाहरण.

इस दस्तावेज़ में, विजेट उपलब्ध कराने वाली कंपनी का इस्तेमाल करके विजेट पब्लिश करने का तरीका बताया गया है. ऐप्लिकेशन विजेट को होस्ट करने के लिए, खुद का AppWidgetHost बनाने के बारे में जानकारी पाने के लिए, विजेट होस्ट बनाना लेख पढ़ें.

विजेट डिज़ाइन करने के तरीके के बारे में जानने के लिए, ऐप्लिकेशन विजेट की खास जानकारी देखें.

विजेट कॉम्पोनेंट

विजेट बनाने के लिए, आपको इन बुनियादी कॉम्पोनेंट की ज़रूरत होगी:

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

दूसरी इमेज में दिखाया गया है कि ये कॉम्पोनेंट, ऐप्लिकेशन विजेट की प्रोसेसिंग के पूरे फ़्लो में कैसे काम करते हैं.

ऐप्लिकेशन के विजेट को प्रोसेस करने का फ़्लो
दूसरी इमेज. ऐप्लिकेशन विजेट के डेटा को प्रोसेस करने का फ़्लो.

अगर आपके विजेट को उपयोगकर्ता के कॉन्फ़िगरेशन की ज़रूरत है, तो ऐप्लिकेशन विजेट कॉन्फ़िगरेशन गतिविधि लागू करें. इस गतिविधि की मदद से, उपयोगकर्ता विजेट की सेटिंग में बदलाव कर सकते हैं. उदाहरण के लिए, घड़ी वाले विजेट के लिए टाइम ज़ोन.

हम यहां दिए गए सुधारों को भी लागू करने का सुझाव देते हैं: विजेट के लेआउट में बदलाव करने की सुविधा, अन्य सुधार, ऐडवांस विजेट, कलेक्शन विजेट, और विजेट होस्ट बनाना.

AppWidgetProviderInfo एक्सएमएल का एलान करना

AppWidgetProviderInfo ऑब्जेक्ट, किसी विजेट की ज़रूरी क्वालिटी के बारे में बताता है. एक <appwidget-provider> एलिमेंट का इस्तेमाल करके, एक्सएमएल रिसॉर्स फ़ाइल में AppWidgetProviderInfo ऑब्जेक्ट तय करें. इसके बाद, इसे प्रोजेक्ट के res/xml/ फ़ोल्डर में सेव करें.

इसे यहां दिए गए उदाहरण में दिखाया गया है:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:targetCellWidth="1"
    android:targetCellHeight="1"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="120dp"
    android:updatePeriodMillis="86400000"
    android:description="@string/example_appwidget_description"
    android:previewLayout="@layout/example_appwidget_preview"
    android:initialLayout="@layout/example_loading_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

विजेट के साइज़ से जुड़े एट्रिब्यूट

डिफ़ॉल्ट होम स्क्रीन, विजेट को अपनी विंडो में सेल की ग्रिड के आधार पर रखती है. इन सेल की ऊंचाई और चौड़ाई तय होती है. ज़्यादातर होम स्क्रीन पर, विजेट को सिर्फ़ ऐसे साइज़ में रखा जा सकता है जो ग्रिड सेल के पूर्णांक गुणक होते हैं. उदाहरण के लिए, दो सेल हॉरिज़ॉन्टल और तीन सेल वर्टिकल.

विजेट के साइज़ के एट्रिब्यूट की मदद से, अपने विजेट के लिए डिफ़ॉल्ट साइज़ तय किया जा सकता है. साथ ही, विजेट के साइज़ की निचली और ऊपरी सीमाएं तय की जा सकती हैं. इस संदर्भ में, विजेट के डिफ़ॉल्ट साइज़ का मतलब उस साइज़ से है जो विजेट को होम स्क्रीन पर पहली बार जोड़ने पर मिलता है.

यहां दी गई टेबल में, विजेट के साइज़ से जुड़े <appwidget-provider> एट्रिब्यूट के बारे में बताया गया है:

एट्रिब्यूट और जानकारी
targetCellWidth और targetCellHeight (Android 12), minWidth और minHeight
  • Android 12 से, targetCellWidth और targetCellHeight एट्रिब्यूट, ग्रिड सेल के हिसाब से विजेट का डिफ़ॉल्ट साइज़ तय करते हैं. Android 11 और इससे पहले के वर्शन में, इन एट्रिब्यूट को अनदेखा किया जाता है. साथ ही, अगर होम स्क्रीन पर ग्रिड-आधारित लेआउट काम नहीं करता है, तो इन्हें अनदेखा किया जा सकता है.
  • minWidth और minHeight एट्रिब्यूट, डीपी में विजेट का डिफ़ॉल्ट साइज़ तय करते हैं. अगर किसी विजेट की कम से कम चौड़ाई या ऊंचाई की वैल्यू, सेल के डाइमेंशन से मेल नहीं खाती हैं, तो वैल्यू को सेल के सबसे नज़दीकी साइज़ के हिसाब से राउंड अप कर दिया जाता है.
हमारा सुझाव है कि आप एट्रिब्यूट के दोनों सेट—targetCellWidth और targetCellHeight, और minWidth और minHeight—दें, ताकि अगर उपयोगकर्ता के डिवाइस पर targetCellWidth और targetCellHeight काम न करें, तो आपका ऐप्लिकेशन minWidth और minHeight का इस्तेमाल कर सके. अगर ऐसा हो सकता है, तो targetCellWidth और targetCellHeight एट्रिब्यूट को minWidth और minHeight एट्रिब्यूट के मुकाबले ज़्यादा प्राथमिकता दी जाती है.
minResizeWidth और minResizeHeight विजेट का सबसे छोटा साइज़ तय करें. इन वैल्यू से उस साइज़ के बारे में पता चलता है जिसमें विजेट को पढ़ा नहीं जा सकता या उसका इस्तेमाल नहीं किया जा सकता. इन एट्रिब्यूट का इस्तेमाल करके, उपयोगकर्ता विजेट का साइज़ बदलकर डिफ़ॉल्ट विजेट साइज़ से छोटा कर सकता है. अगर minResizeWidth एट्रिब्यूट की वैल्यू minWidth से ज़्यादा है या हॉरिज़ॉन्टल रीसाइज़िंग की सुविधा चालू नहीं है, तो इसे अनदेखा कर दिया जाता है. resizeMode देखें. इसी तरह, अगर minResizeHeight एट्रिब्यूट की वैल्यू minHeight से ज़्यादा है या वर्टिकल साइज़ बदलने की सुविधा चालू नहीं है, तो इसे अनदेखा कर दिया जाता है.
maxResizeWidth और maxResizeHeight विजेट के लिए, सुझाए गए ज़्यादा से ज़्यादा साइज़ के बारे में बताएं. अगर वैल्यू, ग्रिड सेल के डाइमेंशन के हिसाब से नहीं हैं, तो उन्हें सेल के सबसे नज़दीकी साइज़ के हिसाब से राउंड अप कर दिया जाता है. अगर maxResizeWidth एट्रिब्यूट की वैल्यू, minWidth से कम है या हॉरिज़ॉन्टल रीसाइज़िंग की सुविधा चालू नहीं है, तो इसे अनदेखा कर दिया जाता है. resizeMode देखें. इसी तरह, अगर maxResizeHeight एट्रिब्यूट की वैल्यू minHeight से ज़्यादा है या वर्टिकल साइज़ बदलने की सुविधा चालू नहीं है, तो इसे अनदेखा कर दिया जाता है. इसे Android 12 में पेश किया गया था.
resizeMode इन नियमों से पता चलता है कि किसी विजेट का साइज़ कैसे बदला जा सकता है. इस एट्रिब्यूट का इस्तेमाल करके, होम स्क्रीन पर मौजूद विजेट को हॉरिज़ॉन्टल, वर्टिकल या दोनों ऐक्सिस पर साइज़ बदलने की सुविधा दी जा सकती है. उपयोगकर्ता, विजेट को दबाकर रखते हैं, ताकि उसके साइज़ बदलने वाले हैंडल दिखें. इसके बाद, लेआउट ग्रिड पर उसका साइज़ बदलने के लिए, हॉरिज़ॉन्टल या वर्टिकल हैंडल को खींचते हैं. resizeMode एट्रिब्यूट की वैल्यू में ये शामिल हैं: horizontal, vertical, और none. किसी विजेट को हॉरिज़ॉन्टल और वर्टिकल, दोनों तरह से साइज़ बदलने की सुविधा के तौर पर सेट करने के लिए, horizontal|vertical का इस्तेमाल करें.

उदाहरण

ऊपर दी गई टेबल में मौजूद एट्रिब्यूट, विजेट के साइज़ पर किस तरह असर डालते हैं, यह दिखाने के लिए यहां दी गई खास बातों पर ध्यान दें:

  • ग्रिड सेल की चौड़ाई 30 dp और लंबाई 50 dp है.
  • एट्रिब्यूट की खास जानकारी यहां दी गई है:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="80dp"
    android:minHeight="80dp"
    android:targetCellWidth="2"
    android:targetCellHeight="2"
    android:minResizeWidth="40dp"
    android:minResizeHeight="40dp"
    android:maxResizeWidth="120dp"
    android:maxResizeHeight="120dp"
    android:resizeMode="horizontal|vertical" />

Android 12 और इसके बाद के वर्शन के लिए:

targetCellWidth और targetCellHeight एट्रिब्यूट का इस्तेमाल, विजेट के डिफ़ॉल्ट साइज़ के तौर पर करें.

विजेट का साइज़ डिफ़ॉल्ट रूप से 2x2 होता है. विजेट का साइज़ बदलकर 2x1 या 4x3 तक किया जा सकता है.

Android 11 और उससे पहले के वर्शन के लिए:

विजेट के डिफ़ॉल्ट साइज़ का हिसाब लगाने के लिए, minWidth और minHeight एट्रिब्यूट का इस्तेमाल करें.

डिफ़ॉल्ट चौड़ाई = Math.ceil(80 / 30) = 3

डिफ़ॉल्ट ऊंचाई = Math.ceil(80 / 50) = 2

विजेट का साइज़ डिफ़ॉल्ट रूप से 3x2 होता है. इस विजेट का साइज़ बदलकर 2x1 या फ़ुल स्क्रीन किया जा सकता है.

विजेट के अन्य एट्रिब्यूट

नीचे दी गई टेबल में, विजेट के साइज़ के अलावा अन्य क्वालिटी से जुड़े <appwidget-provider> एट्रिब्यूट के बारे में बताया गया है.

एट्रिब्यूट और जानकारी
updatePeriodMillis इससे यह तय होता है कि विजेट फ़्रेमवर्क, onUpdate() कॉलबैक तरीके को कॉल करके, AppWidgetProvider से कितनी बार अपडेट का अनुरोध करता है. इस वैल्यू के हिसाब से, अपडेट ठीक समय पर नहीं हो सकता. इसलिए, हमारा सुझाव है कि आप बैटरी बचाने के लिए, अपडेट को कम से कम बार करें. जैसे, हर घंटे में एक बार से ज़्यादा अपडेट न करें. अपडेट करने की सही अवधि चुनने के लिए, ध्यान रखने वाली बातों की पूरी सूची देखने के लिए, विजेट के कॉन्टेंट को अपडेट करने के लिए ऑप्टिमाइज़ेशन लेख पढ़ें.
initialLayout यह उस लेआउट रिसॉर्स की ओर ले जाता है जो विजेट के लेआउट को तय करता है.
configure इस फ़ील्ड में, उस गतिविधि के बारे में बताया जाता है जो उपयोगकर्ता के विजेट जोड़ने पर शुरू होती है. इससे उपयोगकर्ता को विजेट की प्रॉपर्टी कॉन्फ़िगर करने का विकल्प मिलता है. उपयोगकर्ताओं को विजेट कॉन्फ़िगर करने की अनुमति देना लेख पढ़ें. Android 12 से, आपका ऐप्लिकेशन शुरुआती कॉन्फ़िगरेशन को स्किप कर सकता है. ज़्यादा जानकारी के लिए, विजेट के डिफ़ॉल्ट कॉन्फ़िगरेशन का इस्तेमाल करना लेख पढ़ें.
description इस विकल्प की मदद से, विजेट पिकर के लिए ब्यौरा तय किया जाता है. यह ब्यौरा आपके विजेट के लिए दिखाया जाता है. इसे Android 12 में पेश किया गया था.
previewLayout (Android 12) और previewImage (Android 11 और उससे पहले के वर्शन)
  • Android 12 से, previewLayout एट्रिब्यूट, स्केल की जा सकने वाली झलक के बारे में बताता है. इसे आपको विजेट के डिफ़ॉल्ट साइज़ पर सेट किए गए एक्सएमएल लेआउट के तौर पर उपलब्ध कराना होता है. आदर्श रूप से, इस एट्रिब्यूट के तौर पर दिया गया लेआउट एक्सएमएल, उसी लेआउट एक्सएमएल के जैसा होता है जो डिफ़ॉल्ट वैल्यू के साथ असली विजेट में होता है.
  • Android 11 या इससे पहले के वर्शन में, previewImage एट्रिब्यूट से यह पता चलता है कि कॉन्फ़िगर होने के बाद विजेट कैसा दिखेगा. यह जानकारी, ऐप्लिकेशन विजेट चुनते समय उपयोगकर्ता को दिखती है. अगर यह जानकारी नहीं दी जाती है, तो उपयोगकर्ता को आपके ऐप्लिकेशन का लॉन्चर आइकॉन दिखता है. यह फ़ील्ड, AndroidManifest.xml फ़ाइल में मौजूद <receiver> एलिमेंट के android:previewImage एट्रिब्यूट से मेल खाता है.
ध्यान दें: हमारा सुझाव है कि previewImage और previewLayout, दोनों एट्रिब्यूट की वैल्यू दें, ताकि अगर उपयोगकर्ता के डिवाइस पर previewLayout काम न करे, तो आपका ऐप्लिकेशन previewImage का इस्तेमाल कर सके. ज़्यादा जानकारी के लिए, स्केल किए जा सकने वाले विजेट की झलक दिखाने की सुविधा के साथ काम करने वाले पिछले वर्शन लेख पढ़ें.
autoAdvanceViewId इससे विजेट के उस सबव्यू का व्यू आईडी तय होता है जिसे विजेट का होस्ट अपने-आप आगे बढ़ाता है.
widgetCategory इससे यह तय होता है कि आपका विजेट होम स्क्रीन (home_screen), लॉक स्क्रीन (keyguard) या दोनों पर दिखाया जा सकता है या नहीं. Android 5.0 और इसके बाद के वर्शन के लिए, सिर्फ़ home_screen मान्य है.
widgetFeatures इस एलिमेंट से, विजेट के साथ काम करने वाली सुविधाओं के बारे में पता चलता है. उदाहरण के लिए, अगर आपको चाहिए कि जब कोई उपयोगकर्ता आपके विजेट को जोड़े, तो वह अपने डिफ़ॉल्ट कॉन्फ़िगरेशन का इस्तेमाल करे, तो configuration_optional और reconfigurable, दोनों फ़्लैग तय करें. इससे उपयोगकर्ता के विजेट जोड़ने के बाद, कॉन्फ़िगरेशन गतिविधि शुरू नहीं होती. हालांकि, उपयोगकर्ता बाद में भी विजेट को फिर से कॉन्फ़िगर कर सकता है.

विजेट ब्रॉडकास्ट मैनेज करने के लिए, AppWidgetProvider क्लास का इस्तेमाल करना

AppWidgetProvider क्लास, विजेट ब्रॉडकास्ट को मैनेज करती है. साथ ही, विजेट के लाइफ़साइकल इवेंट के जवाब में विजेट को अपडेट करती है. यहां दिए गए सेक्शन में, मेनिफ़ेस्ट में AppWidgetProvider को शामिल करने और फिर उसे लागू करने का तरीका बताया गया है.

मेनिफ़ेस्ट में विजेट के बारे में जानकारी देना

सबसे पहले, अपने ऐप्लिकेशन की AndroidManifest.xml फ़ाइल में AppWidgetProvider क्लास का एलान करें. इसके लिए, यहां दिया गया उदाहरण देखें:

<receiver android:name="ExampleAppWidgetProvider"
                 android:exported="false">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider"
               android:resource="@xml/example_appwidget_info" />
</receiver>

<receiver> एलिमेंट के लिए android:name एट्रिब्यूट ज़रूरी है. यह एट्रिब्यूट, विजेट के इस्तेमाल किए गए AppWidgetProvider के बारे में बताता है. कॉम्पोनेंट को तब तक एक्सपोर्ट नहीं किया जाना चाहिए, जब तक कि आपके AppWidgetProvider पर ब्रॉडकास्ट करने के लिए किसी अलग प्रोसेस की ज़रूरत न हो. हालांकि, ऐसा आम तौर पर नहीं होता है.

<intent-filter> एलिमेंट में, android:name एट्रिब्यूट वाला <action> एलिमेंट शामिल होना चाहिए. इस एट्रिब्यूट से पता चलता है कि AppWidgetProvider accepts the ACTION_APPWIDGET_UPDATE broadcast. आपको सिर्फ़ इस ब्रॉडकास्ट के बारे में साफ़ तौर पर बताना होगा. AppWidgetManager, ज़रूरत के मुताबिक अन्य सभी विजेट ब्रॉडकास्ट को AppWidgetProvider पर अपने-आप भेजता है.

<meta-data> एलिमेंट, AppWidgetProviderInfo रिसॉर्स के बारे में बताता है. इसमें ये एट्रिब्यूट होने चाहिए:

  • android:name: मेटाडेटा का नाम बताता है. डेटा को AppWidgetProviderInfo डिस्क्रिप्टर के तौर पर पहचानने के लिए, android.appwidget.provider का इस्तेमाल करें.
  • android:resource: AppWidgetProviderInfo संसाधन की जगह की जानकारी देता है.

AppWidgetProvider क्लास लागू करना

AppWidgetProvider क्लास, BroadcastReceiver क्लास से इनहेरिट की जाती है. इसका इस्तेमाल विजेट ब्रॉडकास्ट को मैनेज करने के लिए किया जाता है. इसे सिर्फ़ ऐसे इवेंट ब्रॉडकास्ट मिलते हैं जो विजेट के लिए काम के होते हैं. जैसे, विजेट को अपडेट, मिटाया, चालू, और बंद किए जाने पर. ब्रॉडकास्ट इवेंट होने पर, ये AppWidgetProvider तरीके कॉल किए जाते हैं:

onUpdate()
इस फ़ंक्शन को कॉल करके, विजेट को अपडेट किया जाता है. विजेट को अपडेट करने का इंटरवल, AppWidgetProviderInfo में मौजूद updatePeriodMillis एट्रिब्यूट से तय होता है. ज़्यादा जानकारी के लिए, इस पेज पर विजेट के अन्य एट्रिब्यूट के बारे में बताने वाली टेबल देखें.
जब उपयोगकर्ता विजेट जोड़ता है, तब भी इस तरीके को कॉल किया जाता है. इसलिए, यह ज़रूरी सेटअप करता है. जैसे, View ऑब्जेक्ट के लिए इवेंट हैंडलर तय करना या विजेट में डेटा दिखाने के लिए जॉब शुरू करना. हालांकि, अगर आपने configuration_optional फ़्लैग के बिना कॉन्फ़िगरेशन गतिविधि का एलान किया है, तो उपयोगकर्ता के विजेट जोड़ने पर यह तरीका नहीं कॉल किया जाता है. हालांकि, बाद के अपडेट के लिए इसे कॉल किया जाता है. कॉन्फ़िगरेशन पूरा होने पर, पहला अपडेट करने की ज़िम्मेदारी कॉन्फ़िगरेशन गतिविधि की होती है. ज़्यादा जानकारी के लिए, उपयोगकर्ताओं को ऐप्लिकेशन विजेट कॉन्फ़िगर करने की सुविधा देना लेख पढ़ें.
सबसे ज़रूरी कॉलबैक onUpdate() है. ज़्यादा जानकारी के लिए, इस पेज पर onUpdate() क्लास की मदद से इवेंट हैंडल करना देखें.
onAppWidgetOptionsChanged()

इस फ़ंक्शन को तब कॉल किया जाता है, जब विजेट को पहली बार रखा जाता है. साथ ही, जब भी विजेट का साइज़ बदला जाता है, तब भी इसे कॉल किया जाता है. इस कॉलबैक का इस्तेमाल, विजेट के साइज़ की रेंज के आधार पर कॉन्टेंट दिखाने या छिपाने के लिए करें. getAppWidgetOptions() को कॉल करके, साइज़ की रेंज और Android 12 से शुरू होने वाले, उन साइज़ की सूची पाएं जिनमें विजेट इंस्टेंस को रखा जा सकता है. यह Bundle दिखाता है, जिसमें यह जानकारी शामिल होती है:

  • OPTION_APPWIDGET_MIN_WIDTH: इसमें विजेट इंस्टेंस की चौड़ाई की निचली सीमा होती है. यह सीमा, डीपी यूनिट में होती है.
  • OPTION_APPWIDGET_MIN_HEIGHT: इसमें विजेट इंस्टेंस की ऊंचाई की निचली सीमा होती है. यह सीमा, डीपी यूनिट में होती है.
  • OPTION_APPWIDGET_MAX_WIDTH: इसमें विजेट इंस्टेंस की चौड़ाई की ऊपरी सीमा होती है. यह सीमा, डीपी यूनिट में होती है.
  • OPTION_APPWIDGET_MAX_HEIGHT: इसमें विजेट इंस्टेंस की ऊंचाई की ऊपरी सीमा होती है. यह सीमा, डीपी यूनिट में होती है.
  • OPTION_APPWIDGET_SIZES: इसमें संभावित साइज़ (List<SizeF>) की सूची होती है. ये साइज़, डीपी यूनिट में होते हैं. यह सूची बताती है कि विजेट का कोई इंस्टेंस कौनसे साइज़ ले सकता है. इसे Android 12 में पेश किया गया था.
onDeleted(Context, int[])

जब भी विजेट होस्ट से कोई विजेट मिटाया जाता है, तब इस फ़ंक्शन को कॉल किया जाता है.

onEnabled(Context)

इस फ़ंक्शन को तब कॉल किया जाता है, जब विजेट का कोई इंस्टेंस पहली बार बनाया जाता है. उदाहरण के लिए, अगर उपयोगकर्ता आपके विजेट के दो इंस्टेंस जोड़ता है, तो इस फ़ंक्शन को सिर्फ़ पहली बार कॉल किया जाता है. अगर आपको कोई नया डेटाबेस खोलना है या कोई ऐसा सेटअप करना है जो विजेट के सभी इंस्टेंस के लिए सिर्फ़ एक बार किया जाना चाहिए, तो यह ऐसा करने के लिए सबसे सही जगह है.

onDisabled(Context)

इस फ़ंक्शन को तब कॉल किया जाता है, जब विजेट होस्ट से आपके विजेट का आखिरी इंस्टेंस मिटा दिया जाता है. यहां onEnabled(Context) में किए गए किसी भी काम को मिटाया जा सकता है. जैसे, कुछ समय के लिए बनाए गए डेटाबेस को मिटाना.

onReceive(Context, Intent)

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

आपको AppWidgetProvider क्लास को ब्रॉडकास्ट रिसीवर के तौर पर लागू करने का एलान करना होगा. इसके लिए, AndroidManifest में <receiver> एलिमेंट का इस्तेमाल करें. ज़्यादा जानकारी के लिए, इस पेज पर मेनिफ़ेस्ट फ़ाइल में किसी विजेट का एलान करना सेक्शन देखें.

onUpdate() क्लास की मदद से इवेंट मैनेज करना

सबसे अहम AppWidgetProvider कॉलबैक onUpdate() है, क्योंकि इसे तब कॉल किया जाता है, जब हर विजेट को किसी होस्ट में जोड़ा जाता है. हालांकि, अगर आपने configuration_optional फ़्लैग के बिना कॉन्फ़िगरेशन गतिविधि का इस्तेमाल किया है, तो ऐसा नहीं होगा. अगर आपका विजेट उपयोगकर्ता के किसी भी इंटरैक्शन इवेंट को स्वीकार करता है, तो इस कॉलबैक में इवेंट हैंडलर रजिस्टर करें. अगर आपका विजेट, कुछ समय के लिए फ़ाइलें या डेटाबेस नहीं बनाता है या ऐसा कोई अन्य काम नहीं करता है जिसके लिए क्लीन-अप की ज़रूरत होती है, तो हो सकता है कि आपको सिर्फ़ onUpdate() कॉलबैक तरीके को तय करना पड़े.

उदाहरण के लिए, अगर आपको ऐसा विजेट चाहिए जिसमें एक बटन हो और उस पर टैप करने से कोई गतिविधि शुरू हो, तो AppWidgetProvider को इस तरह से लागू किया जा सकता है:

Kotlin

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity.
            val pendingIntent: PendingIntent = PendingIntent.getActivity(
                    /* context = */ context,
                    /* requestCode = */  0,
                    /* intent = */ Intent(context, ExampleActivity::class.java),
                    /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            val views: RemoteViews = RemoteViews(
                    context.packageName,
                    R.layout.appwidget_provider_layout
            ).apply {
                setOnClickPendingIntent(R.id.button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

Java

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        for (int i=0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];
            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                /* context = */ context,
                /* requestCode = */ 0,
                /* intent = */ intent,
                /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

यह AppWidgetProvider सिर्फ़ onUpdate() तरीके को तय करता है. इसका इस्तेमाल करके, एक PendingIntent बनाया जाता है. यह Activity को लॉन्च करता है और setOnClickPendingIntent(int, PendingIntent) का इस्तेमाल करके, इसे विजेट के बटन से जोड़ता है. इसमें एक लूप शामिल होता है, जो appWidgetIds में मौजूद हर एंट्री को दोहराता है. appWidgetIds, आईडी का एक ऐसा कलेक्शन होता है जो इस सेवा देने वाली कंपनी के बनाए गए हर विजेट की पहचान करता है. अगर उपयोगकर्ता विजेट के एक से ज़्यादा इंस्टेंस बनाता है, तो वे सभी एक साथ अपडेट होते हैं. हालांकि, विजेट के सभी इंस्टेंस के लिए सिर्फ़ एक updatePeriodMillis शेड्यूल मैनेज किया जाता है. उदाहरण के लिए, अगर अपडेट करने का शेड्यूल हर दो घंटे में अपडेट करने के लिए तय किया गया है और पहले विजेट के एक घंटे बाद दूसरा विजेट जोड़ा जाता है, तो दोनों विजेट पहले विजेट के लिए तय की गई अवधि में अपडेट किए जाते हैं. साथ ही, दूसरे विजेट के लिए तय की गई अपडेट की अवधि को अनदेखा कर दिया जाता है. ये दोनों हर दो घंटे में अपडेट होते हैं, न कि हर घंटे में.

ज़्यादा जानकारी के लिए, ExampleAppWidgetProvider.java सैंपल क्लास देखें.

विजेट ब्रॉडकास्ट इंटेंट पाना

AppWidgetProvider एक सुविधा क्लास है. अगर आपको सीधे तौर पर विजेट ब्रॉडकास्ट पाने हैं, तो अपना BroadcastReceiver लागू करें या onReceive(Context,Intent) कॉलबैक को बदलें. आपको इन इंटेंट पर ध्यान देना होगा:

विजेट का लेआउट बनाना

आपको एक्सएमएल में अपने विजेट के लिए शुरुआती लेआउट तय करना होगा. साथ ही, इसे प्रोजेक्ट की res/layout/ डायरेक्ट्री में सेव करना होगा. ज़्यादा जानकारी के लिए, डिज़ाइन से जुड़ी दिशा-निर्देश देखें.

अगर आपको लेआउट के बारे में जानकारी है, तो विजेट का लेआउट बनाना आसान है. हालांकि, ध्यान रखें कि विजेट लेआउट, RemoteViews पर आधारित होते हैं. इसलिए, हर तरह के लेआउट या व्यू विजेट के साथ काम नहीं करते. RemoteViews के साथ काम करने वाले व्यू के कस्टम व्यू या सबक्लास का इस्तेमाल नहीं किया जा सकता.

RemoteViews, ViewStub के साथ भी काम करता है. यह एक अदृश्य, शून्य साइज़ वाला View है. इसका इस्तेमाल, लेआउट रिसॉर्स को रनटाइम पर लेज़ी तरीके से बढ़ाने के लिए किया जा सकता है.

स्टेटफ़ुल व्यवहार के लिए सहायता

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

विजेट अब भी स्टेटलेस है. आपके ऐप्लिकेशन को स्थिति सेव करनी चाहिए और स्थिति में बदलाव होने पर सूचना पाने के लिए रजिस्टर करना चाहिए.

स्टेटफ़ुल व्यवहार दिखाने वाले शॉपिंग लिस्ट विजेट का उदाहरण
तीसरी इमेज. स्टेटफ़ुल व्यवहार का उदाहरण.

यहां दिए गए कोड के उदाहरण में, इन कॉम्पोनेंट को लागू करने का तरीका बताया गया है.

Kotlin

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

Java

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

दो लेआउट उपलब्ध कराएं: एक लेआउट, Android 12 या इसके बाद के वर्शन वाले डिवाइसों को टारगेट करने के लिए res/layout-v31 फ़ोल्डर में और दूसरा लेआउट, Android 11 या इससे पहले के वर्शन वाले डिवाइसों को टारगेट करने के लिए डिफ़ॉल्ट res/layout फ़ोल्डर में.

गोल कोनों को लागू करना

Android 12 में, आपके विजेट के गोल कोनों के रेडियस सेट करने के लिए, ये सिस्टम पैरामीटर उपलब्ध हैं:

  • system_app_widget_background_radius: विजेट के बैकग्राउंड के कोने का रेडियस. यह कभी भी 28 डीपी से ज़्यादा नहीं होता.

  • इनर रेडियस, जिसे आउटर रेडियस और पैडिंग से कैलकुलेट किया जा सकता है. यह स्निपेट देखें:

    /**
     * Applies corner radius for views that are visually positioned [widgetPadding]dp inside of the
     * widget background.
     */
    @Composable
    fun GlanceModifier.appWidgetInnerCornerRadius(widgetPadding: Dp): GlanceModifier {
    
        if (Build.VERSION.SDK_INT < 31) {
            return this
        }
    
        val resources = LocalContext.current.resources
        // get dimension in float (without rounding).
        val px = resources.getDimension(android.R.dimen.system_app_widget_background_radius)
        val widgetBackgroundRadiusDpValue = px / resources.displayMetrics.density
        if (widgetBackgroundRadiusDpValue < widgetPadding.value) {
            return this
        }
        return this.cornerRadius(Dp(widgetBackgroundRadiusDpValue - widgetPadding.value))
    }

अपने विजेट के अंदर मौजूद कॉन्टेंट के लिए सही रेडियस का हिसाब लगाने के लिए, इस फ़ॉर्मूले का इस्तेमाल करें: systemRadiusValue - widgetPadding

जिन विजेट का कॉन्टेंट, आयताकार के अलावा किसी और आकार में काटा जाता है उन्हें @android:id/background का इस्तेमाल करना चाहिए. यह बैकग्राउंड व्यू का व्यू आईडी होता है. इसमें android:clipToOutline को true पर सेट किया जाता है.

गोल कोनों के लिए ज़रूरी बातें

  • तीसरे पक्ष के लॉन्चर और डिवाइस बनाने वाली कंपनियां, system_app_widget_background_radius पैरामीटर को 28 डीपी से कम पर सेट कर सकती हैं.
  • अगर आपके विजेट में @android:id/background का इस्तेमाल नहीं किया जाता है या ऐसा बैकग्राउंड तय नहीं किया जाता है जो आउटलाइन के आधार पर कॉन्टेंट को काटता है, तो android:clipToOutline को true पर सेट किया जाता है. ऐसे में, लॉन्चर अपने-आप बैकग्राउंड का पता लगाता है और विजेट को काटता है. इसके लिए, सिस्टम के रेडियस पर सेट किए गए गोल कोनों वाले आयत का इस्तेमाल किया जाता है.

  • स्क्वेयर के अलावा अन्य शेप को, गोल किनारों वाले आयताकार रीसाइज़ कंटेनर में रखना ज़रूरी है, ताकि वे कट न जाएं.

  • Android 16 से, AOSP सिस्टम के लिए system_app_widget_background_radius की वैल्यू 24dp है. लॉन्चर और डिवाइस बनाने वाली कंपनियां, विजेट को system_app_widget_background_radius पर क्लिप कर सकती हैं.

  • किसी विजेट के अंदर मौजूद कॉन्टेंट में, system_app_widget_background_radius तक की रेडियस वैल्यू के लिए ज़रूरी पैडिंग होनी चाहिए, ताकि गोल कोनों की वजह से कॉन्टेंट न कटे.28dp

हमारा सुझाव है कि Android के पिछले वर्शन के साथ विजेट काम करे, इसके लिए कस्टम एट्रिब्यूट तय करें. साथ ही, Android 12 के लिए उन्हें बदलने के लिए कस्टम थीम का इस्तेमाल करें. ऐसा करने का तरीका, यहां दी गई सैंपल एक्सएमएल फ़ाइलों में दिखाया गया है:

/values/attrs.xml

<resources>
  <attr name="backgroundRadius" format="dimension" />
</resources>

/values/styles.xml

<resources>
  <style name="MyWidgetTheme">
    <item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
  </style>
</resources>

/values-31/styles.xml

<resources>
  <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
    <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
  </style>
</resources>

/drawable/my_widget_background.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="?attr/backgroundRadius" />
  ...
</shape>

/layout/my_widget_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:background="@drawable/my_widget_background" />