القنوات على الشاشة الرئيسية

توفِّر شاشة Android TV الرئيسية أو الشاشة الرئيسية واجهة مستخدم المحتوى المُقترَح كجدول للقنوات والبرامج. يمثل كل صف قناة. تحتوي القناة على بطاقات لكل برنامج متاح على هذه القناة:

شاشة التلفزيون الرئيسية

يوضح هذا المستند كيفية إضافة قنوات وبرامج إلى الشاشة الرئيسية، وتحديث المحتوى، والتعامل مع إجراءات المستخدمين، وتقديم أفضل تجربة للمستخدمين. (إذا كنت تريد التعمق في واجهة برمجة التطبيقات، فحاول درس تطبيقي حول ترميز الشاشة الرئيسية ومشاهدة جلسة مؤتمر I/O لعام 2017 على Android TV.)

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

واجهة مستخدم الشاشة الرئيسية

يمكن للتطبيقات إنشاء قنوات جديدة وإضافة برامج وإزالتها وتعديلها في القناة والتحكّم في ترتيب البرامج في القناة. على سبيل المثال، يمكن لتطبيق إنشاء قناة باسم "الميزات الجديدة" وإظهار بطاقات للبرامج المتاحة حديثًا

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

قناة "اقتراحات أخرى"

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

قنوات التطبيقات

تتبع القنوات التي ينشئها تطبيقك دورة الحياة التالية:

  1. يكتشف المستخدم قناة في تطبيقك ويطلب إضافتها إلى الشاشة الرئيسية.
  2. ينشئ التطبيق القناة ويضيفها إلى TvProvider (تكون القناة غير مرئية في هذه المرحلة).
  3. يطلب التطبيق من النظام عرض القناة.
  4. يطلب النظام من المستخدم الموافقة على القناة الجديدة.
  5. تظهر القناة الجديدة في الصف الأخير من الشاشة الرئيسية.

القناة التلقائية

يمكن أن يقدم تطبيقك أي عدد من القنوات للمستخدم لإضافته إلى الشاشة الرئيسية. يضطر المستخدم عادةً إلى تحديد كل قناة والموافقة عليها قبل ظهورها في الشاشة الرئيسية. يمكن لكل تطبيق إنشاء قناة تلقائية واحدة. القناة الافتراضية خاصة لأنها تظهر تلقائيًا في الشاشة الرئيسية؛ لا يضطر المستخدم إلى تطلبها صراحةً.

المتطلّبات الأساسية

تستخدم شاشة Android TV الرئيسية واجهات TvProvider API في Android لإدارة القنوات والبرامج التي ينشئها تطبيقك. للوصول إلى بيانات موفِّر التطبيق، أضِف الإذن التالي إلى ملف بيان تطبيقك:

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />

تسهّل مكتبة الدعم في "TvProvider" استخدام مقدّم الخدمة. أضِفها إلى العناصر التابعة في ملف build.gradle:

Groovy

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

implementation("androidx.tvprovider:tvprovider:1.0.0")

للعمل مع القنوات والبرامج، يجب تضمين عمليات استيراد مكتبة الدعم التالية في برنامجك:

Kotlin

import android.support.media.tv.Channel
import android.support.media.tv.TvContractCompat
import android.support.media.tv.ChannelLogoUtils
import android.support.media.tv.PreviewProgram
import android.support.media.tv.WatchNextProgram

Java

import android.support.media.tv.Channel;
import android.support.media.tv.TvContractCompat;
import android.support.media.tv.ChannelLogoUtils;
import android.support.media.tv.PreviewProgram;
import android.support.media.tv.WatchNextProgram;

القنوات

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

إنشاء قناة

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

لإنشاء قناة، يُرجى اتّباع الخطوات التالية:

  1. أنشئ أداة إنشاء القنوات واضبط سماتها. لاحظ أن يجب أن يكون نوع القناة TYPE_PREVIEW. إضافة المزيد السمات على النحو المطلوب.

    Kotlin

    val builder = Channel.Builder()
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri)
    

    Java

    Channel.Builder builder = new Channel.Builder();
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri);
    
  2. أدخِل القناة في مقدّم الخدمة:

    Kotlin

    var channelUri = context.contentResolver.insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues())
    

    Java

    Uri channelUri = context.getContentResolver().insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues());
    
  3. يجب حفظ معرّف القناة لإضافة برامج إلى القناة. لاحقًا. استخرِج معرّف القناة من معرّف الموارد المنتظم (URI) الذي تم عرضه:

    Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    Java

    long channelId = ContentUris.parseId(channelUri);
    
  4. يجب إضافة شعار لقناتك. يُرجى استخدام Uri أو Bitmap. الشعار يجب أن يكون حجم الرمز 80 بكسل مستقل الكثافة × 80 بكسل مستقل الكثافة (dp)، ويجب أن يكون معتمًا. يتم عرضها ضمن قناع دائري:

    قناع رمز شاشة التلفزيون الرئيسية

    Kotlin

    // Choose one or the other
    storeChannelLogo(context: Context, channelId: Long, logoUri: Uri) // also works if logoUri is a URL
    storeChannelLogo(context: Context, channelId: Long, logo: Bitmap)
    

    Java

    // Choose one or the other
    storeChannelLogo(Context context, long channelId, Uri logoUri); // also works if logoUri is a URL
    storeChannelLogo(Context context, long channelId, Bitmap logo);
    
  5. إنشاء القناة التلقائية (اختياري): عند إنشاء التطبيق لأول مرة على قناتك، فيمكنك جعلها القناة التلقائية كي تظهر في الصفحة الرئيسية الشاشة على الفور دون أي إجراء من جانب المستخدم. وأي قنوات أخرى تنشئها لا تكون مرئية إلى أن ينقر المستخدم بشكل صريح يحددها.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    

  6. اجعل قناتك التلقائية تظهر قبل فتح تطبيقك. يمكنك أن يحدث هذا السلوك من خلال إضافة BroadcastReceiver التي تستمع إلى الإجراء android.media.tv.action.INITIALIZE_PROGRAMS، الذي تصل إليه الشاشة الرئيسية يرسله بعد تثبيت التطبيق:
    <receiver
      android:name=".RunOnInstallReceiver"
      android:exported="true">
        <intent-filter>
          <action android:name="android.media.tv.action.INITIALIZE_PROGRAMS" />
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    
    عند تثبيت تطبيقك من مصدر غير معروف أثناء تطويره، يمكنك اختبار هذه الخطوة يؤدي إلى تفعيل intent من خلال adb، حيث يشير your.package.name/.YourReceiverName هو مستوى أداء تطبيقك BroadcastReceiver:

    adb shell am broadcast -a android.media.tv.action.INITIALIZE_PROGRAMS -n \
        your.package.name/.YourReceiverName
    

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

تحديث قناة

إنّ تحديث القنوات يشبه إلى حد كبير إنشائها.

استخدِم سمة Channel.Builder أخرى لضبط السمات التي تحتاج إلى تغييرها.

استخدِم "ContentResolver" لتعديل القناة. استخدِم معرّف القناة الذي حفظته عند إضافة القناة في الأصل:

Kotlin

context.contentResolver.update(
        TvContractCompat.buildChannelUri(channelId),
        builder.build().toContentValues(),
        null,
        null
)

Java

context.getContentResolver().update(TvContractCompat.buildChannelUri(channelId),
    builder.build().toContentValues(), null, null);

ولتعديل شعار القناة، استخدِم storeChannelLogo().

حذف قناة

Kotlin

context.contentResolver.delete(TvContractCompat.buildChannelUri(channelId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildChannelUri(channelId), null, null);

البرامج

إضافة برامج إلى قناة التطبيق

أنشئ PreviewProgram.Builder واضبط سماته:

Kotlin

val builder = PreviewProgram.Builder()
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId)

Java

PreviewProgram.Builder builder = new PreviewProgram.Builder();
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId);

ويمكنك إضافة المزيد من السمات حسب نوع البرنامج. (لعرض السمات لكل نوع من البرامج، راجِع الجداول الواردة أدناه.)

إدراج البرنامج في المزوِّد:

Kotlin

var programUri = context.contentResolver.insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
        builder.build().toContentValues())

Java

Uri programUri = context.getContentResolver().insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
      builder.build().toContentValues());

استرجع رقم تعريف البرنامج للرجوع إليه لاحقًا:

Kotlin

val programId = ContentUris.parseId(programUri)

Java

long programId = ContentUris.parseId(programUri);

إضافة برامج إلى قناة "اقتراحات أخرى"

لإدراج برامج في قناة "اقتراحات أخرى"، راجِع القسم إضافة برامج إلى قائمة "اقتراحات". القناة التالية:

تحديث برنامج

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

استخدِم PreviewProgram.Builder لضبط السمات التي تريد تغييرها. ثم اتصل بـ getContentResolver().update لتحديث البرنامج. حدِّد رقم تعريف البرنامج الذي حفظته عند إضافة البرنامج في الأصل:

Kotlin

context.contentResolver.update(
        TvContractCompat.buildPreviewProgramUri(programId),
                builder.build().toContentValues(), null, null
)

Java

context.getContentResolver().update(TvContractCompat.buildPreviewProgramUri(programId),
    builder.build().toContentValues(), null, null);

حذف برنامج

Kotlin

context.contentResolver
        .delete(TvContractCompat.buildPreviewProgramUri(programId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildPreviewProgramUri(programId), null, null);

معالجة إجراءات المستخدم

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

اكتشاف القنوات وإضافتها

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

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

Kotlin

val intent = Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE)
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId)
try {
  activity.startActivityForResult(intent, 0)
} catch (e: ActivityNotFoundException) {
  // handle error
}

Java

Intent intent = new Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE);
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
try {
   activity.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
  // handle error
}

يعرض النظام مربع حوار يطلب من المستخدم الموافقة على القناة. تعامل مع نتيجة الطلب في طريقة onActivityResult لنشاطك (Activity.RESULT_CANCELED أو Activity.RESULT_OK).

أحداث الشاشة الرئيسية على Android TV

عندما يتفاعل المستخدم مع البرامج/القنوات التي ينشرها التطبيق، ترسل الشاشة الرئيسية الأهداف إلى التطبيق:

  • ترسل الشاشة الرئيسية إلى التطبيق رمز Uri المخزّن في سمة APP_LINK_INTENT_URI لإحدى القنوات عندما يختار المستخدم شعار القناة. يجب أن يشغِّل التطبيق واجهة المستخدم الرئيسية أو عرضًا مرتبطًا بالقناة المحددة.
  • ترسل الشاشة الرئيسية إلى التطبيق رمز Uri المُخزّن في السمة INTENT_URI لأحد البرامج، وذلك عندما يختار المستخدم أحد البرامج. من المفترض أن يشغّل التطبيق المحتوى الذي اخترته.
  • يمكن للمستخدم الإشارة إلى أنه لم يعد مهتمًا ببرنامج ويريد إزالته من واجهة مستخدم الشاشة الرئيسية. يزيل النظام البرنامج من واجهة المستخدم ويرسل رسالة intent إلى التطبيق الذي يملك البرنامج (android.media.tv.ACTION_PREVIEW_Program_BROWSABLE_DISABLED أو android.media.tv.ACTION_watch_NEXT_Program_BROWSABLE_DISABLED) مع معرّف البرنامج. يجب أن يزيل التطبيق البرنامج من موفر الخدمة ويجب ألا يعيد إدخاله.

احرِص على إنشاء فلاتر الأهداف لكل Uris التي ترسلها الشاشة الرئيسية لتفاعلات المستخدمين. على سبيل المثال:

<receiver
   android:name=".WatchNextProgramRemoved"
   android:enabled="true"
   android:exported="true">
   <intent-filter>
       <action android:name="android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
   </intent-filter>
</receiver>

أفضل الممارسات

  • تتطلّب العديد من تطبيقات TV من المستخدمين تسجيل الدخول. وهو في هذه الحالة BroadcastReceiver التي تستجيب لـ android.media.tv.action.INITIALIZE_PROGRAMS يجب أن تقترح محتوى القناة للمستخدمين الذين لم تتم مصادقتهم.على سبيل المثال، يمكن لتطبيقك أن تعرض أفضل محتوى أو محتوى رائج حاليًا. بعد أن يقوم المستخدم بتسجيل الدخول، عرض محتوى مخصّص هذه فرصة رائعة لزيادة مبيعات التطبيقات. للمستخدمين قبل تسجيل دخولهم.
  • عندما لا يكون تطبيقك يعمل في المقدّمة وتحتاج إلى تحديث قناة أو البرنامج، استخدِم JobScheduler لجدولة العمل (يُرجى الاطّلاع على: أداة جدولة المهام وJobService).
  • يمكن للنظام إبطال أذونات موفّر التطبيق في حال حدوث خلل في أداء التطبيق. (على سبيل المثال، إرسال بيانات غير مرغوب فيها باستمرار إلى المزوِّد). تأكد من يجب إحاطة الرمز البرمجي الذي يصل إلى الموفر بعبارات Try-catch للتعامل معها. استثناءات الأمان.
  • قبل تحديث البرامج والقنوات، اطلب من مقدم الخدمة البحث عن البيانات تحتاج إلى تحديث البيانات وتوفيقها. على سبيل المثال، لا حاجة إلى تحديث برنامج يريد المستخدم إزالته من واجهة المستخدم. استخدم وظيفة في الخلفية إدراج/تحديث بياناتك في المزود بعد الاستعلام عن البيانات ثم طلب الموافقة على إنشاء قنواتك. يمكنك تشغيل هذه المهمة عندما عند بدء تشغيل التطبيق وعندما يحتاج التطبيق إلى تحديث بياناته.

    Kotlin

    context.contentResolver
      .query(
          TvContractCompat.buildChannelUri(channelId),
              null, null, null, null).use({
                  cursor-> if (cursor != null and cursor.moveToNext()) {
                               val channel = Channel.fromCursor(cursor)
                               if (channel.isBrowsable()) {
                                   //update channel's programs
                               }
                           }
              })
    

    Java

    try (Cursor cursor = context.getContentResolver()
          .query(
              TvContractCompat.buildChannelUri(channelId),
              null,
              null,
              null,
              null)) {
                  if (cursor != null && cursor.moveToNext()) {
                      Channel channel = Channel.fromCursor(cursor);
                      if (channel.isBrowsable()) {
                          //update channel's programs
                      }
                  }
              }
    
  • استخدم Uris الفريد لجميع الصور (الشعارات والرموز وصور المحتوى). احرص على استخدام معرّف موارد منتظم (URI) مختلف عند تعديل الصورة. تم تخزين جميع الصور مؤقتًا. إذا لم تُغير معرف الموارد المنتظم (URI) عند تغيير الصورة، فستستمر الصورة القديمة في الظهور.

  • تذكر أن عبارات WHERE غير مسموح بها وأن الاتصالات المقدمة إلى الموفرين باستخدام عبارات WHERE ستؤدي إلى استثناء أمان.

السمات

يصف هذا القسم سمتَي القناة والبرنامج بشكل منفصل.

سمات القناة

عليك تحديد السمات التالية لكل قناة:

السمة ملاحظات
النوع تم الضبط على TYPE_PREVIEW
DISPLAY_NAME على اسم القناة
APP_LINK_INTENT_URI عندما يختار المستخدم شعار القناة، يرسل النظام نيةً لبدء نشاط يعرض محتوًى ذا صلة بالقناة. اضبط هذه السمة على معرّف الموارد المنتظم (URI) المستخدَم في فلتر الأهداف لهذا النشاط.

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

  • INTERNAL_provider_ID
  • البيانات الداخلية
  • INTERNAL_provider_FLAG1
  • INTERNAL_provider_FLAG2
  • INTERNAL_provider_FLAG3
  • INTERNAL_provider_FLAG4

سمات البرنامج

اطّلِع على الصفحات الفردية لسمات كل نوع من أنواع البرامج:

نموذج التعليمات البرمجية

لمزيد من المعلومات حول إنشاء تطبيقات تتفاعل مع الشاشة الرئيسية وتضيف قنوات وبرامج إلى شاشة Android TV الرئيسية، يمكنك الاطّلاع على الدرس التطبيقي حول الترميز على الشاشة الرئيسية.