book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml
يتضمّن هذا الدليل تعليمات للمطوّرين لمشاركة بيانات اشتراك التطبيق والأهلية مع Google TV باستخدام Engage SDK. يمكن للمستخدمين العثور على المحتوى الذي يحق لهم الوصول إليه والسماح لـ Google TV بتقديم اقتراحات محتوى ذات صلة عالية للمستخدمين مباشرةً ضمن تجارب Google TV على التلفزيون والأجهزة الجوّالة والأجهزة اللوحية.
المتطلّبات الأساسية
يجب إعداد خلاصة "إجراءات الوسائط" قبل استخدام واجهة برمجة التطبيقات الخاصة بأذونات الجهاز. إذا لم يسبق لك ذلك، أكمل عملية إعداد خلاصة مهام الوسائط.
العمل التحضيري
أكمِل تعليمات العمل التحضيري في دليل البدء.
- نشر معلومات الاشتراك عند وقوع الأحداث التالية:
- يسجّل المستخدم الدخول إلى تطبيقك.
- يبدّل المستخدم بين الملفات الشخصية (إذا كانت الملفات الشخصية متاحة).
- يشتري المستخدم اشتراكًا جديدًا.
- يرقّي المستخدم اشتراكًا حاليًا.
- تنتهي صلاحية اشتراك المستخدم.
التكامل
يقدّم هذا القسم أمثلة على الرموز والإرشادات اللازمة لتنفيذ SubscriptionEntity من أجل إدارة أنواع الاشتراكات المختلفة.
اشتراك في مستوى مشترك
بالنسبة إلى المستخدمين الذين لديهم اشتراكات أساسية في خدمات مقدّم المحتوى الإعلامي، مثل خدمة تتضمّن فئة اشتراك واحدة تتيح الوصول إلى كل المحتوى المدفوع، يُرجى تقديم التفاصيل الأساسية التالية:
SubscriptionType: تشير هذه السمة بوضوح إلى خطة الاشتراك المحدّدة التي اشترك فيها المستخدم.-
SUBSCRIPTION_TYPE_ACTIVE: يشير إلى أنّ المستخدم لديه اشتراك مدفوع نشط. -
SUBSCRIPTION_TYPE_ACTIVE_TRIAL: يملك المستخدم اشتراكًا تجريبيًا. -
SUBSCRIPTION_TYPE_INACTIVE: يعني أنّ المستخدم لديه حساب ولكن ليس لديه اشتراك نشط أو فترة تجريبية نشطة.
-
ExpirationTimeMillis: وقت اختياري بالملّي ثانية. حدِّد تاريخ انتهاء صلاحية الاشتراك.استبدِل
ProviderPackageNameباسم حزمة التطبيق الذي يتعامل مع الاشتراك.
مثال على خلاصة مقدّم المحتوى الإعلامي النموذجية
"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
إذا كان التطبيق يقدّم حِزم اشتراك مدفوع متعددة المستويات تتضمّن محتوًى أو ميزات موسّعة تتجاوز المستوى الشائع، يمكنك توضيح ذلك من خلال إضافة إذن واحد أو أكثر إلى الاشتراك.
يتضمّن إذن الوصول هذا الحقول التالية:
Identifier: سلسلة المعرّف المطلوبة لهذا الإذن. يجب أن يتطابق هذا المعرّف مع أحد معرّفات الاستحقاق (يُرجى العِلم أنّ هذا ليس حقل المعرّف) المقدَّمة في خلاصة مقدّم المحتوى المنشورة على Google TV.-
Name: هذه معلومات مساعدة تُستخدم لمطابقة حقوق الملكية. على الرغم من أنّ توفير اسم إذن سهل القراءة للمستخدم أمر اختياري، إلا أنّه يحسّن فهم الأذونات الممنوحة للمستخدمين لكلّ من المطوّرين وفِرق الدعم. على سبيل المثال: Sling Orange. -
ExpirationTimeMillis: يمكنك اختياريًا تحديد وقت انتهاء الصلاحية بالملّي ثانية لإذن الاستخدام هذا، إذا كان يختلف عن وقت انتهاء صلاحية الاشتراك. بشكل تلقائي، ستنتهي صلاحية حق الاستخدام عند انتهاء صلاحية الاشتراك.
إليك مقتطفًا من خلاصة مقدّم خدمة وسائط نموذجية:
"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.
احرص على تهيئة العميل والتحقّق من توفّر الخدمة كما هو موضّح في دليل البدء.
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) .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT) .build() )يوضّح مقتطف الرمز التالي كيفية إزالة اشتراك المستخدم عندما يلغي المستخدم موافقته:
// 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) .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT) .build() )يوضّح الرمز التالي كيفية إزالة بيانات الاشتراك عند حذف ملف المستخدم.
// 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) .setReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION) .build() )
الاختبار
يقدّم هذا القسم دليلاً تفصيليًا لاختبار عملية تنفيذ الاشتراكات. تحقَّق من دقة البيانات والوظائف المناسبة قبل الإطلاق.
قائمة مهام نشر عملية الدمج
يجب أن يتم النشر عندما يكون التطبيق في المقدّمة ويتفاعل المستخدم معه بشكل نشط.
النشر عند:
- يسجّل المستخدم الدخول لأول مرة.
- يغيّر المستخدم الملف الشخصي (في حال توفّر الملفات الشخصية).
- يشتري المستخدم اشتراكًا جديدًا.
- يرقّي المستخدم اشتراكه.
- تنتهي صلاحية اشتراك المستخدم.
تحقَّق مما إذا كان التطبيق يستدعي واجهات برمجة التطبيقات
isServiceAvailable()وpublishClusters()بشكل صحيح في logcat عند نشر الأحداث.تأكَّد من ظهور البيانات في تطبيق التحقّق. من المفترض أن يعرض تطبيق التحقّق الاشتراك كصف منفصل. عند استدعاء واجهة برمجة التطبيقات للنشر، من المفترض أن تظهر البيانات في تطبيق التحقّق.
انتقِل إلى التطبيق ونفِّذ كلّاً من الإجراءات التالية:
- سجِّل الدخول.
- التبديل بين الملفات الشخصية (إذا كان ذلك متاحًا)
- شراء اشتراك جديد
- ترقية اشتراك حالي
- انتهاء صلاحية الاشتراك
تأكيد عملية الدمج
لاختبار عملية الدمج، استخدِم تطبيق التحقّق.
- بالنسبة إلى كل حدث من الأحداث، تحقَّق مما إذا كان التطبيق قد استدعى واجهة برمجة التطبيقات
publishSubscription. تحقَّق من البيانات المنشورة في تطبيق التحقّق. التأكّد من أنّ كل شيء باللون الأخضر في تطبيق التحقّق إذا كانت جميع معلومات المؤسسة صحيحة، ستظهر علامة تحقّق خضراء "كل شيء على ما يرام" في جميع المؤسسات.
الشكل 1. الاشتراك بنجاح يتم أيضًا تمييز المشاكل في تطبيق التحقّق
الشكل 2.تعذُّر الاشتراك للاطّلاع على المشاكل في الاشتراك المجمّع، استخدِم جهاز التحكّم عن بُعد في التلفزيون للتركيز على هذا الاشتراك المجمّع المحدّد، ثم انقر للاطّلاع على المشاكل. قد تحتاج أولاً إلى التركيز على الصف والانتقال إلى اليسار للعثور على بطاقة "الاشتراك المجمّع". يتم تمييز المشاكل باللون الأحمر كما هو موضّح في الشكل 3. يمكنك أيضًا استخدام جهاز التحكّم عن بُعد للانتقال إلى الأسفل والاطّلاع على المشاكل في الأذونات ضمن الاشتراك المجمّع.
الشكل 3.أخطاء الاشتراك للاطّلاع على المشاكل في حق الوصول، استخدِم جهاز التحكّم عن بُعد في التلفزيون للتركيز على حق الوصول المحدّد هذا، ثم انقر عليه للاطّلاع على المشاكل. يتم تمييز المشاكل باللون الأحمر.
الشكل 4.تفاصيل خطأ الاشتراك