إنشاء مربّعات مخصّصة للإعدادات السريعة لتطبيقك

"الإعدادات السريعة" هي مربّعات يتم عرضها في لوحة "الإعدادات السريعة"، ويمثّل كلّ مربّع إجراءً يمكن للمستخدمين النقر عليه لإكمال المهام المتكرّرة بسرعة. يمكن أن يوفّر تطبيقك مربّعًا مخصّصًا للمستخدمين من خلال TileService. الفئة واستخدام الكائن Tile لتتبُّع حالة المربّع. على سبيل المثال: يمكنك إنشاء مربّع يتيح للمستخدمين تفعيل شبكة VPN التي يوفّرها تطبيقك.

لوحة "الإعدادات السريعة" مع تفعيل مربّع شبكة VPN
  تفعيل وإيقاف
الشكل 1. لوحة "الإعدادات السريعة" مع تفعيل مربّع VPN وإيقافه

تحديد وقت إنشاء مربّع

ننصحك بإنشاء مربّعات وظائف معيّنة تتوقّع أن يستخدمها المستخدمون بشكل متكرّر أو يحتاجون إلى الوصول إليها بسرعة (أو كليهما). الأكثر فعالية المربعات هي تلك التي تتطابق مع هاتين الصفتين، مما يوفر وصولاً سريعًا إلى الإجراءات المتكررة.

على سبيل المثال، يمكنك إنشاء مربّع لتطبيق اللياقة البدنية الذي يتيح للمستخدمين لبدء جلسة تمرين بسرعة. ومع ذلك، لا ننصح بإنشاء مربّع شاشة للتطبيق نفسه يتيح للمستخدمين مراجعة سجلّ التمارين بالكامل.

حالات استخدام مربّعات تطبيقات اللياقة البدنية
الشكل 2. أمثلة على الفئات المقترَحة مقارنةً بغيرها لتطبيق اللياقة البدنية.

للمساعدة في تحسين قابلية اكتشاف مربّع التطبيق وسهولة استخدامه، ننصحك بتجنُّب ممارسات معيّنة:

  • تجنَّب استخدام المربّعات لتشغيل تطبيق. استخدِم اختصار تطبيق أو مشغّل تطبيقات عادي بدلاً من ذلك.

  • تجنَّب استخدام المربّعات لإجراءات المستخدم لمرة واحدة. استخدم اختصار تطبيق أو إشعار بدلاً من ذلك.

  • تجنَّب إنشاء عدد كبير جدًا من المربّعات. ننصحك باستخدام تطبيقَين كحد أقصى لكل تطبيق. يمكنك استخدام اختصار التطبيق بدلاً من ذلك.

  • تجنَّب استخدام مربّعات تعرض معلومات، ولكنها ليست تفاعلية للمستخدمين. استخدِم إشعارًا أو تطبيقًا مصغّرًا بدلاً من ذلك.

إنشاء مربّع معلومات

لإنشاء مربع، تحتاج أولاً إلى إنشاء رمز مربع مناسب، ثم إنشاء TileService وتوضيحها في ملف البيان لتطبيقك

يقدّم نموذج الإعدادات السريعة مثالاً على كيفية إنشاء المربع وإدارته.

إنشاء الرمز المخصّص

يجب تقديم رمز مخصّص يظهر على المربّع في لوحة "الإعدادات السريعة". (ستضيف هذا الرمز عند الإعلان عن السمة TileService، الموضحة في القسم التالي). يجب أن يكون الرمز أبيض خالصًا مع خلفية شفافة، وأن يكون أبعاده 24 x ‏24dp، وأن يكون على شكل VectorDrawable.

مثال على عنصر قابل للرسم
الشكل 3. مثال على عنصر قابل للرسم باستخدام متّجه

أنشئ رمزًا يشير بصريًا إلى الغرض من مربّع الرموز. يساعد هذا المستخدمين التعرف بسهولة على ما إذا كان البلاط يناسب احتياجاتهم. على سبيل المثال، يمكنك إنشاء رمز قياس زمن لتطبيق لياقة بدنية يتيح للمستخدمين بدء جلسة تمرين.

إنشاء TileService والإعلان عنه

أنشِئ خدمة لمربّعك تضيف فئة TileService.

Kotlin

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()
  }
}

Java

public class MyQSTileService extends TileService {

  // Called when the user adds your tile.
  @Override
  public void onTileAdded() {
    super.onTileAdded();
  }

  // Called when your app can update your tile.
  @Override
  public void onStartListening() {
    super.onStartListening();
  }

  // Called when your app can no longer update your tile.
  @Override
  public void onStopListening() {
    super.onStopListening();
  }

  // Called when the user taps on your tile in an active or inactive state.
  @Override
  public void onClick() {
    super.onClick();
  }

  // Called when the user removes your tile.
  @Override
  public void onTileRemoved() {
    super.onTileRemoved();
  }
}

يُرجى تقديم بيان عن TileService في ملف البيان لتطبيقك. إضافة الاسم والتصنيف TileService، وهو الرمز المخصّص الذي أنشأته في القسم السابق والحصول على الإذن المناسب.

 <service
     android:name=".MyQSTileService"
     android:exported="true"
     android:label="@string/my_default_tile_label"  // 18-character limit.
     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 لإظهار حالات العناصر.
الشكل 4. أمثلة على مربّع ملوّن ليعكس حالة المربّع (الحالات النشطة وغير النشطة وغير المتوفّرة على التوالي)

تعديل مربّع معلوماتك

يمكنك تعديل مربّع معلوماتك بعد تلقّي مكالمة من فريق الدعم على الرقم onStartListening(). استنادًا إلى وضع مربّع الرموز، يمكن تعديل مربّع الرموز مرة واحدة على الأقل إلى أن يتمتلقّي مكالمة هاتفية إلى onStopListening().

في الوضع النشط، يمكنك تعديل مربّع العرض مرة واحدة بالضبط قبل تلقّي onStopListening(). في الوضع غير النشط، يمكنك تعديل مربّع المعلومات بقدر ما تريد بين onStartListening() وonStopListening().

يمكنك استرداد عنصر Tile من خلال الاتصال برقم getQsTile(). للتحديث حقول معيّنة في كائن Tile، يمكنك استدعاء الطرق التالية:

يجب استدعاء updateTile() لتعديل مربّع البيانات بعد الانتهاء من ضبط حقول عنصر Tile على القيم الصحيحة. سيؤدي ذلك إلى تحليل النظام لبيانات المربّعات المعدَّلة وتعديل واجهة المستخدم.

Kotlin

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 = tile.label
  qsTile.state = if (state.enabled) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.icon = state.icon
  qsTile.updateTile()
}

Java

public class StateModel {
  final boolean enabled;
  final String label;
  final Icon icon;

  public StateModel(boolean e, String l, Icon i) {
    enabled = e;
    label = l;
    icon = i;
  }
}

@Override
public void onStartListening() {
  super.onStartListening();
  StateModel state = getStateFromService();
  Tile tile = getQsTile();
  tile.setLabel(state.label);
  tile.setContentDescription(state.label);
  tile.setState(state.enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setIcon(state.icon);
  tile.updateTile();
}

النقر بالمقبض

يمكن للمستخدمين النقر على مربّعك لبدء إجراء إذا كان مربّعك في وضع STATE_ACTIVE أو STATE_INACTIVE. ثم يستدعي النظام بعد ذلك onClick() معاودة الاتصال.

بعد أن يتلقّى تطبيقك طلبًا للرجوع إلى onClick()، يمكنه تشغيل مربّع حوار أو نشاط أو بدء عمل في الخلفية أو تغيير حالة مربّع الرموز.

Kotlin

var clicks = 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()
}

Java

int clicks = 0;

@Override
public void onClick() {
  super.onClick();
  counter++;
  Tile tile = getQsTile();
  tile.setState((counter % 2 == 0) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setLabel("Clicked " + counter + " times");
  tile.setContentDescription(tile.getLabel());
  tile.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) تنقله إلى هذا العنصر .

مطالبة المستخدم بإضافة مربّعك

لإضافة مربّع العرض يدويًا، على المستخدمين اتّباع عدة خطوات:

  1. مرِّر سريعًا للأسفل لفتح لوحة "الإعدادات السريعة".
  2. انقر على زر التعديل.
  3. يُرجى الانتقال بين جميع المربّعات على الجهاز إلى أن يعثر المستخدم على مربّعك.
  4. اضغط مع الاستمرار على المربّع واسحبه إلى قائمة المربّعات النشطة.

يمكن للمستخدم أيضًا نقل مربّع التطبيق أو إزالته في أي وقت.

بدءًا من نظام التشغيل Android 13، يمكنك استخدام الطريقة requestAddTileService(). لتسهّل على المستخدمين إضافة مربّعك إلى الجهاز. تُطلِب هذه الطريقة من المستخدمين إضافة مربّع التطبيق بسرعة إلى لوحة "التفاصيل السريعة" مباشرةً. يتضمّن الطلب اسم التطبيق والتصنيف الذي تم تقديمه ورمزه.

طلب من واجهة برمجة التطبيقات الخاصة بموضع الإعدادات السريعة
الشكل 5. إشعار Quick Settings Placement API
public void requestAddTileService (
  ComponentName tileServiceComponentName,
  CharSequence tileLabel,
  Icon icon,
  Executor resultExecutor,
  Consumer<Integer> resultCallback
)

تحتوي معاودة الاتصال على معلومات حول ما إذا تمت إضافة المربّع أم لا، إذا كانت موجودة بالفعل أو حدث أي خطأ.

استخدِم تقديرك الخاص عند تحديد الوقت وعدد المرات التي تريد فيها مطالبة المستخدمين بمنح الإذن. ننصح باستخدام requestAddTileService() في سياق معيّن فقط، مثل عندما يتفاعل المستخدم لأول مرة مع ميزة تسهّلها مربّعك.

يمكن أن يختار النظام إيقاف معالجة الطلبات ComponentName إذا تم رفضه من قِبل المستخدم عددًا كافيًا من المرات من قبل. يتم تحديد المستخدِم من Context المستخدَم لاسترداد هذه الخدمة، ويجب أن يتطابق مع المستخدِم الحالي.