برای برنامه‌تان کاشی‌های «تنظیمات فوری» سفارشی بسازید

«تنظیمات فوری» کاشی‌هایی هستند که در پانل «تنظیمات فوری» نمایش داده می‌شوند و کنش‌ها را نشان می‌دهند. کاربران می‌توانند روی آن‌ها ضربه بزنند تا تکالیف تکرارشونده را به‌سرعت تکمیل کنند. برنامه شما می‌تواند ازطریق کلاس TileService کاشی سفارشی به کاربران ارائه دهد و از شیء Tile برای پیگیری وضعیت کاشی استفاده کند. برای مثال، می‌توانید کاشی‌ای بسازید که به کاربران امکان دهد وی‌پی‌ان ارائه‌شده توسط برنامه‌تان را روشن یا خاموش کنند.

پانل «تنظیمات فوری» با کاشی وی‌پی‌ان روشن و خاموش
شکل ۱. پانل «تنظیمات فوری» با کاشی VPN روشن و خاموش.

تصمیم بگیرید چه زمانی کاشی ایجاد شود

توصیه می‌کنیم برای عملکردهای خاصی که انتظار دارید کاربران یا اغلب به آن‌ها دسترسی داشته باشند یا به دسترسی سریع به آن‌ها نیاز داشته باشند (یا هر دو)، کاشی ایجاد کنید. مؤثرترین کاشی‌ها آن‌هایی هستند که هر دو این کیفیت‌ها را داشته باشند و دسترسی سریع به کنش‌های پرتکرار را فراهم کنند.

برای مثال، می‌توانید کاشی‌ای برای برنامه تناسب اندام ایجاد کنید که به کاربران امکان می‌دهد به‌سرعت جلسه تمرین را شروع کنند. بااین‌حال، توصیه نمی‌کنیم کاشی‌ای برای همان برنامه ایجاد کنید که به کاربران اجازه دهد کل سابقه تمرین خود را مرور کنند.

موارد استفاده کاشی برنامه تناسب اندام
شکل ۲. نمونه‌هایی از کاشی‌های توصیه‌شده درمقایسه با کاشی‌های توصیه‌نشده برای برنامه تناسب اندام.

برای کمک به بهبود قابلیت شناسایی و سهولت استفاده از کاشی، توصیه می‌کنیم از برخی‌از روش‌ها اجتناب کنید:

  • برای راه‌اندازی برنامه از کاشی استفاده نکنید. درعوض از میان‌بر برنامه یا راه‌انداز استاندارد استفاده کنید.

  • از کاشی‌ها برای اقدامات یک‌باره کاربر استفاده نکنید. درعوض از میان‌بر برنامه یا اعلان استفاده کنید.

  • از ایجاد کاشی‌های زیاد خودداری کنید. توصیه می‌کنیم حداکثر دو میان‌بر برای هر برنامه استفاده کنید. به‌جای آن از میان‌بر برنامه استفاده کنید.

  • از استفاده از کاشی‌هایی که اطلاعات را نمایش می‌دهند اما برای کاربران تعاملی نیستند اجتناب کنید. درعوض از اعلان یا ابزاره استفاده کنید.

ایجاد کاشی

برای ایجاد کاشی، ابتدا باید نماد کاشی مناسبی ایجاد کنید، سپس TileService را در فایل مانیفست برنامه‌تان ایجاد و اعلام کنید.

نمونه «تنظیمات فوری» نمونه‌ای از نحوه ایجاد و مدیریت کاشی ارائه می‌دهد.

ایجاد نماد سفارشی

باید نماد سفارشی‌ای ارائه دهید که در کاشی پانل «تنظیمات سریع» نمایش داده می‌شود. (این نماد را هنگام اظهار TileService، که در بخش بعدی توضیح داده شده است، اضافه خواهید کرد.) نماد باید سفید یکدست با پس‌زمینه شفاف باشد، اندازه آن ۲۴ × ۲۴dp باشد، و به‌شکل VectorDrawable باشد.

نمونه‌ای از ترسیمی بُرداری
شکل ۳. نمونه‌ای از ترسیمی بُرداری.

نمادی ایجاد کنید که به‌صورت دیداری به هدف کاشی شما اشاره کند. این کار به کاربران کمک می‌کند تشخیص دهند کاشی شما با نیازهایشان مطابقت دارد یا نه. برای مثال، ممکن است برای کاشی برنامه تناسب اندام که به کاربران امکان می‌دهد جلسه تمرین را شروع کنند، نماد کرنومتر ایجاد کنید.

ایجاد و اعلام کردن TileService

سرویسی برای کاشی‌تان ایجاد کنید که کلاس TileService را گسترش دهد.

class MyQSTileService : TileService() {

    // Called when the user adds your tile.
    override fun onTileAdded() {
        super.onTileAdded()
    }
    // Called when your app can update your tile.
    override fun onStartListening() {
        super.onStartListening()
    }

    // Called when your app can no longer update your tile.
    override fun onStopListening() {
        super.onStopListening()
    }

    // Called when the user taps on your tile in an active or inactive state.
    override fun onClick() {
        super.onClick()
    }
    // Called when the user removes your tile.
    override fun onTileRemoved() {
        super.onTileRemoved()
    }
}

‫TileService را در فایل مانیفست برنامه‌تان اعلام کنید. نام و برچسب TileService (حداکثر ۱۸ نویسه برای android:label)، نماد سفارشی ایجادشده در بخش قبلی، و اجازه مناسب را اضافه کنید.

 <!-- 18-character limit for android:label. -->
 <service
     android:name=".MyQSTileService"
     android:exported="true"
     android:label="@string/my_default_tile_label"
     android:icon="@drawable/my_default_icon_label"
     android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
     <intent-filter>
         <action android:name="android.service.quicksettings.action.QS_TILE" />
     </intent-filter>
 </service>

مدیریت TileService

پس‌از اینکه TileService را در مانیفست برنامه‌تان ایجاد و اعلام کردید، باید وضعیت آن را مدیریت کنید.

‫TileService یک سرویس محدود است. TileService شما زمانی مقید می‌شود که برنامه‌تان درخواست کند یا اگر سیستم نیاز داشته باشد با آن ارتباط برقرار کند. چرخه حیات سرویس محدود معمولاً شامل چهار روش برگشتی زیر است: onCreate()، onBind()، onUnbind()، و onDestroy(). این روش‌ها هر بار که سرویس وارد مرحله جدیدی از چرخه حیات می‌شود توسط سیستم فراخوانی می‌شوند.

نمای کلی چرخه حیات TileService

علاوه‌بر توابع برگشتی که چرخه حیات سرویس پیوندی را کنترل می‌کنند، باید روش‌های دیگری را که مختص چرخه حیات TileService است پیاده‌سازی کنید. این روش‌ها ممکن است خارج از onCreate() و onDestroy() فراخوانی شوند زیرا روش‌های چرخه حیات Service و روش‌های چرخه حیات TileService در دو رشته ناهم‌زمان جداگانه فراخوانی می‌شوند.

چرخه حیات TileService شامل روش‌های زیر است که هر بار که TileService شما وارد مرحله جدیدی از چرخه حیات می‌شود، توسط سیستم فراخوانی می‌شوند:

  • onTileAdded(): این روش فقط زمانی فراخوانده می‌شود که کاربر کاشی شما را برای اولین‌بار اضافه کند، و اگر کاربر کاشی شما را بردارد و دوباره اضافه کند. این بهترین زمان برای انجام هرگونه مقداردهی اولیه یک‌باره است. بااین‌حال، این ممکن است همه راه‌اندازی‌های موردنیاز را برآورده نکند.

  • onStartListening() و onStopListening(): این روش‌ها هر زمان که برنامه‌تان کاشی را به‌روزرسانی می‌کند فراخوانده می‌شوند و اغلب فراخوانده می‌شوند. ‫TileService بین onStartListening() و onStopListening() همچنان محدود می‌ماند و به برنامه‌تان اجازه می‌دهد کاشی را تغییر دهد و به‌روزرسانی‌ها را ارسال کند.

  • onTileRemoved(): این روش فقط درصورتی فراخوانده می‌شود که کاربر کاشی شما را بردارد.

انتخاب حالت شنیداری

TileService شما در حالت فعال یا حالت غیرفعال گوش می‌دهد. توصیه می‌کنیم از حالت فعال استفاده کنید که باید آن را در مانیفست برنامه اعلام کنید. درغیراین‌صورت، TileService حالت استاندارد است و نیازی به اعلام ندارد.

فرض نکنید که TileService شما خارج از onStartListening() و onStopListening() جفت روش زندگی خواهد کرد.

از حالت فعال برای TileService استفاده کنید که در فرایند خودش به وضعیتش گوش می‌دهد و آن را پایش می‌کند. TileService در حالت فعال به onTileAdded()، onTileRemoved()، رویدادهای ضربه، و زمانی که فرایند برنامه درخواست می‌کند محدود می‌شود.

اگر TileService شما وقتی وضعیت کاشی باید توسط فرایند خودش به‌روز شود مطلع می‌شود، حالت فعال را توصیه می‌کنیم. کاشی‌های فعال فشار روی سیستم را کاهش می‌دهند زیرا هر بار که پانل «تنظیمات سریع» برای کاربر نمایان می‌شود، لازم نیست این کاشی‌ها پیوند داده شوند.

روش TileService.requestListeningState() ثابت را می‌توان برای درخواست شروع حالت شنیدن و دریافت فراخوانی به onStartListening() فراخوانی کرد.

با افزودن META_DATA_ACTIVE_TILE به فایل مانیفست برنامه‌تان می‌توانید حالت فعال را اعلام کنید.

<service ...>
    <meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
       android:value="true" />
    ...
</service>

حالت غیرفعال

حالت غیرفعال حالت استاندارد است. TileService در حالت غیرفعال است اگر هرزمان کاشی شما برای کاربر نمایان باشد، محدود باشد. این یعنی TileService شما ممکن است در زمان‌هایی خارج از کنترل شما دوباره ایجاد و محدود شود. همچنین ممکن است وقتی کاربر کاشی را مشاهده نمی‌کند، ازهم باز شود و ازبین برود.

پس‌از اینکه کاربر پانل «تنظیمات سریع» را باز کرد، برنامه شما یک بازخوانی به onStartListening() دریافت می‌کند. می‌توانید شیء Tile خود را هر چند بار که بخواهید بین onStartListening() و onStopListening() به‌روز کنید.

نیازی نیست حالت غیرفعال را اعلام کنید: META_DATA_ACTIVE_TILE را به فایل مانیفست برنامه‌تان اضافه نکنید.

نمای کلی وضعیت‌های کاشی

پس‌از اینکه کاربر کاشی شما را اضافه کرد، کاشی همیشه در یکی از حالت‌های زیر وجود دارد.

  • STATE_ACTIVE: نشان‌دهنده وضعیت روشن یا فعال است. کاربر می‌تواند در این حالت با کاشی شما تعامل داشته باشد.

    برای مثال، برای کاشی برنامه تناسب اندام که به کاربران امکان می‌دهد جلسه تمرین زمان‌دار را شروع کنند، STATE_ACTIVE به این معنی است که کاربر جلسه تمرین را شروع کرده است و زمان‌سنج درحال کار است.

  • STATE_INACTIVE: نشان‌دهنده وضعیت خاموش یا متوقف است. کاربر می‌تواند در این حالت با کاشی شما تعامل داشته باشد.

    برای استفاده مجدد از مثال کاشی برنامه تناسب اندام، کاشی در STATE_INACTIVE به این معنی است که کاربر جلسه تمرینی را شروع نکرده است، اما درصورت تمایل می‌تواند این کار را انجام دهد.

  • STATE_UNAVAILABLE: نشان‌دهنده وضعیت موقتاً دردسترس نبودن است. کاربر نمی‌تواند در این حالت با کاشی شما تعامل داشته باشد.

    برای مثال، کاشی در STATE_UNAVAILABLE یعنی کاشی درحال‌حاضر به‌دلایلی برای کاربر دردسترس نیست.

سیستم فقط وضعیت اولیه شیء Tile شما را تنظیم می‌کند. وضعیت Tile شیء را در طول بقیه چرخه حیات آن تنظیم می‌کنید.

سیستم ممکن است نماد کاشی و پس‌زمینه را رنگی کند تا وضعیت Tile شیء شما را منعکس کند. ‫Tile شیء تنظیم‌شده روی STATE_ACTIVE تاریک‌ترین است، با STATE_INACTIVE و STATE_UNAVAILABLE که به‌تدریج روشن‌تر می‌شوند. ته‌رنگ دقیق مختص سازنده و نسخه است.

کاشی VPN برای نشان دادن وضعیت‌های شیء رنگی شد
شکل ۴. نمونه‌هایی از کاشی رنگی برای نشان دادن وضعیت کاشی (وضعیت‌های فعال، غیرفعال، و دردسترس نبودن به‌ترتیب).

به‌روزرسانی کاشی

پس‌از دریافت تماس برگشتی به onStartListening()، می‌توانید کاشی‌تان را به‌روز کنید. بسته به حالت کاشی، کاشی شما می‌تواند حداقل یک‌بار تا دریافت تماس برگشتی به onStopListening() به‌روز شود.

در حالت فعال، می‌توانید کاشی‌تان را دقیقاً یک‌بار قبل‌از دریافت تماس برگشتی به onStopListening() به‌روز کنید. در حالت غیرفعال، می‌توانید کاشی‌تان را هر چند بار که می‌خواهید بین onStartListening() و onStopListening() به‌روز کنید.

با تماس گرفتن با getQsTile() می‌توانید شیء Tile را بازیابی کنید. برای به‌روزرسانی فیلدهای خاصی از شیء Tile، روش‌های زیر را فراخوانی کنید:

وقتی تنظیم فیلدهای شیء Tile روی مقادیر صحیح تمام شد، باید با updateTile() تماس بگیرید تا کاشی‌تان را به‌روز کنید. با این کار، سیستم داده‌های کاشی به‌روزشده را تجزیه می‌کند و واسط کاربر را به‌روز می‌کند.

data class StateModel(val enabled: Boolean, val label: String, val icon: Icon)

override fun onStartListening() {
    super.onStartListening()
    val state = getStateFromService()
    qsTile.label = state.label
    qsTile.contentDescription = state.label
    qsTile.state = if (state.enabled) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
    qsTile.icon = state.icon
    qsTile.updateTile()
}

مدیریت ضربه‌ها

اگر کاشی شما در STATE_ACTIVE یا STATE_INACTIVE باشد، کاربران می‌توانند روی کاشی شما تک‌ضرب بزنند تا کنشی را راه‌اندازی کنند. سپس سیستم onClick() برگشت‌تماس برنامه شما را فرا می‌خواند.

وقتی برنامه‌تان برای onClick() تماس برگشتی دریافت می‌کند، می‌تواند کادر گفتگویی یا فعالیتی راه‌اندازی کند، کار پس‌زمینه‌ای را راه‌اندازی کند، یا وضعیت کاشی را تغییر دهد.

var counter = 0
override fun onClick() {
    super.onClick()
    counter++
    qsTile.state = if (counter % 2 == 0) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
    qsTile.label = "Clicked $counter times"
    qsTile.contentDescription = qsTile.label
    qsTile.updateTile()
}

راه‌اندازی کادر گفتگو

showDialog() پانل «تنظیمات فوری» را جمع می‌کند و کادر گفتگویی را نشان می‌دهد. اگر کنش شما به ورودی اضافی یا موافقت کاربر نیاز دارد، از چارگوش گفتگو برای افزودن بافت به کنش استفاده کنید.

راه‌اندازی فعالیت

startActivityAndCollapse() فعالیتی را شروع می‌کند و پانل را جمع می‌کند. اگر اطلاعات دقیق‌تری برای نمایش دادن وجود داشته باشد یا اگر کنش شما بسیار تعاملی باشد، فعالیت‌ها مفید هستند.

اگر برنامه شما به تعامل کاربر قابل‌توجهی نیاز دارد، برنامه باید فعالیت را فقط به‌عنوان آخرین راهکار راه‌اندازی کند. به‌جای آن، از یک گفتگو یا یک دکمه تغییر وضعیت استفاده کنید.

با فشار طولانی روی کاشی، صفحه اطلاعات برنامه برای کاربر باز می‌شود. برای ملغی کردن این رفتار و به‌جای آن راه‌اندازی فعالیتی برای تنظیم اولویت‌ها، <intent-filter> را به یکی از فعالیت‌هایتان با ACTION_QS_TILE_PREFERENCES اضافه کنید.

از Android API 28، PendingIntent باید Intent.FLAG_ACTIVITY_NEW_TASK را داشته باشد:

if (Build.VERSION.SDK_INT >= 28) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}

همچنین می‌توانید پرچم را در AndroidManifest.xml در بخش خاص Activity اضافه کنید.

علامت‌گذاری کاشی به‌عنوان قابل‌تغییر

توصیه می‌کنیم کاشی‌تان را به‌عنوان قابل‌تغییر علامت‌گذاری کنید اگر عمدتاً به‌عنوان یک کلید دوحالته عمل می‌کند (که رایج‌ترین رفتار کاشی‌ها است). این کار به ارائه اطلاعات درباره عملکرد کاشی به سیستم عامل و بهبود دسترسی‌پذیری کلی کمک می‌کند.

فراداده TOGGLEABLE_TILE را روی true تنظیم کنید تا کاشی‌تان به‌عنوان قابل‌تغییر علامت‌گذاری شود.

<service ...>
  <meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
    android:value="true" />
</service>

فقط کنش‌های ایمن را در دستگاه‌های ایمن قفل‌شده انجام دهید

کاشی شما ممکن است در بالای صفحه قفل در دستگاه‌های قفل‌شده نمایش داده شود. اگر کاشی حاوی اطلاعات حساس است، مقدار isSecure() را بررسی کنید تا مشخص شود دستگاه در وضعیت امنی قرار دارد یا نه، و TileService شما باید رفتار خود را براساس آن تغییر دهد.

اگر کنش کاشی در حالت قفل ایمن است، از startActivity() برای راه‌اندازی فعالیت در بالای صفحه قفل استفاده کنید.

اگر کنش کاشی ناامن است، از unlockAndRun() برای درخواست از کاربر برای باز کردن قفل دستگاهش استفاده کنید. اگر موفقیت‌آمیز باشد، سیستم شیء Runnable را که به این روش ارسال می‌کنید اجرا می‌کند.

دسته‌بندی کردن کاشی

برای بهبود تجربه کاربری در «تنظیمات فوری»، می‌توانید کاشی‌تان را دسته‌بندی کنید. سیستم کاشی‌ها را در دسته‌هایی مثل «اتصال‌پذیری»، «نمایشگر»، و «حریم خصوصی» سازمان‌دهی می‌کند. سیستم از این دسته‌ها برای مرتب‌سازی و گروه‌بندی کاشی‌ها در حالت ویرایش «تنظیمات سریع» استفاده می‌کند که باعث می‌شود کاربران راحت‌تر آن‌ها را پیدا و مدیریت کنند.

پیاده‌سازی

برای مشخص کردن دسته‌ای برای TileService خود، فیلد فراداده‌ای به اعلان سرویس در فایل AndroidManifest.xml اضافه کنید:

  • در AndroidManifest.xml، در عنصر <service> برای TileService، عنصر <meta-data> را اضافه کنید.
  • android:name: این مقدار را روی android.service.quicksettings.TILE_CATEGORY تنظیم کنید.
  • ‫android:value: یکی از ثابت‌های دسته ازپیش تعریف‌شده را، مثل android.service.quicksettings.CATEGORY_CONNECTIVITY یا android.service.quicksettings.CATEGORY_DISPLAY، اختصاص دهید.

همان‌طور که در مثال زیر نشان داده شده است:

<service
    android:name=".MyConnectivityTileService"
    [...]
    >
    <meta-data android:name="android.service.quicksettings.TILE_CATEGORY"
        android:value="android.service.quicksettings.CATEGORY_CONNECTIVITY" />
</service>

این API مجموعه‌ای از دسته‌های ازپیش تعریف‌شده را برای انتخاب ارائه می‌دهد. این دسته‌ها به‌صورت ثابت‌های رشته‌ای در کلاس TileService تعریف شده‌اند.

اگر دسته‌ای مشخص نشده باشد، سیستم به‌طور خودکار دسته پیش‌فرضی را اختصاص می‌دهد:

  • از برنامه‌های سیستم: برای کاشی‌هایی که بخشی از یک برنامه سیستم هستند.
  • از برنامه‌هایی که نصب کرده‌اید: برای کاشی‌های برنامه‌های نصب‌شده توسط کاربر.

اگرچه دستگاه‌های Google Pixel از دسته‌بندی‌ها در «تنظیمات فوری» استفاده می‌کنند، تولیدکنندگان تجهیزات اصلی می‌توانند از این اطلاعات دسته‌بندی در واسط‌های کاربر سیستم مربوطه استفاده کنند یا آن‌ها را نادیده بگیرند.

از کاربر بخواهید کاشی‌تان را اضافه کند

برای افزودن دستی کاشی، کاربران باید چند مرحله را دنبال کنند:

  1. برای باز کردن پانل «تنظیمات فوری»، تند به‌پایین بکشید.
  2. روی دکمه ویرایش تک‌ضرب بزنید.
  3. در همه کاشی‌های دستگاهش پیمایش کند تا کاشی شما را پیدا کند.
  4. کاشی را نگه دارید و آن را به فهرست کاشی‌های فعال بکشید.

کاربر همچنین می‌تواند کاشی شما را در هر زمانی جابه‌جا یا حذف کند.

از Android 13، می‌توانید از روش requestAddTileService() استفاده کنید تا کاربران بتوانند بسیار راحت‌تر کاشی شما را به دستگاه اضافه کنند. این روش با درخواست از کاربران، آن‌ها را ترغیب می‌کند کاشی‌تان را مستقیماً به پانل «تنظیمات فوری» اضافه کنند. پیام‌واره شامل نام برنامه، برچسب ارائه‌شده، و نماد است.

پیام‌واره «میانای برنامه‌سازی کاربردی جای‌گذاری تنظیمات فوری»
شکل ۵. پیام‌واره «میانای برنامه‌سازی کاربردی جای‌گذاری تنظیمات فوری».
public void requestAddTileService (
  ComponentName tileServiceComponentName,
  CharSequence tileLabel,
  Icon icon,
  Executor resultExecutor,
  Consumer<Integer> resultCallback
)

این برگشتی حاوی اطلاعاتی درباره اینکه کاشی اضافه شده است یا نه، اگر ازقبل وجود داشته است، یا اگر خطایی رخ داده است، می‌باشد.

هنگام تصمیم‌گیری درباره زمان و تعداد دفعات درخواست از کاربران، محتاط باشید. توصیه می‌کنیم فقط در بافتار، مثلاً وقتی کاربر برای اولین‌بار با ویژگی‌ای که کاشی شما تسهیل می‌کند تعامل برقرار می‌کند، با requestAddTileService() تماس بگیرید.

اگر کاربر قبلاً درخواست‌های مربوط به یک ComponentName را به تعداد کافی رد کرده باشد، سیستم می‌تواند پردازش درخواست‌های مربوط به آن را متوقف کند. کاربر از Context استفاده‌شده برای بازیابی این سرویس تعیین می‌شود: باید با کاربر فعلی مطابقت داشته باشد.