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

توفّر شاشة 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 في نظام التشغيل 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

جافا

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)
    

    جافا

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

    جافا

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

    لغة Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    جافا

    long channelId = ContentUris.parseId(channelUri);
    
  4. يجب إضافة شعار لقناتك. استخدِم السمة Uri أو السمة Bitmap. ويجب أن يكون حجم رمز الشعار 80dp x 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)
    

    جافا

    // 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)
    

    جافا

    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
)

جافا

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

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

حذف قناة

لغة Kotlin

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

جافا

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)

جافا

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

جافا

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

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

لغة Kotlin

val programId = ContentUris.parseId(programUri)

جافا

long programId = ContentUris.parseId(programUri);

إضافة برامج إلى قناة "مشاهدة التالي"

لإدراج برامج في قناة "مشاهدة التالي"، يُرجى الاطّلاع على قسم إضافة برامج إلى قناة مشاهدة التالي.

تحديث برنامج

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

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

لغة Kotlin

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

جافا

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

حذف برنامج

لغة Kotlin

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

جافا

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
}

جافا

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_YOUTUBE_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>

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

  • تتطلب العديد من تطبيقات التلفزيون من المستخدمين تسجيل الدخول. في هذه الحالة، يجب أن يقترح 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
                               }
                           }
              })
    

    جافا

    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_DATA
  • INTERNAL_PROVIDER_FLAG1
  • INTERNAL_PROVIDER_FLAG2
  • INTERNAL_PROVIDER_FLAG3
  • INTERNAL_PROVIDER_FLAG4

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

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

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

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