ایجاد ابزاره برنامه با Glance

بخش‌های زیر نحوه ایجاد ابزاره برنامه پایه با 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 XML وجود ندارد، اما باید یکی تعریف کنید. می‌توانید از چیدمان بارگیری ازپیش تعریف‌شده ارائه‌شده در کتابخانه استفاده کنید:

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

اعلام کردن AppWidgetProviderInfo XML

شیء 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 (Android 12)، minWidth و minHeight
  • از Android 12، مشخصه‌های targetCellWidth و targetCellHeight اندازه پیش‌فرض ابزاره را ازنظر سلول‌های شبکه مشخص می‌کنند. این مشخصه‌ها در Android نسخه ۱۱ و پایین‌تر نادیده گرفته می‌شوند و اگر صفحه اصلی از چیدمان شبکه‌ای پشتیبانی نکند، می‌توان آن‌ها را نادیده گرفت.
  • مشخصه‌های 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 استفاده کنید.

مثال

برای نشان دادن اینکه چگونه مشخصه‌های جدول قبلی بر اندازه ابزاره تأثیر می‌گذارند، مشخصات زیر را فرض کنید:

  • سلول توری ۳۰ دی‌پی پهنا و ۵۰ دی‌پی ارتفاع دارد.
  • مشخصات مشخصه زیر ارائه شده است:
<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 به‌عنوان اندازه پیش‌فرض ابزاره استفاده کنید.

اندازه ابزاره به‌طور پیش‌فرض ۲×۲ است. اندازه ابزاره را می‌توان تا ۲×۱ کوچک یا تا ۴×۳ بزرگ کرد.

‫Android 11 و نسخه‌های پایین‌تر:

از مشخصه‌های minWidth و minHeight برای محاسبه اندازه پیش‌فرض ابزاره استفاده کنید.

پهنای پیش‌فرض = Math.ceil(80 / 30) = 3

ارتفاع پیش‌فرض = Math.ceil(80 / 50) = ۲

اندازه ابزاره به‌طور پیش‌فرض ۳×۲ است. اندازه ابزاره را می‌توان تا ۲×۱ کوچک کرد یا تا تمام‌صفحه بزرگ کرد.

مشخصه‌های اضافی ابزاره

جدول زیر مشخصه‌های <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 پیش‌نمایش مقیاس‌پذیری را مشخص می‌کند که آن را به‌عنوان چیدمان XML تنظیم‌شده روی اندازه پیش‌فرض ابزاره ارائه می‌دهید. در حالت ایده‌آل، این به نگاشت XML ایستایی اشاره می‌کند که با چیدمان طراحی شما مطابقت دارد.
  • در Android 11 یا نسخه‌های پایین‌تر، ویژگی previewImage نماگرفت قابل‌ترسیم تصویر ثابتی را از ظاهر ابزاره مشخص می‌کند که در انتخابگر ابزاره نشان داده می‌شود.
توصیه می‌کنیم هر دو را مشخص کنید تا برنامه‌تان به‌خوبی در پلاتفرم‌های قدیمی‌تر اجرا شود. برای پلاتفرم‌های جدیدتر (Android 15 و بالاتر)، می‌توانید پیش‌نمایش‌های تولیدشده زنده را در Kotlin بااستفاده از `GlanceAppWidget.providePreview` تعریف کنید. راهنمای پیش‌نمایش‌های تولیدشده را ببینید.
autoAdvanceViewId شناسه نمای زیرنمای ابزاره را که به‌طور خودکار توسط میزبان ابزاره پیش می‌رود مشخص می‌کند.
widgetCategory اعلام می‌کند که ابزاره شما می‌تواند در صفحه اصلی (home_screen)، صفحه قفل (keyguard)، یا هر دو نمایش داده شود. برای Android نسخه ۵.۰ و بالاتر، فقط 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. آن را در glanceAppWidget در GlanceAppWidgetReceiver خود نمونه‌سازی کنید:

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

اکنون AppWidget را بااستفاده از Glance پیکربندی کرده‌اید.

مدیریت حافظه تصویر ابزاره در اندازه‌های مختلف

وقتی ابزاره شما نقشه‌های بیتی یا شناسه منبع یکسان تصویر content:// را نمایش می‌دهد، با انجام کارهای زیر، کل حافظه تصویر سریالی‌شده RemoteViews را در محدوده سیستم (6 * width * height بایت، که با IllegalArgumentException در Android نسخه ۱۷ و بالاتر اعمال می‌شود) نگه دارید:

  • رمزگشایی نقشه‌های بیتی هم‌رسانی‌شده قبل‌از provideContent: اگر ابزاره شما از SizeMode.Responsive یا SizeMode.Exact استفاده می‌کند، Glance عبارت لامبدا provideContent را یک‌بار برای هر دسته DpSize اجرا می‌کند. رمزگشایی Bitmap در داخل provideContent برای هر دسته، نمونه Bitmap جداگانه‌ای اختصاص می‌دهد، و مصرف حافظه را در RemoteViews.mBitmapCache چندبرابر می‌کند. نقشه‌های بیتی با نمونه‌برداری کاهشی (Bitmap.Config.RGB_565 برای تصاویر مات) را یک‌بار در داخل provideGlance قبل‌از provideContent رمزگشایی کنید تا همه دسته‌ها یک مرجع Bitmap مشترک داشته باشند.
  • از وارد کردن ImageProvider منطبق استفاده کنید: Jetpack Glance دو سرریز ImageProvider متمایز در دو بسته ارائه می‌دهد:

    • هنگام ارسال منبع ترسیم‌شدنی ImageProvider(bitmap: Bitmap) یا درون‌حافظه‌ای ImageProvider(resId: Int)، از import androidx.glance.ImageProvider استفاده کنید.
    • هنگام ارسال URI، از import androidx.glance.appwidget.ImageProvider استفاده کنید ImageProvider(uri: Uri). هنگام ارائه فایل‌های ذخیره‌شده در حافظه نهان ازطریق FileProvider URI، به هر بسته راه‌انداز Intent.CATEGORY_HOME نصب‌شده Intent.FLAG_GRANT_READ_URI_PERMISSION اعطا کنید تا میزبان بتواند تصویر را ارائه دهد.

از کلاس 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 باید به منبع فراداده XML‏ 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 اهداف همه‌فرستی ابزاره پلاتفرم بنیادی زیر را فیلتر و مدیریت می‌کند:

ایجاد میانای کاربر

قطعه کد زیر نحوه ایجاد واسط کاربر را نشان می‌دهد:

/* 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: شعاع گوشه محفظه پس‌زمینه ابزاره را مشخص می‌کند (هرگز بزرگ‌تر از ۲۸ dp نیست).
  • شعاع داخلی: برای جلوگیری از برش محتوا، شعاع متناسبی را برای محتوای داخلی خود براساس طرح کلی پس‌زمینه سیستم محاسبه کنید: systemRadiusValue - widgetPadding

در Glance، می‌توانید ویژگی‌های اندازه شعاع گوشه را به‌طور پویا در ترکیب‌بندی بااستفاده از GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius) اعمال کنید.

برای سازگاری با نسخه‌های قدیمی در دستگاه‌هایی که Android 11 (سطح میانای برنامه‌سازی کاربردی ۳۰) یا پایین‌تر را اجرا می‌کنند، مشخصه‌های سفارشی و منابع زمینه سفارشی جایگزین را پیاده‌سازی کنید:

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