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

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

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

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

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

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

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

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

قناة "مشاهدة المحتوى التالي"

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

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

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

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

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

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

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

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

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

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

رائع

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. ويجب أن يكون حجم رمز الشعار 80dp × 80dp، ويجب أن يكون معتمًا. ويتم عرضه تحت قناع دائري:

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

    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>
    
    BroadcastReceiveryour.package.name.YourReceiverName

    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 لبرنامج إلى التطبيق عندما يختار المستخدم برنامجًا. يجب أن يشغِّل التطبيق المحتوى الذي تم اختياره.
  • يمكن للمستخدم الإشارة إلى أنه لم يعد مهتمًا بأحد البرامج ويريد إزالته من واجهة مستخدم الشاشة الرئيسية. يزيل النظام البرنامج من واجهة المستخدم ويرسل التطبيق الذي يملك البرنامج غرضًا (android.media.tv.ACTION_PREVIEW_program_BROWSABLE_DISABLED أو android.media.tv.ACTION_watch_NEXT_YPP_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>

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

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

    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 سيطرح استثناء أمان.

السمات

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

سمات القناة

يجب تحديد هذه السمات لكل قناة:

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

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

  • معرّف INTERNAL_googleapis_ID
  • INTERNAL_provider_DATA
  • INTERNAL_provider_FLAG1
  • INTERNAL_provider_FLAG2
  • INTERNAL_googleapis_FLAG3
  • INTERNAL_provider_FLAG4

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

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

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

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