يتضمّن هذا الدليل تعليمات للمطوّرين لمشاركة بيانات اشتراك التطبيق والأهلية مع Google TV باستخدام Engage SDK. يمكن للمستخدمين العثور على المحتوى الذي يحق لهم مشاهدته، كما يمكنهم السماح لخدمة Google TV بتقديم اقتراحات محتوى ذات صلة عالية للمستخدمين مباشرةً ضمن تجارب Google TV على التلفزيون والأجهزة الجوّالة والأجهزة اللوحية.
المتطلّبات الأساسية
يجب إعداد خلاصة إجراءات الوسائط قبل استخدام واجهة برمجة التطبيقات الخاصة بأذونات الجهاز. إذا لم يسبق لك ذلك، أكمل عملية إعداد خلاصة مهام الوسائط.
العمل التحضيري
قبل البدء، أكمِل الخطوات التالية تأكَّد من أنّ تطبيقك يستهدف المستوى 19 أو مستوى أحدث لواجهة برمجة التطبيقات لإجراء عملية الدمج هذه.
أضِف مكتبة
com.google.android.engage
إلى تطبيقك باتّباع الخطوات التالية:تتوفّر حِزم SDK منفصلة لاستخدامها في عملية الدمج، إحداها للتطبيقات المتوافقة مع الأجهزة الجوّالة والأخرى للتطبيقات المتوافقة مع أجهزة التلفزيون.
لأجهزة الجوّال
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
للتلفزيون
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
اضبط بيئة خدمة Engage على الإنتاج في ملف
AndroidManifest.xml
.ملف APK للأجهزة الجوّالة
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
حزمة APK للتلفزيون
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
قبل إرسال حزمة APK إلى Google، اضبط بيئة خدمة التفاعل على الإنتاج في ملف AndroidManifest.xml. للحصول على أفضل أداء وضمان التوافق في المستقبل، لا تنشر البيانات إلا عندما يكون التطبيق في المقدّمة ويتفاعل معه المستخدم بشكل نشط، مثل عند تشغيل التطبيق أو بعد تسجيل الدخول أو أثناء الاستخدام النشط. ننصحك بعدم النشر من خلال عمليات الخلفية.
نشر معلومات الاشتراك في الأحداث التالية:
- يسجّل المستخدم الدخول إلى تطبيقك.
- يبدّل المستخدم بين الملفات الشخصية (إذا كانت الملفات الشخصية متاحة).
- يشترك المستخدم في اشتراك جديد.
- يرقّي المستخدم اشتراكًا حاليًا.
- انتهاء صلاحية اشتراك المستخدم
التكامل
يقدّم هذا القسم أمثلة على الرموز والإرشادات اللازمة لتنفيذ AccountProfile
وSubscriptionEntity
من أجل إدارة أنواع الاشتراكات المختلفة.
حساب المستخدم وملفه الشخصي
للسماح باستخدام ميزات مخصّصة على Google TV، يجب تقديم معلومات الحساب. استخدِم AccountProfile
لتقديم ما يلي:
- معرّف الحساب: معرّف فريد يمثّل حساب المستخدِم. يمكن أن يكون هذا المعرّف هو رقم تعريف الحساب الفعلي أو نسخة مشوّشة بشكل مناسب.
// Set the account ID to which the subscription applies.
// Don't set the profile ID because subscription applies to account level.
val accountProfile = AccountProfile.Builder()
.setAccountId("user_account_id")
.setProfileId("user_profile id")
.build();
اشتراك في مستوى مشترك
بالنسبة إلى المستخدمين الذين لديهم اشتراكات أساسية في خدمات مقدّم المحتوى، مثل خدمة تتضمّن فئة اشتراك واحدة تتيح الوصول إلى كل المحتوى المدفوع، يُرجى تقديم التفاصيل الأساسية التالية:
نوع الاشتراك: يجب الإشارة بوضوح إلى خطة الاشتراك المحدّدة التي اشترك فيها المستخدم.
-
SUBSCRIPTION_TYPE_ACTIVE
: يشير إلى أنّ المستخدم لديه اشتراك مدفوع نشط. -
SUBSCRIPTION_TYPE_ACTIVE_TRIAL
: يملك المستخدم اشتراكًا تجريبيًا. -
SUBSCRIPTION_TYPE_INACTIVE
: يعني أنّ المستخدم لديه حساب ولكن ليس لديه اشتراك نشط أو فترة تجريبية نشطة.
-
وقت انتهاء الصلاحية: وقت اختياري بالمللي ثانية. حدِّد تاريخ انتهاء صلاحية الاشتراك.
اسم حزمة مقدّم الخدمة: حدِّد اسم حزمة التطبيق الذي يتعامل مع الاشتراك.
مثال على خلاصة مقدّم المحتوى الإعلامي النموذجي
"actionAccessibilityRequirement": [
{
"@type": "ActionAccessSpecification",
"category": "subscription",
"availabilityStarts": "2022-06-01T07:00:00Z",
"availabilityEnds": "2026-05-31T07:00:00Z",
"requiresSubscription": {
"@type": "MediaSubscription",
// Don't match this string,
// ID is only used to for reconciliation purpose
"@id": "https://www.example.com/971bfc78-d13a-4419",
// Don't match this, as name is only used for displaying purpose
"name": "Basic common name",
"commonTier": true
}
ينشئ المثال التالي SubscriptionEntity
لمستخدم:
val subscription = SubscriptionEntity
.Builder()
setSubscriptionType(
SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
)
.setProviderPackageName("com.google.android.example")
// Optional
// December 30, 2025 12:00:00AM in milliseconds since epoch
.setExpirationTimeMillis(1767052800000)
.build();
اشتراك Premium
إذا كان التطبيق يقدّم حِزم اشتراك مميّز متعددة المستويات تتضمّن محتوًى أو ميزات موسّعة تتجاوز المستوى العادي، يمكنك توضيح ذلك من خلال إضافة إذن واحد أو أكثر إلى الاشتراك.
يتضمّن إذن الاستخدام هذا الحقول التالية:
- المعرّف: سلسلة المعرّف المطلوبة لهذا الاستحقاق. يجب أن يتطابق هذا المعرّف مع أحد معرّفات الأهلية (يُرجى العِلم أنّ هذا المعرّف ليس حقل المعرّف) المقدَّمة في خلاصة مقدّم خدمة الوسائط المنشورة على Google TV.
- الاسم: هذه معلومات مساعدة تُستخدَم لمطابقة الأهلية. على الرغم من أنّ توفير اسم إذن سهل القراءة للمستخدم أمر اختياري، إلا أنّه يحسّن فهم الأذونات الممنوحة للمستخدمين لكلّ من المطوّرين وفِرق الدعم. على سبيل المثال: Sling Orange.
- Expiration TimeMillis: يمكنك اختياريًا تحديد وقت انتهاء الصلاحية بالملي ثانية لإذن الاستخدام هذا، إذا كان يختلف عن وقت انتهاء صلاحية الاشتراك. بشكلٍ تلقائي، ستنتهي صلاحية الاستخدام عند انتهاء صلاحية الاشتراك.
إليك مقتطفًا من خلاصة مقدّم وسائط نموذجية:
"actionAccessibilityRequirement": [
{
"@type": "ActionAccessSpecification",
"category": "subscription",
"availabilityStarts": "2022-06-01T07:00:00Z",
"availabilityEnds": "2026-05-31T07:00:00Z",
"requiresSubscription": {
"@type": "MediaSubscription",
// Don't match this string,
// ID is only used to for reconciliation purpose
"@id": "https://www.example.com/971bfc78-d13a-4419",
// Don't match this, as name is only used for displaying purpose
"name": "Example entitlement name",
"commonTier": false,
// match this identifier in your API. This is the crucial
// entitlement identifier used for recommendation purpose.
"identifier": "example.com:entitlementString1"
}
ينشئ المثال التالي SubscriptionEntity
لمستخدم مشترك:
// Subscription with entitlements.
// The entitlement expires at the same time as its subscription.
val subscription = SubscriptionEntity
.Builder()
.setSubscriptionType(
SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
)
.setProviderPackageName("com.google.android.example")
// Optional
// December 30, 2025 12:00:00AM in milliseconds
.setExpirationTimeMillis(1767052800000)
.addEntitlement(
SubscriptionEntitlement.Builder()
// matches with the identifier in media provider feed
.setEntitlementId("example.com:entitlementString1")
.setDisplayName("entitlement name1")
.build()
)
.build();
// Subscription with entitlements
// The entitement has different expiration time from its subscription
val subscription = SubscriptionEntity
.Builder()
.setSubscriptionType(
SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
)
.setProviderPackageName("com.google.android.example")
// Optional
// December 30, 2025 12:00:00AM in milliseconds
.setExpirationTimeMillis(1767052800000)
.addEntitlement(
SubscriptionEntitlement.Builder()
.setEntitlementId("example.com:entitlementString1")
.setDisplayName("entitlement name1")
// You may set the expiration time for entitlement
// December 15, 2025 10:00:00 AM in milliseconds
.setExpirationTimeMillis(1765792800000)
.build())
.build();
اشتراك في حزمة خدمات مرتبطة
على الرغم من أنّ الاشتراكات تكون عادةً خاصة بموفّر الوسائط في التطبيق الأصلي، يمكن ربط اشتراك بحزمة خدمة مرتبطة من خلال تحديد اسم حزمة الخدمة المرتبطة ضمن الاشتراك.
يوضّح نموذج الرمز البرمجي التالي كيفية إنشاء اشتراك مستخدم.
// Subscription for linked service package
val subscription = SubscriptionEntity
.Builder()
.setSubscriptionType(
SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
)
.setProviderPackageName("com.google.android.example")
// Optional
// December 30, 2025 12:00:00AM in milliseconds since epoch
.setExpirationTimeMillis(1767052800000)
.build();
بالإضافة إلى ذلك، إذا كان لدى المستخدم اشتراك آخر في خدمة فرعية، أضِف اشتراكًا آخر واضبط اسم حزمة الخدمة المرتبطة وفقًا لذلك.
// Subscription for linked service package
val linkedSubscription = Subscription
.Builder()
.setSubscriptionType(
SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
)
.setProviderPackageName("linked service package name")
// Optional
// December 30, 2025 12:00:00AM in milliseconds since epoch
.setExpirationTimeMillis(1767052800000)
.addBundledSubscription(
BundledSubscription.Builder()
.setBundledSubscriptionProviderPackageName(
"bundled-subscription-package-name"
)
.setSubscriptionType(SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE)
.setExpirationTimeMillis(111)
.addEntitlement(
SubscriptionEntitlement.Builder()
.setExpirationTimeMillis(111)
.setDisplayName("Silver subscription")
.setEntitlementId("subscription.tier.platinum")
.build()
)
.build()
)
.build();
يمكنك أيضًا إضافة امتيازات إلى اشتراك في خدمة مرتبطة.
توفير مجموعة اشتراكات
تشغيل مهمة نشر المحتوى أثناء عمل التطبيق في المقدّمة
استخدِم طريقة publishSubscriptionCluster()
من فئة AppEngagePublishClient
لنشر عنصر SubscriptionCluster
.
استخدِم isServiceAvailable
للتحقّق مما إذا كانت الخدمة متاحة للتكامل.
client.publishSubscription(
PublishSubscriptionRequest.Builder()
.setAccountProfile(accountProfile)
.setSubscription(subscription)
.build();
)
استخدِم setSubscription()
للتأكّد من أنّ المستخدم يجب أن يكون لديه اشتراك واحد فقط في الخدمة.
استخدِم addLinkedSubscription()
أو addLinkedSubscriptions()
اللذين يقبلان قائمة
بالاشتراكات المرتبطة، وذلك للسماح للمستخدم بالحصول على صفر أو أكثر من الاشتراكات المرتبطة.
عندما تتلقّى الخدمة الطلب، يتم إنشاء إدخال جديد وحذف الإدخال القديم تلقائيًا بعد 60 يومًا. يستخدم النظام دائمًا أحدث إدخال. في حال حدوث خطأ، يتم رفض الطلب بأكمله ويتم الحفاظ على الحالة الحالية.
تحديث الاشتراك
- لتقديم تحديثات فورية عند إجراء تغييرات، عليك استدعاء
publishSubscriptionCluster()
كلما تغيّرت حالة اشتراك المستخدم مثل التفعيل أو الإلغاء أو الترقية أو الرجوع إلى إصدار أقدم. لتقديم عملية تحقّق منتظمة من الدقة المستمرة، اتّصِل بالدالة
publishSubscriptionCluster()
مرة واحدة على الأقل شهريًا.لحذف بيانات "اقتراحات الفيديو"، عليك حذف بيانات المستخدم يدويًا من خادم Google TV قبل فترة الاحتفاظ العادية البالغة 60 يومًا، وذلك باستخدام الطريقة
client.deleteClusters()
. يؤدي هذا الإجراء إلى حذف جميع بيانات العثور على الفيديوهات الحالية لملف الحساب أو للحساب بأكمله، وذلك استنادًا إلىDeleteReason
المحدّد.مقتطف الرمز البرمجي لإزالة اشتراك المستخدم
// If the user logs out from your media app, you must make the following call // to remove subscription and other video discovery data from the current // google TV device. client.deleteClusters( new DeleteClustersRequest.Builder() .setAccountProfile( AccountProfile .Builder() .setAccountId() .setProfileId() .build() ) .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT) .build() ) ``` Following code snippet demonstrates removal of user subscription when user revokes the consent. ```Kotlin // If the user revokes the consent to share across device, make the call // to remove subscription and other video discovery data from all google // TV devices. client.deleteClusters( new DeleteClustersRequest.Builder() .setAccountProfile( AccountProfile .Builder() .setAccountId() .setProfileId() .build() ) .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT) .build() ) ``` Following code demonstrates how to remove subscription data on user profile deletion. ```Kotlin // If the user delete a specific profile, you must make the following call // to remove subscription data and other video discovery data. client.deleteClusters( new DeleteClustersRequest.Builder() .setAccountProfile( AccountProfile .Builder() .setAccountId() .setProfileId() .build() ) .setReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION) .build() )
الاختبار
يقدّم هذا القسم دليلاً تفصيليًا لاختبار عملية تنفيذ الاشتراكات. تأكَّد من دقة البيانات والوظائف المناسبة قبل الإطلاق.
قائمة التحقّق من عملية الدمج
يجب أن يتم النشر عندما يكون التطبيق في المقدّمة ويتفاعل معه المستخدم بشكل نشط.
النشر عند:
- يسجّل المستخدم الدخول لأول مرة.
- يغيّر المستخدم الملف الشخصي (في حال توفُّر الملفات الشخصية).
- يشتري المستخدم اشتراكًا جديدًا.
- يرقّي المستخدم اشتراكه.
- انتهاء صلاحية اشتراك المستخدم
تحقَّق مما إذا كان التطبيق يستدعي واجهات برمجة التطبيقات
isServiceAvailable()
وpublishClusters()
بشكل صحيح في logcat عند نشر الأحداث.تأكَّد من أنّ البيانات ظاهرة في تطبيق التحقّق. يجب أن يعرض تطبيق التحقّق الاشتراك كصف منفصل. عند استدعاء واجهة برمجة التطبيقات الخاصة بالنشر، من المفترض أن تظهر البيانات في تطبيق التحقّق.
- تأكَّد من عدم ضبط علامة خدمة التفاعل على الإنتاج في ملف بيان Android الخاص بالتطبيق.
- ثبِّت تطبيق Engage Verification وافتحه.
- إذا كانت قيمة
isServiceAvailable
هيfalse
في تطبيق التحقّق، انقر على الزرToggle
داخل تطبيق التحقّق لضبطها علىtrue
. - أدخِل اسم حزمة التطبيق، وسيتم تلقائيًا عرض البيانات المنشورة.
انتقِل إلى التطبيق ونفِّذ كلّاً من الإجراءات التالية:
- سجِّل الدخول.
- التبديل بين الملفات الشخصية (إذا كان ذلك متاحًا)
- شراء اشتراك جديد
- ترقية اشتراك حالي
- انتهاء صلاحية الاشتراك
التأكّد من عملية الدمج
لاختبار عملية الدمج، استخدِم .
تطبيق التحقّق هو تطبيق Android يمكن للمطوّرين استخدامه للتأكّد من أنّ عملية الدمج تعمل بشكل صحيح. يتضمّن التطبيق إمكانات لمساعدة المطوّرين في التحقّق من البيانات وبث الأهداف. ويساعد ذلك في التحقّق من دقة البيانات وسلامة الوظائف قبل الإطلاق.
- بالنسبة إلى كل حدث من الأحداث، تحقَّق مما إذا كان التطبيق قد استدعى واجهة برمجة التطبيقات
publishSubscription
. تحقَّق من البيانات المنشورة في تطبيق التحقّق. التأكّد من أنّ كل شيء باللون الأخضر في تطبيق التحقّق إذا كانت جميع معلومات المؤسسة صحيحة، ستظهر علامة صح خضراء "كل شيء على ما يرام" في جميع المؤسسات.
الشكل 1. الاشتراك بنجاح يتم أيضًا تمييز المشاكل في تطبيق التحقّق
الشكل 2.تعذّر الاشتراك للاطّلاع على المشاكل في الاشتراك المجمّع، استخدِم جهاز التحكّم عن بُعد في التلفزيون للتركيز على هذا الاشتراك المجمّع المحدّد، ثم انقر للاطّلاع على المشاكل. قد تحتاج أولاً إلى التركيز على الصف والانتقال إلى اليسار للعثور على بطاقة "الاشتراك المجمّع". يتم تمييز المشاكل باللون الأحمر كما هو موضّح في الشكل 3. يمكنك أيضًا استخدام جهاز التحكّم عن بُعد للانتقال إلى الأسفل والاطّلاع على المشاكل في الأذونات ضمن الاشتراك المجمّع.
الشكل 3:أخطاء الاشتراك للاطّلاع على المشاكل في حق الوصول، استخدِم جهاز التحكّم عن بُعد في التلفزيون للتركيز على حق الوصول المحدّد هذا، ثم انقر عليه للاطّلاع على المشاكل. يتم تمييز المشاكل باللون الأحمر.
الشكل 4:تفاصيل خطأ الاشتراك
تنزيل
قبل تنزيل التطبيق، عليك الموافقة على الأحكام والشروط التالية.