عرض البيانات للإضافات

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

تشمل خدمة مزوِّد البيانات ComplicationProviderService لتقديم معلومات مفيدة مباشرةً إلى خلفية شاشة الساعة.

إنشاء مشروع لمزود بيانات

لإنشاء مشروع في "استوديو Android" لتطبيق مزوّد البيانات، يجب إكمال الخطوات التالية:

  1. انقر على ملف > جديد > مشروع جديد.
  2. في نافذة نموذج المشروع، انقر على علامة التبويب Wear OS، واختَر ما مِن نشاط، ثم انقر على التالي.
  3. في نافذة Configure Your Project (إعداد مشروعك)، أدخِل اسمًا لمشروعك واملأ معلومات المشروع العادية، ثم انقر على Finish (إنهاء).
  4. ينشئ "استوديو Android" مشروعًا باستخدام وحدة تطبيق لمزوِّد البيانات. لمزيد من المعلومات حول المشاريع في "استوديو Android"، يمكنك الاطّلاع على المقالة إنشاء مشروع.
  5. ابدأ تطبيق موفّر البيانات عن طريق إنشاء صف جديد يضم BroadcastReceiver. الغرض من هذه الصف هو الاستماع إلى طلبات تحديث الإضافات الواردة من نظام Wear OS. بالإضافة إلى ذلك، يمكنك إنشاء فئة جديدة يتم فيها توسيع نطاق ComplicationProviderService لتوفير البيانات كما هو مطلوب من خلال الإضافات المناسبة. لمزيد من المعلومات، يُرجى الاطّلاع على ما يلي:

    ملاحظة: إنّ إضافة نشاط لموفّر البيانات اختيارية. على سبيل المثال، قد تحتاج إلى نشاط لا يتم تشغيله إلا عند نقر المستخدم على إحدى الإضافات.

تنفيذ طريقة لطلبات التعديل

عند الحاجة إلى إضافة بيانات، يرسِل نظام Wear OS طلبات التعديل إلى مقدّم البيانات. وتتلقّى الطلبات BroadcastReceiver. للردّ على طلبات التعديل، على مزوِّد البيانات تنفيذ طريقة onComplicationUpdate() للفئة ComplicationProviderService.

يستدعي نظام Wear OS onComplicationUpdate() عندما يحتاج إلى بيانات من موفّر الخدمة، على سبيل المثال، عند تفعيل إضافة تستخدم مقدّم الخدمة أو عند انقضاء فترة زمنية ثابتة. ويمرِّر عنصر ComplicationManager كمَعلمة إلى onComplicationUpdate، والتي تُستخدم لإرسال البيانات مرة أخرى إلى النظام.

ملاحظة: عندما يقدّم تطبيق مزوِّد البيانات بيانات، تتلقّى خلفية شاشة الساعة القيم الأولية التي ترسلها لكي ترسم المعلومات.

يعرض مقتطف الرمز التالي نموذجًا لتنفيذ طريقة onComplicationUpdate:

Kotlin

override fun onComplicationUpdate(
    complicationId: Int, dataType: Int, complicationManager: ComplicationManager) {

    Log.d(TAG, "onComplicationUpdate() id: $complicationId")

    // Used to create a unique key to use with SharedPreferences for this complication.
    val thisProvider = ComponentName(this, javaClass)

    // Retrieves your data; in this case, grabs an incrementing number from SharedPrefs.
    val preferences = getSharedPreferences(ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0)

    val number = preferences.getInt(
            ComplicationTapBroadcastReceiver.getPreferenceKey(
                    thisProvider, complicationId),
                    0)
    val numberText = String.format(Locale.getDefault(), "%d!", number)

    var complicationData: ComplicationData? = null

    when (dataType) {
        ComplicationData.TYPE_SHORT_TEXT -> complicationData = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                .setShortText(ComplicationText.plainText(numberText))
                .build()
        else -> if (Log.isLoggable(TAG, Log.WARN)) {
                    Log.w(TAG, "Unexpected complication type $dataType")
                }
    }

    if (complicationData != null) {
        complicationManager.updateComplicationData(complicationId, complicationData)
    } else {
        // If no data is sent, we still need to inform the ComplicationManager, so
        // the update job can finish and the wake lock isn't held any longer.
        complicationManager.noUpdateRequired(complicationId)
    }
}

Java

@Override
public void onComplicationUpdate(
       int complicationId, int dataType, ComplicationManager complicationManager) {

   Log.d(TAG, "onComplicationUpdate() id: " + complicationId);

   // Used to create a unique key to use with SharedPreferences for this complication.
   ComponentName thisProvider = new ComponentName(this, getClass());

   // Retrieves your data; in this case, grabs an incrementing number from SharedPrefs.
   SharedPreferences preferences =
     getSharedPreferences( ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);

   int number =
           preferences.getInt(
                   ComplicationTapBroadcastReceiver.getPreferenceKey(
                           thisProvider, complicationId),
                   0);
   String numberText = String.format(Locale.getDefault(), "%d!", number);

   ComplicationData complicationData = null;

   switch (dataType) {
       case ComplicationData.TYPE_SHORT_TEXT:
           complicationData =
                   new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                           .setShortText(ComplicationText.plainText(numberText))
                           .build();
           break;
       default:
           if (Log.isLoggable(TAG, Log.WARN)) {
               Log.w(TAG, "Unexpected complication type " + dataType);
           }
   }

   if (complicationData != null) {
       complicationManager.updateComplicationData(complicationId, complicationData);

   } else {
       // If no data is sent, we still need to inform the ComplicationManager, so
       // the update job can finish and the wake lock isn't held any longer.
       complicationManager.noUpdateRequired(complicationId);
   }
}

نماذج البيان والأذونات

يجب أن تتضمّن تطبيقات مزوّدي البيانات تعريفات محددة في ملف بيان التطبيق الخاص بها لكي يتم التعامل مع هذه التطبيقات باعتبارها مزوِّد بيانات من خلال نظام Android. يوضّح هذا القسم الإعدادات المطلوبة لتطبيقات مزوّدي البيانات.

في ملف البيان الخاص بتطبيقك، عليك تعريف الخدمة وإضافة فلتر لأهداف إجراء طلب التحديث. يجب أن يحمي البيان أيضًا الخدمة من خلال إضافة إذن BIND_COMPLICATION_PROVIDER لضمان ربط نظام Wear OS فقط بخدمات مقدِّم الخدمة.

ويجب أيضًا تضمين السمة android:icon في العنصر service الذي يوفّر رمزًا أبيض أحادي اللون. نوصي باستخدام رسومات متجهات للأيقونات. يمثّل الرمز مقدّم الخدمة ويظهر في أداة اختيار الموفّر.

إليك مثال على ذلك:

<service
    android:name=".provider.IncrementingNumberComplicationProviderService"
    android:icon="@drawable/icn_complications"
    android:label="@string/complications_provider_incrementing_number"
    android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
    <intent-filter>
        <action
         android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
    </intent-filter>
</service>

تحديد عناصر البيانات الوصفية

في ملف البيان، ضمِّن البيانات الوصفية لتحديد الأنواع المتوافقة وفترة التحديث وإجراء الإعداد، كما هو موضّح في المثال التالي:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT" />

<meta-data
    android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
    android:value="300" />

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

إذا لم تضبط UPDATE_PERIOD_SECONDS على 0، يجب استخدام قيمة لا تقل عن 300 (5 دقائق)، وهي الحد الأدنى لفترة التحديث التي يفرضها النظام، للحفاظ على عمر بطارية الجهاز. بالإضافة إلى ذلك، يُرجى العلِم بأنّ طلبات التحديث تأتي بمعدّل أقل عندما يكون الجهاز في وضع الاستراحة أو عندما لا يتم ارتداء الجهاز.

لمزيد من التفاصيل حول إرسال التعديلات، يمكنك الاطّلاع على المفاتيح المدرَجة في الفئة ComplicationProviderService في مرجع واجهة برمجة تطبيقات Wear OS.

إضافة نشاط ضبط

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

<meta-data
    android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
    android:value="PROVIDER_CONFIG_ACTION"/>

يمكن أن تكون القيمة أي إجراء.

بعد ذلك، يمكنك إنشاء نشاط الإعداد باستخدام فلتر أهداف لهذا الإجراء. يجب أن يكون نشاط الإعداد في الحزمة نفسها التي يستخدمها الموفّر. يجب أن يعرض نشاط الإعداد RESULT_OK أو RESULT_CANCELED لإعلام النظام بما إذا كان يجب ضبط مقدّم الخدمة أم لا.

خلفيات شاشة آمنة يحددها مقدّم الخدمة

يمكن لمقدّمي الخدمات تحديد خلفيات معيّنة لشاشة الساعة كـ "آمنة" لتلقّي بياناتهم. لا تُستخدَم هذه الطريقة إلا عندما تحاول خلفية شاشة الساعة استخدام مقدِّم الخدمة كخيار تلقائي وعندما يثق مقدِّم الخدمة في تطبيق خلفية شاشة الساعة.

لتعريف خلفيات شاشة الساعة بأنّها آمنة، يضيف مقدّم الخدمة بيانات وصفية باستخدام مفتاح android.support.wearable.complications.SAFE_WATCH_FACES. وتكون قيمة البيانات الوصفية عبارة عن قائمة مفصولة بفواصل تتألف من أسماء مكونات WatchFaceService، ويتم تحديدها كما لو تم استدعاء ComponentName.flattenToString()، أو أسماء حِزم التطبيقات. وفي هذه الحالة، تُعتبر كل خلفية شاشة ساعة داخل تطبيق محدّد آمنة. يتم تجاهل المسافة البيضاء في قائمة القيم. على سبيل المثال:

<meta-data
       android:name="android.support.wearable.complications.SAFE_WATCH_FACES"
       android:value="
          com.app.watchface/com.app.watchface.MyWatchFaceService,
          com.anotherapp.anotherwatchface/com.something.WatchFaceService,
          com.something.text"/>

توفير صور آمنة محروقة

على الشاشات المعرّضة للتلف، يجب تجنُّب كتل الألوان الصلبة في "وضع الإضاءة السينمائية". إذا كانت الرموز أو الصور تتضمن كتلاً خالصة من الألوان، قدِّم أيضًا نسخة آمنة مُدمَجة.

عند تقديم رمز باستخدام ComplicationData.Builder#setIcon، ضمِّن نسخة آمنة ومضمّنة باستخدام ComplicationData.Builder#setBurnInProtectionIcon.

عند تقديم صورة باستخدام ComplicationData.Builder#setSmallImage، ضمِّن نسخة آمنة ومضمّنة باستخدام ComplicationData.Builder#setBurnInProtectionSmallImage.

استخدام التحديثات الفورية

وكبديل لتحديد فاصل زمني ثابت غير صفري للتحديث لأحد الإضافات في ملف بيان تطبيقك، يمكنك استخدام مثيل ComplicationDataSourceUpdateRequester لطلب التحديثات بشكل ديناميكي. لطلب تعديل المحتوى المرئي للمستخدمين في الإضافة، اتصل بـ requestUpdate().

تحذير: للحفاظ على عمر بطارية الجهاز، يجب عدم طلب الرقم requestUpdate() من مثيل "ComplicationDataSourceUpdateRequester" بمعدّل يتجاوز كل 5 دقائق في المتوسط.

تقديم قيم ديناميكية

بدءًا من نظام التشغيل Wear OS 4، يمكن أن تعرض بعض الإضافات قيمًا يتم إعادة تحميلها بمعدّل أكبر استنادًا إلى القيم المتاحة على النظام الأساسي مباشرةً. لتوفير هذه الميزة في الإضافات، استخدِم حقول ComplicationData التي تقبل القيم الديناميكية. وتقيّم المنصة هذه القيم وتعدّلها بشكل متكرّر بدون الحاجة إلى تشغيل موفّر الإضافات.

تتضمن أمثلة الحقول حقل القيمة الديناميكية للسمة GoalProgressComplicationData و DynamicComplicationText، والتي يمكن استخدامها في أي حقل ComplicationText. تستند هذه القيم الديناميكية إلى مكتبة androidx.wear.protolayout.expression.

في بعض الحالات، لا يمكن للنظام الأساسي تقييم القيم الديناميكية:

تقديم قيم تعتمد على الوقت

وهناك بعض التعقيدات التي تحتاج إلى عرض قيمة مرتبطة بالوقت الحالي. وتشمل الأمثلة التاريخ الحالي أو الوقت المتبقي حتى الاجتماع التالي أو الوقت في منطقة زمنية أخرى.

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

معدّل التعديلات المُضافة

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