यहां दिए गए सेक्शन में, Glance की मदद से एक बेसिक ऐप्लिकेशन विजेट बनाने का तरीका बताया गया है.
मेनिफ़ेस्ट में AppWidget की जानकारी दें
सेटअप के चरण पूरे करने के बाद, अपने ऐप्लिकेशन में AppWidget और उसके मेटाडेटा के बारे में बताएं.
AppWidgetरिसीवर कोGlanceAppWidgetReceiverसे बढ़ाएं:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
अपनी
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 ऑब्जेक्ट, आपके विजेट की ज़रूरी विशेषताओं के बारे में बताता है. अपनी एक्सएमएल मेटाडेटा रिसॉर्स फ़ाइल (res/xml/my_app_widget_info.xml) में, <appwidget-provider> एलिमेंट के अंदर AppWidgetProviderInfo को तय करें:
<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 |
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() कॉलबैक के तरीके को कॉल करके, GlanceAppWidgetReceiver से कितनी बार अपडेट का अनुरोध करता है. हमारा सुझाव है कि बैटरी बचाने के लिए, अपडेट करने की फ़्रीक्वेंसी को कम से कम रखें. जैसे, एक घंटे में एक बार से ज़्यादा अपडेट न करें.
ज़्यादा जानकारी के लिए, Glance स्टेट मैनेजमेंट में विजेट कब अपडेट करें सेक्शन देखें. |
initialLayout |
यह उस लेआउट रिसॉर्स पर ले जाता है जो Glance यूआई कंपोज़िशन के रेंडर होने से पहले, विजेट के लोडिंग लेआउट को तय करता है. लाइब्रेरी में पहले से मौजूद लोडिंग लेआउट का इस्तेमाल किया जा सकता है: @layout/glance_default_loading_layout. |
configure |
यह उस कॉन्फ़िगरेशन गतिविधि के बारे में बताता है जो उपयोगकर्ता के विजेट जोड़ने पर लॉन्च होती है. उपयोगकर्ताओं को ऐप्लिकेशन विजेट कॉन्फ़िगर करने की सुविधा देना गाइड देखें. |
description |
इससे विजेट पिकर के लिए ब्यौरा तय होता है, ताकि वह आपके विजेट के लिए दिखे. इसे Android 12 में लॉन्च किया गया था. |
previewLayout (Android 12)
और previewImage (Android 11 और इससे पहले के वर्शन) |
|
autoAdvanceViewId |
इससे विजेट के सबव्यू का व्यू आईडी तय होता है. विजेट का होस्ट, इस सबव्यू को अपने-आप आगे बढ़ाता है. |
widgetCategory |
इससे यह तय होता है कि आपका विजेट, होम स्क्रीन (home_screen), लॉक स्क्रीन (keyguard) या दोनों पर दिखाया जा सकता है या नहीं. Android 5.0 और इसके बाद के वर्शन के लिए, सिर्फ़ home_screen मान्य है. |
widgetFeatures |
विजेट के साथ काम करने वाली सुविधाओं के बारे में बताता है. उदाहरण के लिए, अगर आपके विजेट का कॉन्फ़िगरेशन ज़रूरी नहीं है, तो configuration_optional और reconfigurable, दोनों की जानकारी दें. |
GlanceAppWidget को परिभाषित करें
एक नई क्लास बनाएं, जो
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") } } }
इसे अपनी
GlanceAppWidgetReceiverपरglanceAppWidgetमें इंस्टैंशिएट करें:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
अब आपने Glance का इस्तेमाल करके, AppWidget को कॉन्फ़िगर कर लिया है.
अलग-अलग साइज़ बकेट में विजेट की इमेज मेमोरी मैनेज करना
जब आपका विजेट बिटमैप या content:// इमेज यूआरआई दिखाता है, तो सीरियलाइज़ की गई RemoteViews इमेज मेमोरी को सिस्टम की तय सीमा (6 * width *
height बाइट, Android 17 और इसके बाद के वर्शन पर IllegalArgumentException के साथ लागू की गई) के अंदर रखें. इसके लिए, यह तरीका अपनाएं:
provideContentसे पहले, शेयर किए गए बिट मैप को डिकोड करना: अगर आपका विजेटSizeMode.ResponsiveयाSizeMode.Exactका इस्तेमाल करता है, तो Glance हरDpSizeबकेट के लिए,provideContentलैम्डा को एक बार चलाता है.provideContentके अंदरBitmapको डिकोड करने से, हर बकेट के लिए एक अलगBitmapइंस्टेंस असाइन होता है. इससेRemoteViews.mBitmapCacheमें मेमोरी का इस्तेमाल कई गुना बढ़ जाता है.provideGlanceमेंprovideContentसे पहले, डाउनसैंपल किए गए बिटमैप (अपारदर्शी इमेज के लिएBitmap.Config.RGB_565) को एक बार डिकोड करें, ताकि सभी बकेट एक हीBitmapरेफ़रंस शेयर करें.मैच करने वाले
ImageProviderइंपोर्ट का इस्तेमाल करें: Jetpack Glance, दो पैकेज में दो अलग-अलगImageProviderओवरलोड उपलब्ध कराता है:- इन-मेमोरी
ImageProvider(bitmap: Bitmap)या ड्रॉ करने लायक संसाधनImageProvider(resId: Int)पास करते समय,import androidx.glance.ImageProviderका इस्तेमाल करें. - यूआरआई पास करते समय
import androidx.glance.appwidget.ImageProviderका इस्तेमाल करेंImageProvider(uri: Uri).FileProviderयूआरआई की मदद से कैश मेमोरी में सेव की गई फ़ाइलें उपलब्ध कराते समय, इंस्टॉल किए गए हरIntent.CATEGORY_HOMEलॉन्चर पैकेज कोIntent.FLAG_GRANT_READ_URI_PERMISSIONकी अनुमति दें, ताकि होस्ट इमेज को रेंडर कर सके.
- इन-मेमोरी
विजेट ब्रॉडकास्ट को मैनेज करने के लिए, GlanceAppWidgetReceiver क्लास का इस्तेमाल करना
GlanceAppWidgetReceiver कोऑर्डिनेट विजेट, AppWidgetProvider को एक्सटेंड करके ब्रॉडकास्ट और प्लैटफ़ॉर्म की स्थिति के अपडेट भेजता है. विजेट के अपडेट होने, मिटने, चालू होने या बंद होने पर, इसे प्लैटफ़ॉर्म इवेंट मिलते हैं. इसके बाद, यह उन्हें Compose लाइफ़साइकल के अनुरोधों में बदल देता है.
मेनिफ़ेस्ट में विजेट के बारे में बताना
अपनी AndroidManifest.xml फ़ाइल में, GlanceAppWidgetReceiver क्लास सबक्लास को ब्रॉडकास्ट रिसीवर के तौर पर एलान करें:
<receiver android:name="MyReceiver"
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(): इसे तब कॉल किया जाता है, जब विजेट को पहली बार जोड़ा जाता है या उसका साइज़ बदला जाता है. Glance, विकल्पों के बंडल आइटम को हुड के अंदर पढ़ता है, ताकि आपका लेआउट रनटाइम डाइमेंशन के आधार पर आसानी से अडजस्ट हो सके.onDeleted(Context, IntArray): यह तब ट्रिगर होता है, जब उपयोगकर्ता किसी विजेट के इंस्टेंस को मिटाता है.onEnabled(Context): यह इवेंट तब ट्रिगर होता है, जब आपके विजेट का पहला इंस्टेंस सफलतापूर्वक बन जाता है. ग्लोबल माइग्रेशन चलाने के लिए बेहतरीन.onDisabled(Context): इसे तब कॉल किया जाता है, जब सेवा देने वाली कंपनी का आखिरी चालू इंस्टेंस हटा दिया जाता है.onReceive(Context, Intent): कॉलबैक के खास तरीकों से पहले, हर प्लैटफ़ॉर्म के ब्रॉडकास्ट को इंटरसेप्ट करता है. आपको यह पक्का करना होगा कि आपने जो कस्टम रिसीवर लॉजिक लिखा है वहsuper.onReceive(context, intent)को कॉल करे. साथ ही, आपकोgoAsyncको खुद कॉल नहीं करना चाहिए, क्योंकि Glance अपने-आप काम को एसिंक्रोनस तरीके से रूट करता है.
विजेट ब्रॉडकास्ट इंटेंट पाना
GlanceAppWidgetReceiver, बैकग्राउंड में काम करते हुए, प्लैटफ़ॉर्म के बुनियादी विजेट ब्रॉडकास्ट इंटेंट को फ़िल्टर और मैनेज करता है:
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
यूज़र इंटरफ़ेस (यूआई) बनाना
यहां दिए गए स्निपेट में, यूज़र इंटरफ़ेस (यूआई) बनाने का तरीका बताया गया है:
/* 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). फ़ाइनल डिसप्ले, उपलब्ध जगह पर निर्भर करता है. यहां दी गई इमेज से पता चलता है कि यह कैसा दिख सकता है:
कॉम्पोनेंट की जगह और साइज़ बदलने के लिए, अलाइनमेंट की वैल्यू बदली जा सकती हैं या अलग-अलग मॉडिफ़ायर वैल्यू (जैसे, पैडिंग) लागू की जा सकती हैं. हर क्लास के लिए कॉम्पोनेंट, पैरामीटर, और उपलब्ध मॉडिफ़ायर की पूरी सूची देखने के लिए, रेफ़रंस दस्तावेज़ देखें.
गोल बॉर्डर लागू करना
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>