يحتوي هذا الدليل على تعليمات للمطوّرين لمشاركة بيانات اشتراك التطبيق وإذن استخدامه مع 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
إذا كان التطبيق يقدّم حِزم اشتراكات Premium متعددة المستويات، تتضمّن محتوًى أو ميزات موسّعة تتجاوز المستوى الشائع، يجب تمثيل ذلك من خلال إضافة إذن استخدام واحد أو أكثر إلى الاشتراك.
يحتوي إذن الاستخدام هذا على الحقول التالية:
Identifier: سلسلة معرّف مطلوبة لإذن الاستخدام هذا يجب أن يتطابق هذا المعرّف مع أحد معرّفات إذن الاستخدام (يُرجى العِلم أنّ هذا ليس حقل المعرّف) المقدَّمة في خلاصة مقدِّم الوسائط المنشورة على Google TV.Name: هذه معلومات إضافية تُستخدم لمطابقة إذن الاستخدام. على الرغم من أنّ هذا الحقل اختياري، فإنّ تقديم اسم إذن استخدام قابل للقراءة يحسّن فهم أذونات استخدام المستخدمين لكلٍّ من المطوّرين وفِرق الدعم. على سبيل المثال: Sling OrangeExpirationTimeMillis: يمكن تحديد وقت انتهاء الصلاحية بالملّي ثانية لإذن الاستخدام هذا، إذا كان يختلف عن وقت انتهاء صلاحية الاشتراك. سينتهي تلقائيًا إذن استخدام الاشتراك مع انتهاء صلاحية الاشتراك.
بالنسبة إلى مقتطف خلاصة مقدِّم الوسائط النموذجية التالية:
"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مرة واحدة على الأقل شهريًا.لحذف بيانات Engage، يجب حذف بيانات المستخدم يدويًا من خادم Google TV قبل فترة الاحتفاظ العادية البالغة 60 يومًا، وذلك باستخدام طريقة
client.deleteClusters. يؤدي ذلك إلى حذف جميع بيانات Engage الحالية للملف الشخصي للحساب أو للحساب بأكمله استنادًا إلى المحدّدةDeleteReason.يوضّح مقتطف الرمز البرمجي التالي كيفية إزالة اشتراك مستخدم:
// If the user logs out from your media app, you must make the following call // to remove subscription and other Engage 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 Engage 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 Engage 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.تفاصيل خطأ الاشتراك