تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
تجربة طريقة "الكتابة"
Jetpack Compose هي مجموعة أدوات واجهة المستخدم التي يُنصح باستخدامها على Android. تعرَّف على كيفية إنشاء أدوات باستخدام واجهات برمجة التطبيقات المتوافقة مع Compose.
يمكنك استدعاء هذه الطرق من أي مكان في تطبيقك، طالما أنّ التطبيق لديه معرّف UID نفسه مثل فئة AppWidgetProvider المقابلة.
تحديد عدد مرات تحديث أداة
يتم تعديل التطبيقات المصغّرة بشكل دوري استنادًا إلى القيمة المقدَّمة للسمة
updatePeriodMillis. ويمكن أن يتم تعديلها استجابةً لتفاعل المستخدم أو بث التعديلات أو كليهما.
التحديث بشكل دوري
يمكنك التحكّم في معدّل تكرار التحديث الدوري من خلال تحديد قيمة AppWidgetProviderInfo.updatePeriodMillis في ملف appwidget-provider XML. يؤدي كل تحديث إلى تشغيل الطريقة AppWidgetProvider.onUpdate()، وهي المكان الذي يمكنك فيه وضع الرمز لتحديث الأداة. ومع ذلك، ننصحك بالاطّلاع على بدائل لتحديثات أداة استقبال البث الموضّحة في القسم التالي إذا كانت الأداة تحتاج إلى تحميل البيانات بشكل غير متزامن أو تستغرق أكثر من 10 ثوانٍ للتحديث، لأنّه بعد 10 ثوانٍ، يعتبر النظام BroadcastReceiver غير مستجيب.
لا تتيح الدالة updatePeriodMillis استخدام قيم أقل من 30 دقيقة. ومع ذلك، إذا أردت إيقاف التحديثات الدورية، يمكنك تحديد القيمة 0.
يمكنك السماح للمستخدمين بضبط عدد مرات التحديث في عملية الإعداد. على سبيل المثال، قد يريدون أن يتم تعديل مؤشر الأسهم كل 15 دقيقة أو أربع مرات فقط في اليوم. في هذه الحالة، اضبط updatePeriodMillis على 0 واستخدِم
WorkManager بدلاً من ذلك.
تعديل استجابةً لتفاعل المستخدم
في ما يلي بعض الطرق المقترَحة لتعديل الأداة استنادًا إلى تفاعل المستخدم:
من نشاط التطبيق: يمكنك طلب
AppWidgetManager.updateAppWidget مباشرةً استجابةً لتفاعل المستخدم، مثل
نقرة المستخدم.
من التفاعلات عن بُعد، مثل الإشعارات أو أدوات التطبيقات:
أنشئ PendingIntent، ثم عدِّل الأداة من Activity أو Broadcast أو Service الذي تم استدعاؤه. يمكنك اختيار الأولوية التي تريدها. على سبيل المثال، إذا اخترت Broadcast لـ PendingIntent، يمكنك اختيار بث في المقدّمة لمنح BroadcastReceiver الأولوية.
تعديل استجابة لحدث بث
من الأمثلة على أحداث البث التي تتطلّب تحديث تطبيق مصغّر عندما يلتقط المستخدم صورة. في هذه الحالة، عليك تعديل التطبيق المصغّر عند رصد صورة جديدة.
يمكنك أيضًا تسجيل BroadcastReceiver للبث، مثلاً، الاستماع إلى ACTION_LOCALE_CHANGED.
ومع ذلك، بما أنّ هذه العملية تستهلك موارد الجهاز، يجب استخدامها بحذر والاستماع فقط إلى البث المحدّد. مع طرح قيود البث في الإصدار 7.0 من نظام التشغيل Android (المستوى 24 من واجهة برمجة التطبيقات) والإصدار 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، لا يمكن للتطبيقات تسجيل عمليات البث الضمنية في بياناتها، مع بعض الاستثناءات.
اعتبارات عند تعديل تطبيق مصغّر من BroadcastReceiver
إذا تم تحديث التطبيق المصغَّر من BroadcastReceiver، بما في ذلك AppWidgetProvider، يُرجى الانتباه إلى الاعتبارات التالية بشأن مدة تحديث التطبيق المصغَّر وأولويته.
مدة التحديث
كقاعدة عامة، يسمح النظام لمستقبِلات البث، التي تعمل عادةً في سلسلة التعليمات الرئيسية للتطبيق، بالعمل لمدة تصل إلى 10 ثوانٍ قبل اعتبارها غير مستجيبة وتفعيل خطأ التطبيق لا يستجيب (ANR). لتجنُّب حظر سلسلة التعليمات الرئيسية أثناء معالجة البث، استخدِم طريقة goAsync. إذا استغرق تحديث التطبيق المصغّر وقتًا أطول، ننصحك بتحديد موعد لمهمة باستخدام WorkManager.
تُنفَّذ عمليات البث تلقائيًا كعمليات في الخلفية، بما في ذلك عمليات البث التي تتم باستخدام
AppWidgetProvider.onUpdate. وهذا يعني أنّ موارد النظام المحمّلة بشكل زائد يمكن أن تتسبّب في تأخير استدعاء أداة استقبال البث. لإعطاء الأولوية للبث، اجعله عملية في المقدّمة.
على سبيل المثال، أضِف العلامة
Intent.FLAG_RECEIVER_FOREGROUND
إلى Intent التي تم تمريرها إلى PendingIntent.getBroadcast عندما ينقر المستخدم
على جزء معيّن من الأداة.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-08-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-08-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["Try the Compose way \nJetpack Compose is the recommended UI toolkit for Android. Learn how to build widgets using Compose-style APIs. \n[Jetpack Glance →](/develop/ui/compose/glance) \n\n\u003cbr /\u003e\n\nThis page explains recommended practices for creating a more advanced widget for\na better user experience.\n\nOptimizations for updating widget content\n\nUpdating widget content can be computationally expensive. To save battery\nconsumption, optimize the update type, frequency, and timing.\n\nTypes of widget updates\n\nThere are three ways to update a widget: a full update, a partial update, and,\nin the case of a collection widget, a data refresh. Each has different\ncomputational costs and ramifications.\n\nThe following describes each update type and provides code snippets for each.\n\n- **Full update:** call [`AppWidgetManager.updateAppWidget(int,\n android.widget.RemoteViews)`](/reference/android/appwidget/AppWidgetManager#updateAppWidget(int,%20android.widget.RemoteViews))\n to fully update the widget. This replaces the previously provided\n [`RemoteViews`](/reference/android/widget/RemoteViews) with a new\n `RemoteViews`. This is the most computationally expensive update.\n\n Kotlin \n\n ```kotlin\n val appWidgetManager = AppWidgetManager.getInstance(context)\n val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also {\n setTextViewText(R.id.textview_widget_layout1, \"Updated text1\")\n setTextViewText(R.id.textview_widget_layout2, \"Updated text2\")\n }\n appWidgetManager.updateAppWidget(appWidgetId, remoteViews)\n ```\n\n Java \n\n ```java\n AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);\n RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);\n remoteViews.setTextViewText(R.id.textview_widget_layout1, \"Updated text1\");\n remoteViews.setTextViewText(R.id.textview_widget_layout2, \"Updated text2\");\n appWidgetManager.updateAppWidget(appWidgetId, remoteViews);\n ```\n- **Partial update:** call\n [`AppWidgetManager.partiallyUpdateAppWidget`](/reference/android/appwidget/AppWidgetManager#partiallyUpdateAppWidget(int,%20android.widget.RemoteViews))\n to update parts of the widget. This merges the new `RemoteViews` with the\n previously provided `RemoteViews`. This method is ignored if a widget\n doesn't receive at least one full update through [`updateAppWidget(int[],\n RemoteViews)`](/reference/android/appwidget/AppWidgetManager#updateAppWidget(android.content.ComponentName,%20android.widget.RemoteViews)).\n\n Kotlin \n\n ```kotlin\n val appWidgetManager = AppWidgetManager.getInstance(context)\n val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also {\n setTextViewText(R.id.textview_widget_layout, \"Updated text\")\n }\n appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)\n ```\n\n Java \n\n ```java\n AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);\n RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);\n remoteViews.setTextViewText(R.id.textview_widget_layout, \"Updated text\");\n appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews);\n ```\n- **Collection data refresh:** call\n [`AppWidgetManager.notifyAppWidgetViewDataChanged`](/reference/android/appwidget/AppWidgetManager#notifyAppWidgetViewDataChanged(int,%20int))\n to invalidate the data of a collection view in your widget. This triggers\n [`RemoteViewsFactory.onDataSetChanged`](/reference/android/widget/RemoteViewsService.RemoteViewsFactory#onDataSetChanged()).\n In the interim, the old data is displayed in the widget. You can safely\n perform expensive tasks synchronously with this method.\n\n Kotlin \n\n ```kotlin\n val appWidgetManager = AppWidgetManager.getInstance(context)\n appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)\n ```\n\n Java \n\n ```java\n AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);\n appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview);\n ```\n\nYou can call these methods from anywhere in your app, as long as the app has the\nsame UID as the corresponding\n[`AppWidgetProvider`](/reference/android/appwidget/AppWidgetProvider) class.\n\nDetermine how often to update a widget\n\nWidgets are updated periodically depending on the value provided for the\n[`updatePeriodMillis`](/reference/android/appwidget/AppWidgetProviderInfo#updatePeriodMillis)\nattribute. The widget can update in response to user interaction, broadcast\nupdates, or both.\n\nUpdate periodically\n\nYou can control the frequency of the periodic update by specifying a value for\n`AppWidgetProviderInfo.updatePeriodMillis` in the `appwidget-provider` XML. Each\nupdate triggers the `AppWidgetProvider.onUpdate()` method, which is where you\ncan place the code to update the widget. However, consider the [alternatives for\nbroadcast receiver updates](#broadcastreceiver-duration) described in a\nfollowing section if your widget needs to load data asynchronously or takes more\nthan 10 seconds to update, because after 10 seconds, the system considers a\n`BroadcastReceiver` to be non-responsive.\n\n`updatePeriodMillis` doesn't support values of less than 30 minutes. However, if\nyou want to disable periodic updates, you can specify 0.\n\nYou can let users adjust the frequency of updates in a configuration. For\nexample, they might want a stock ticker to update every 15 minutes or only four\ntimes a day. In this case, set the `updatePeriodMillis` to 0 and use\n[`WorkManager`](/topic/libraries/architecture/workmanager) instead.\n| **Note:** Using repeating tasks with `WorkManager` is a good option, but similar power restrictions apply. See [App Standby\n| Buckets](/about/versions/pie/power#buckets) for more information.\n\nUpdate in response to a user interaction\n\nHere are some recommended ways to update the widget based on user interaction:\n\n- **From an activity of the app:** directly call\n `AppWidgetManager.updateAppWidget` in response to a user interaction, such\n as a user's tap.\n\n- **From remote interactions, such as a notification or an app widget:**\n construct a `PendingIntent`, then update the widget from the invoked\n `Activity`, `Broadcast`, or `Service`. You can choose your own priority. For\n example, if you select a `Broadcast` for the `PendingIntent`, you can choose\n a [foreground broadcast](#broadcastreceiver-priority) to give the\n `BroadcastReceiver` priority.\n\nUpdate in response to a broadcast event\n\nAn example of a broadcast event that requires a widget to update is when the\nuser takes a photo. In this case, you want to update the widget when a new photo\nis detected.\n\nYou can schedule a job with `JobScheduler` and specify a broadcast as the\ntrigger using the\n[`JobInfo.Builder.addTriggerContentUri`](/reference/android/app/job/JobInfo.Builder#addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri))\nmethod.\n\nYou can also register a `BroadcastReceiver` for the broadcast---for example,\nlistening for\n[`ACTION_LOCALE_CHANGED`](/reference/android/content/Intent#ACTION_LOCALE_CHANGED).\nHowever, because this consumes device resources, use this with care and listen\nonly to the specific broadcast. With the introduction of [broadcast\nlimitations](/about/versions/oreo/background#broadcasts) in Android\n7.0 (API level 24) and Android 8.0 (API level 26), apps can't register implicit\nbroadcasts in their manifests, with certain\n[exceptions](/guide/components/broadcast-exceptions).\n\nConsiderations when updating a widget from a BroadcastReceiver\n\nIf the widget is updated from a `BroadcastReceiver`, including\n`AppWidgetProvider`, be aware of the following considerations regarding the\nduration and priority of a widget update.\n\nDuration of the update\n\nAs a rule, the system lets broadcast receivers, which usually run in the app's\nmain thread, run for up to 10 seconds before considering them non-responsive and\ntriggering an [Application Not\nResponding](/topic/performance/vitals/anr) (ANR) error. To avoid blocking the\nmain thread while handling the broadcast, use the\n[`goAsync`](/reference/android/content/BroadcastReceiver#goAsync()) method. If it takes\nlonger to update the widget, consider scheduling a task\nusing [`WorkManager`](/reference/androidx/work/WorkManager). \n\n Caution: Any work you do here blocks further broadcasts until it completes,\n so it can slow the receiving of later events.\n\nSee [Security considerations and best\npractices](/guide/components/broadcasts#security-and-best-practices) for more\ninformation.\n\nPriority of the update\n\nBy default, broadcasts---including those made using\n`AppWidgetProvider.onUpdate`---run as background processes. This means\noverloaded system resources can cause a delay in the invocation of the broadcast\nreceiver. To prioritize the broadcast, make it a foreground process.\n\nFor example, add the\n[`Intent.FLAG_RECEIVER_FOREGROUND`](/reference/android/content/Intent#FLAG_RECEIVER_FOREGROUND)\nflag to the `Intent` passed to the `PendingIntent.getBroadcast` when the user\ntaps on a certain part of the widget."]]