توضّح الأقسام التالية كيفية إنشاء تطبيق مصغّر أساسي باستخدام 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 هو عدم توفّر ملف XML لـ initialLayout، ولكن عليك تحديد ملف. يمكنك استخدام تنسيق التحميل المحدّد مسبقًا في
المكتبة:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
تعريف ملف XML الخاص بـ AppWidgetProviderInfo
يحدّد العنصر AppWidgetProviderInfo السمات الأساسية لأداتك. حدِّد AppWidgetProviderInfo في ملف موارد البيانات الوصفية بتنسيق XML
(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 (الإصدار 12 من نظام التشغيل Android) وminWidth وminHeight |
targetCellWidth وtargetCellHeight، وminWidth وminHeight، لكي يتمكّن تطبيقك من استخدام minWidth وminHeight إذا كان جهاز المستخدم لا يتوافق مع targetCellWidth وtargetCellHeight. في حال توفّر السمتَين 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 بكسل غير مرتبط بالكثافة وارتفاعها 50 بكسل غير مرتبط بالكثافة.
- يتم توفير مواصفات السمات التالية:
<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 كالحجم التلقائي
للأداة.
حجم التطبيق المصغّر هو 2×2 تلقائيًا. يمكن تغيير حجم التطبيق المصغّر إلى 2x1 أو إلى 4x3.
الإصدار 11 من نظام التشغيل Android والإصدارات الأقدم:
استخدِم السمتَين minWidth وminHeight لاحتساب الحجم التلقائي
للأداة.
العرض التلقائي = Math.ceil(80 / 30) = 3
الارتفاع التلقائي = Math.ceil(80 / 50) = 2
يكون حجم التطبيق المصغّر 3×2 تلقائيًا. يمكن تغيير حجم التطبيق المصغّر إلى 2x1 أو إلى وضع ملء الشاشة.
سمات التطبيقات المصغّرة الإضافية
يوضّح الجدول التالي سمات <appwidget-provider> المتعلّقة
بخصائص أخرى غير حجم التطبيق المصغّر.
| السمات والوصف | |
|---|---|
updatePeriodMillis |
يحدّد هذا الإعداد عدد المرات التي يطلب فيها إطار عمل التطبيق المصغّر تحديثًا من
GlanceAppWidgetReceiver من خلال استدعاء طريقة رد الاتصال
onUpdate(). ننصحك بتعديل البيانات بأقل معدّل ممكن، أي مرة واحدة في الساعة كحد أقصى، للحفاظ على عمر البطارية.
لمعرفة التفاصيل، يُرجى الاطّلاع على قسم حالات تحديث التطبيقات المصغّرة في إدارة حالة Glance. |
initialLayout |
يشير إلى مورد التصميم الذي يحدّد تصميم تحميل التطبيق المصغّر قبل عرض تركيبات واجهة مستخدم Glance. يمكنك استخدام تنسيق التحميل المحدّد مسبقًا في المكتبة: @layout/glance_default_loading_layout. |
configure |
تحدِّد نشاط الإعداد الذي يتم تشغيله عندما يضيف المستخدم التطبيق المصغّر. يُرجى الاطّلاع على دليل السماح للمستخدمين بضبط تطبيقات مصغّرة. |
description |
يحدّد الوصف الذي ستعرضه أداة اختيار التطبيقات المصغّرة لتطبيقك المصغّر. تم طرح هذه الميزة في Android 12. |
previewLayout (الإصدار 12 من نظام التشغيل Android) وpreviewImage (الإصدار 11 من نظام التشغيل Android والإصدارات الأقدم) |
|
autoAdvanceViewId |
يحدّد رقم تعريف العرض الفرعي للتطبيق المصغّر الذي يتم الانتقال التلقائي إليه من خلال مضيف التطبيق المصغّر. |
widgetCategory |
تحدّد ما إذا كان يمكن عرض التطبيق المصغّر على الشاشة الرئيسية
(home_screen) أو شاشة القفل (keyguard) أو كلتيهما. بالنسبة إلى الإصدار 5.0 من Android والإصدارات الأحدث، لا يكون سوى 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") } } }
يمكنك إنشاء مثيل له في
glanceAppWidgetعلىGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
لقد تمكّنت الآن من إعداد AppWidget باستخدام Glance.
إدارة ذاكرة صور التطبيقات المصغّرة في مجموعات الأحجام المختلفة
عندما يعرض تطبيقك المصغّر صورًا نقطية أو معرّفات موارد منتظمة (URI) لصور content://، يجب إبقاء إجمالي ذاكرة صور RemoteViews المتسلسلة ضمن حدود النظام (6 * width *
height بايت، ويتم فرض ذلك باستخدام IllegalArgumentException على Android 17 والإصدارات الأحدث) من خلال اتّباع الخطوات التالية:
- فك ترميز الصور النقطية المشتركة قبل
provideContent: إذا كان التطبيق المصغّر يستخدمSizeMode.ResponsiveأوSizeMode.Exact، يشغّل Glance دالة lambdaprovideContentمرة واحدة لكل مجموعةDpSize. يؤدي فك ترميزBitmapداخلprovideContentإلى تخصيص مثيلBitmapمنفصل لكل مجموعة، ما يضاعف استخدام الذاكرة فيRemoteViews.mBitmapCache. يتم فك ترميز الصور النقطية التي تم تقليل حجمها (Bitmap.Config.RGB_565للصور غير الشفافة) مرة واحدة داخلprovideGlanceقبلprovideContentحتى تشارك جميع المجموعات مرجعBitmapواحدًا. استخدام عملية الاستيراد المطابقة لـ
ImageProvider: يوفّر Jetpack Glance نوعَين مختلفَين من التحميل الزائد لـImageProviderفي حزمتَين:- استخدِم
import androidx.glance.ImageProviderعند تمرير موردImageProvider(bitmap: Bitmap)أو مورد قابل للرسمImageProvider(resId: Int)في الذاكرة. - استخدِم
import androidx.glance.appwidget.ImageProviderعند تمرير معرّف موارد منتظم (URI)ImageProvider(uri: Uri). عند عرض الملفات المخزّنة مؤقتًا من خلال معرّف موارد منتظم (URI) لـFileProvider، يجب منحIntent.FLAG_GRANT_READ_URI_PERMISSIONلكل حزمة مشغّلIntent.CATEGORY_HOMEمثبّتة ليتمكّن المضيف من عرض الصورة.
- استخدِم
استخدام فئة GlanceAppWidgetReceiver لمعالجة عمليات بث التطبيقات المصغّرة
تبثّ أداة الإحداثيات GlanceAppWidgetReceiver تحديثات حالة المنصة من خلال توسيع نطاق AppWidgetProvider الأساسي. ويتلقّى أحداث النظام الأساسي عند تعديل التطبيق المصغّر أو حذفه أو تفعيله أو إيقافه، ويترجمها إلى طلبات مراحل النشاط في Compose.
تعريف التطبيق المصغّر في البيان
يجب الإعلان عن الفئة الفرعية لفئة GlanceAppWidgetReceiver كمستقبل بث في ملف AndroidManifest.xml:
<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 التي تحدّد فئة المستلِم. يجب أن يقبل المستلِم إجراء البث ACTION_APPWIDGET_UPDATE داخل <intent-filter>.
يجب أن يحدّد العنصر <meta-data> اسمه على أنّه
android.appwidget.provider، ويجب أن تشير السمة android:resource إلى
مورد البيانات الوصفية AppWidgetProviderInfo XML (@xml/my_app_widget_info).
تنفيذ فئة GlanceAppWidgetReceiver
في Glance، يمكنك توسيع GlanceAppWidgetReceiver بدلاً من
AppWidgetProvider مباشرةً. يمكنك تنفيذ ذلك من خلال ربط جهاز الاستقبال بنسخة 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باستخدام دالة lambda. الترتيب مهم.
يمكنك تغيير قيم المحاذاة أو تطبيق قيم معدّلة مختلفة (مثل الحشو) لتغيير موضع المكونات وحجمها. يمكنك الاطّلاع على المستندات المرجعية للحصول على قائمة كاملة بالمكوّنات والمَعلمات والمعدِّلات المتاحة لكل فئة.
تنفيذ الزوايا المستديرة
يقدّم 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>