एक नज़र में जानकारी देखने की सुविधा की मदद से ऐप्लिकेशन का विजेट बनाना

यहां दिए गए सेक्शन में, Glance की मदद से बेसिक ऐप्लिकेशन विजेट बनाने का तरीका बताया गया है.

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

सेटअप के चरण पूरे करने के बाद, अपने ऐप्लिकेशन में AppWidget और उसके मेटाडेटा का एलान करें.

  1. AppWidget रिसीवर को GlanceAppWidgetReceiver से एक्सटेंड करें:

    class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
        override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget")
    }

  2. अपने AndroidManifest.xml फ़ाइल और उससे जुड़ी मेटाडेटा फ़ाइल में, ऐप्लिकेशन विजेट की सुविधा देने वाली कंपनी को रजिस्टर करें:

        <receiver android:name=".glance.MyReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/my_app_widget_info" />
    </receiver>
    

AppWidgetProviderInfo मेटाडेटा जोड़ना

इसके बाद, विजेट बनाना गाइड में दिए गए निर्देशों का पालन करके, @xml/my_app_widget_info फ़ाइल में ऐप्लिकेशन विजेट की जानकारी बनाएं और तय करें.

Glance के लिए सिर्फ़ यह अंतर है कि इसमें initialLayout एक्सएमएल नहीं है. हालांकि, आपको इसे तय करना होगा. लाइब्रेरी में दिए गए, पहले से तय किए गए लोडिंग लेआउट का इस्तेमाल किया जा सकता है:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>

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

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

<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/glance_default_loading_layout"
    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 एट्रिब्यूट की वैल्यू से कम है या वर्टिकल साइज़ बदलने की सुविधा चालू नहीं है, तो maxResizeHeight एट्रिब्यूट को अनदेखा कर दिया जाता है. इसे 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() कॉलबैक तरीके को कॉल करके, GlanceAppWidgetReceiver से कितनी बार अपडेट का अनुरोध करता है. हमारा सुझाव है कि बैटरी बचाने के लिए, इस सुविधा को कम से कम अपडेट करें. इसे हर घंटे में एक बार से ज़्यादा अपडेट न करें. ज़्यादा जानकारी के लिए, Glance की स्थिति को मैनेज करने से जुड़े लेख में विजेट को कब अपडेट करें सेक्शन देखें.
initialLayout यह लेआउट रिसॉर्स की ओर इशारा करता है. यह Glance के यूज़र इंटरफ़ेस (यूआई) कंपोज़िशन रेंडर होने से पहले, विजेट के लोडिंग लेआउट को तय करता है. लाइब्रेरी में दिए गए, पहले से तय किए गए लोडिंग लेआउट का इस्तेमाल किया जा सकता है: @layout/glance_default_loading_layout.
configure यह कॉन्फ़िगरेशन गतिविधि के बारे में बताता है, जो उपयोगकर्ता के विजेट जोड़ने पर लॉन्च होती है. इस पेज पर मौजूद, विजेट कॉन्फ़िगरेशन ऐक्टिविटी लागू करना सेक्शन देखें.
description यह विजेट पिकर के लिए जानकारी तय करता है, ताकि वह आपके विजेट के लिए जानकारी दिखा सके. इसे Android 12 में पेश किया गया था.
previewLayout (Android 12) और previewImage (Android 11 और उससे पहले के वर्शन)
  • Android 12 से, previewLayout एट्रिब्यूट, स्केल की जा सकने वाली झलक के बारे में बताता है. इसे एक्सएमएल लेआउट के तौर पर उपलब्ध कराया जाता है. यह विजेट के डिफ़ॉल्ट साइज़ पर सेट होता है. आम तौर पर, यह आपके डिज़ाइन लेआउट से मेल खाने वाली स्टैटिक एक्सएमएल मैपिंग की ओर इशारा करता है.
  • Android 11 या इससे पहले के वर्शन में, previewImage एट्रिब्यूट, विजेट की स्टैटिक इमेज ड्रॉएबल स्क्रीनशॉट के बारे में बताता है. यह विजेट पिकर में दिखता है.
हमारा सुझाव है कि आप दोनों को तय करें, ताकि आपका ऐप्लिकेशन पुराने प्लैटफ़ॉर्म पर आसानी से काम कर सके. नए प्लैटफ़ॉर्म (Android 15+) के लिए, Kotlin में `GlanceAppWidget.providePreview` का इस्तेमाल करके, लाइव जनरेट की गई झलकें तय की जा सकती हैं. जनरेट की गई झलकें दिखाने से जुड़ी गाइड देखें.
autoAdvanceViewId इससे विजेट के उस सबव्यू का व्यू आईडी पता चलता है जिसे विजेट का होस्ट अपने-आप आगे बढ़ाता है.
widgetCategory इससे यह तय होता है कि आपके विजेट को होम स्क्रीन (home_screen), लॉक स्क्रीन (keyguard) या दोनों पर दिखाया जा सकता है. Android 5.0 और इसके बाद के वर्शन के लिए, सिर्फ़ home_screen मान्य है.
widgetFeatures इससे यह पता चलता है कि विजेट में कौन-कौनसी सुविधाएं काम करती हैं. उदाहरण के लिए, अगर आपके विजेट का कॉन्फ़िगरेशन ज़रूरी नहीं है, तो configuration_optional और reconfigurable, दोनों एट्रिब्यूट की वैल्यू दें.

GlanceAppWidget को परिभाषित करें

  1. GlanceAppWidget से एक्सटेंड होने वाली एक नई क्लास बनाएं और provideGlance तरीके को बदलें. इस तरीके से, अपने विजेट को रेंडर करने के लिए ज़रूरी डेटा लोड किया जा सकता है:

    class MyAppWidget : GlanceAppWidget() {
    
        override suspend fun provideGlance(context: Context, id: GlanceId) {
    
            // In this method, load data needed to render the AppWidget.
            // Use `withContext` to switch to another thread for long running
            // operations.
    
            provideContent {
                // create your AppWidget here
                Text("Hello World")
            }
        }
    }

  2. इसे अपने GlanceAppWidgetReceiver पर मौजूद glanceAppWidget में इंस्टैंशिएट करें:

    class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
    
        // Let MyAppWidgetReceiver know which GlanceAppWidget to use
        override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
    }

आपने Glance का इस्तेमाल करके, AppWidget को कॉन्फ़िगर कर लिया है.

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

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

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

अपनी AndroidManifest.xml फ़ाइल में, अपनी GlanceAppWidgetReceiver क्लास की सबक्लास को ब्रॉडकास्ट रिसीवर के तौर पर एलान करें:

<receiver android:name="ExampleAppWidgetReceiver"
          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/my_app_widget_info" />
</receiver>

<receiver> एलिमेंट के लिए android:name एट्रिब्यूट ज़रूरी है. यह एट्रिब्यूट, रिसीवर क्लास के बारे में बताता है. कॉन्टेंट पाने वाले व्यक्ति को <intent-filter> में जाकर, ACTION_APPWIDGET_UPDATE ब्रॉडकास्ट करने की कार्रवाई को स्वीकार करना होगा.

<meta-data> एलिमेंट को अपना नाम android.appwidget.provider के तौर पर पहचानना चाहिए. साथ ही, android:resource एट्रिब्यूट को आपके AppWidgetProviderInfo एक्सएमएल मेटाडेटा रिसॉर्स (@xml/my_app_widget_info) की ओर पॉइंट करना चाहिए.

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

Glance में, AppWidgetProvider के बजाय सीधे GlanceAppWidgetReceiver को बढ़ाया जाता है. इसे लागू करने के लिए, अपने रिसीवर को GlanceAppWidget इंस्टेंस से लिंक करें. GlanceAppWidgetReceiver में उपलब्ध मुख्य कॉलबैक इस तरह काम करते हैं:

  • onUpdate(): कंपोज़िशन अपडेट लागू करने के लिए, Glance इसे अपने-आप बदल देता है. अगर आपने onUpdate को मैन्युअल तरीके से बदल दिया है, तो आपको super.onUpdate को कॉल करना होगा, ताकि Glance कंपोज़िशन थ्रेड को लॉन्च कर सके.
  • onAppWidgetOptionsChanged(): इस फ़ंक्शन को तब कॉल किया जाता है, जब विजेट को पहली बार रखा जाता है या उसका साइज़ बदला जाता है. एक नज़र में पढ़ने की सुविधा के विकल्प, आइटम को बैकग्राउंड में बंडल करते हैं. इससे आपका लेआउट, रनटाइम डाइमेंशन के हिसाब से आसानी से अडजस्ट हो जाता है.
  • onDeleted(Context, IntArray): जब भी उपयोगकर्ता किसी खास विजेट इंस्टेंस को मिटाता है, तब यह ट्रिगर होता है.
  • onEnabled(Context): यह तब ट्रिगर होता है, जब आपके विजेट का पहला इंस्टेंस बन जाता है. ग्लोबल माइग्रेशन को मैनेज करने के लिए बेहतरीन टूल.
  • onDisabled(Context): इस फ़ंक्शन को तब कॉल किया जाता है, जब प्रोवाइडर का आखिरी चालू इंस्टेंस हटा दिया जाता है.
  • onReceive(Context, Intent): यह हर प्लैटफ़ॉर्म ब्रॉडकास्ट को, खास कॉलबैक तरीकों से पहले इंटरसेप्ट करता है. आपको यह पक्का करना होगा कि आपने कस्टम रिसीवर लॉजिक में super.onReceive(context, intent) को कॉल किया हो. साथ ही, goAsync को कभी कॉल न करें, क्योंकि Glance, काम को एसिंक्रोनस तरीके से अपने-आप रूट करता है.

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

GlanceAppWidgetReceiver, इन बुनियादी प्लैटफ़ॉर्म विजेट ब्रॉडकास्ट इंटेंट को फ़िल्टर करता है और मैनेज करता है:

यूज़र इंटरफ़ेस बनाना

यहां दिए गए स्निपेट में, यूज़र इंटरफ़ेस (यूआई) बनाने का तरीका बताया गया है:

/* Import Glance Composables
 In the event there is a name clash with the Compose classes of the same name,
 you may rename the imports per https://kotlinlang.org/docs/packages.html#imports
 using the `as` keyword.

import androidx.glance.Button
import androidx.glance.layout.Column
import androidx.glance.layout.Row
import androidx.glance.text.Text
*/
class MyAppWidget : GlanceAppWidget() {

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // Load data needed to render the AppWidget.
        // Use `withContext` to switch to another thread for long running
        // operations.

        provideContent {
            // create your AppWidget here
            MyContent()
        }
    }

    @Composable
    private fun MyContent() {
        Column(
            modifier = GlanceModifier.fillMaxSize(),
            verticalAlignment = Alignment.Top,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp))
            Row(horizontalAlignment = Alignment.CenterHorizontally) {
                Button(
                    text = "Home",
                    onClick = actionStartActivity<MyActivity>()
                )
                Button(
                    text = "Work",
                    onClick = actionStartActivity<MyActivity>()
                )
            }
        }
    }
}

ऊपर दिया गया कोड सैंपल, ये काम करता है:

  • टॉप लेवल Column में, आइटम एक के बाद एक वर्टिकल तरीके से रखे जाते हैं.
  • Column, उपलब्ध जगह के हिसाब से अपना साइज़ बढ़ाता है (GlanceModifier के ज़रिए). साथ ही, अपने कॉन्टेंट को सबसे ऊपर (verticalAlignment) अलाइन करता है और उसे हॉरिज़ॉन्टल तौर पर बीच में (horizontalAlignment) रखता है.
  • Column के कॉन्टेंट को लैम्डा का इस्तेमाल करके तय किया जाता है. क्रम मायने रखता है.
    • Column में पहला आइटम, Text कॉम्पोनेंट है. इसमें 12.dp पैडिंग है.
    • दूसरा आइटम Row है. इसमें आइटम को एक के बाद एक, हॉरिज़ॉन्टल तरीके से रखा जाता है. साथ ही, दो Buttons को हॉरिज़ॉन्टल तरीके से सेंटर में रखा जाता है (horizontalAlignment). फ़ाइनल डिसप्ले, उपलब्ध जगह पर निर्भर करता है. इस इमेज में दिखाया गया है कि यह कैसा दिख सकता है:
destination_widget
पहली इमेज. यूज़र इंटरफ़ेस (यूआई) का एक उदाहरण.

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

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

Android 12 में, सिस्टम पैरामीटर पेश किए गए हैं. इनकी मदद से, अपने ऐप्लिकेशन के विजेट के कॉर्नर रेडियस को डाइनैमिक तरीके से पसंद के मुताबिक बनाया जा सकता है:

  • system_app_widget_background_radius: इससे विजेट के बैकग्राउंड कंटेनर के कॉर्नर का रेडियस तय होता है. यह 28 डीपी से ज़्यादा नहीं होना चाहिए.
  • अंदरूनी रेडियस: कॉन्टेंट को क्लिप होने से रोकने के लिए, सिस्टम के बैकग्राउंड आउटलाइन के आधार पर अपने अंदरूनी कॉन्टेंट के लिए आनुपातिक रेडियस की गणना करें: systemRadiusValue - widgetPadding

Glance में, GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius) का इस्तेमाल करके कंपोज़िशन में कॉर्नर रेडियस की साइज़िंग प्रॉपर्टी को डाइनैमिक तौर पर लागू किया जा सकता है.

Android 11 (एपीआई लेवल 30) या इससे पहले के वर्शन वाले डिवाइसों पर, पुराने सिस्टम के साथ काम करने की सुविधा के लिए, कस्टम एट्रिब्यूट और कस्टम थीम रिसॉर्स फ़ॉलबैक लागू करें:

  • /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>