توفّر شاشة Android TV الرئيسية، أو الشاشة الرئيسية ببساطة، واجهة مستخدم تعرض المحتوى المقترَح كجدول يضمّ القنوات والبرامج. يمثل كل صف قناة. تحتوي القناة على بطاقات لكل برنامج متوفّر على تلك القناة:
يوضح هذا المستند كيفية إضافة القنوات والبرامج إلى الشاشة الرئيسية وتحديث المحتوى والتعامل مع إجراءات المستخدم وتقديم أفضل تجربة للمستخدمين. (إذا كنت ترغب في التعمّق في تفاصيل واجهة برمجة التطبيقات، جرِّب الدرس التطبيقي حول ترميز الشاشة الرئيسية وشاهِد جلسة Android TV لمؤتمر I/O لعام 2017.)
ملاحظة: لا تتوفّر قنوات "الاقتراحات" إلا في الإصدار Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) والإصدارات الأحدث. ويجب استخدامها لتقديم اقتراحات للتطبيقات التي تعمل بنظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث. لتوفير اقتراحات للتطبيقات التي تعمل على إصدارات سابقة من Android، يجب أن يستخدم التطبيق صف الاقتراحات بدلاً من ذلك.
واجهة مستخدم الشاشة الرئيسية
يمكن للتطبيقات إنشاء قنوات جديدة، وإضافة برامج وإزالتها وتعديلها في قناة، والتحكّم في ترتيب البرامج في القناة. على سبيل المثال، يمكن لتطبيق إنشاء قناة باسم "الميزات الجديدة" وعرض بطاقات للبرامج المتوفّرة حديثًا.
لا يمكن للتطبيقات التحكّم في ترتيب ظهور القنوات في الشاشة الرئيسية. عندما ينشئ التطبيق قناة جديدة، تضيفها الشاشة الرئيسية إلى أسفل قائمة القنوات. يمكن للمستخدم إعادة ترتيب القنوات وإخفاؤها وعرضها.
قناة "مشاهدة المحتوى التالي"
وقناة "المشاهدة تاليًا" هي الصف الثاني الذي يظهر في الشاشة الرئيسية بعد صف التطبيقات. ينشئ النظام هذه القناة ويحافظ عليها. يمكن لتطبيقك إضافة برامج إلى قناة "مشاهدة التالي". لمزيد من المعلومات، يُرجى الاطّلاع على إضافة برامج إلى قناة "مشاهدة التالي".
قنوات التطبيقات
وتتبع جميع القنوات التي ينشئها تطبيقك دورة الحياة هذه:
- يكتشف المستخدم قناة في تطبيقك ويطلب إضافتها إلى الشاشة الرئيسية.
- ينشئ التطبيق القناة ويضيفها إلى
TvProvider
(لن تكون القناة مرئية في هذه المرحلة). - يطلب التطبيق من النظام عرض القناة.
- يطلب النظام من المستخدم الموافقة على القناة الجديدة.
- تظهر القناة الجديدة في الصف الأخير من الشاشة الرئيسية.
القناة التلقائية
يمكن أن يعرض تطبيقك أي عدد من القنوات للمستخدم لإضافتها إلى الشاشة الرئيسية. يتعين على المستخدم عادةً اختيار كل قناة والموافقة عليها قبل ظهورها في الشاشة الرئيسية. يتوفّر لكل تطبيق خيار إنشاء قناة تلقائية واحدة. القناة الافتراضية خاصة لأنها تظهر تلقائيًا في الشاشة الرئيسية، ولا يتعين على المستخدم أن يطلبها صراحةً.
المتطلّبات الأساسية
تستخدم شاشة 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
.
لإنشاء قناة، يُرجى اتّباع الخطوات التالية:
أنشئ أداة إنشاء القنوات وحدِّد سماتها. ملاحظة: يجب أن يكون نوع القناة
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);إدراج القناة في مقدّم الخدمة:
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());
-
يجب حفظ معرّف القناة لإضافة البرامج إلى القناة لاحقًا. استخرِج معرّف القناة من معرّف الموارد المنتظم (URI) الذي تم عرضه:
Kotlin
var channelId = ContentUris.parseId(channelUri)
Java
long channelId = ContentUris.parseId(channelUri);
يجب إضافة شعار لقناتك. استخدِم
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);
إنشاء القناة التلقائية (اختياري): عندما ينشئ تطبيقك أوّل قناة له، يمكنك ضبطها على القناة التلقائية لكي تظهر على الشاشة الرئيسية على الفور بدون أيّ إجراء من جانب المستخدم. ولن تظهر أي قنوات أخرى تنشئها إلى أن يختارها المستخدم صراحةً.
Kotlin
TvContractCompat.requestChannelBrowsable(context, channelId)
Java
TvContractCompat.requestChannelBrowsable(context, channelId);
- إظهار القناة التلقائية قبل فتح التطبيق ويمكنك تنفيذ هذا السلوك عن طريق إضافة عنصر
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>
BroadcastReceiver
your.package.name.YourReceiverNameadb 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 الرئيسية، يمكنك الاطّلاع على الدرس التطبيقي حول ترميز الشاشة الرئيسية.