این راهنما شامل دستورالعملهایی برای توسعهدهندگان است تا محتوای ویدیویی پیشنهادی خود را با استفاده از Engage SDK ادغام کنند تا تجربیات توصیهها را در سطوح مختلف گوگل، مانند تلویزیون، موبایل و تبلت، ارائه دهند.
پیشنهاد (Recommendation) از خوشه پیشنهاد برای نمایش فیلمها و برنامههای تلویزیونی از چندین برنامه در یک گروهبندی رابط کاربری استفاده میکند. هر شریک توسعهدهنده میتواند حداکثر ۲۵ موجودیت را در هر خوشه پیشنهاد پخش کند و حداکثر ۷ خوشه پیشنهاد برای هر درخواست وجود دارد.
پیش کار
قبل از شروع، مراحل زیر را انجام دهید: ۱. تأیید کنید که اهداف برنامه شما برای این ادغام، API سطح ۱۹ یا بالاتر باشد.
کتابخانه
com.google.android.engageرا به برنامه خود اضافه کنید.برای ادغام، SDK های جداگانهای وجود دارد: یکی برای برنامههای موبایل و دیگری برای برنامههای تلویزیونی.
برای موبایل
dependencies { implementation 'com.google.android.engage:engage-core:1.5.9 }برای تلویزیون
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.5 }محیط سرویس Engage را در فایل
AndroidManifest.xmlروی production تنظیم کنید.برای 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>اجرای عملیات انتشار در یک سرویس پیشزمینه.
دادههای توصیهها را حداکثر روزی یک بار، که توسط هر یک از موارد زیر انجام میشود، منتشر کنید
- اولین ورود کاربر در روز. ( یا )
- وقتی کاربر شروع به تعامل با برنامه میکند.
ادغام
AppEngagePublishClient خوشه توصیه را منتشر میکند. از متد publishRecommendationClusters برای انتشار یک شیء توصیه استفاده کنید.
برای بررسی اینکه آیا سرویس برای ادغام در دسترس است یا خیر، از isServiceAvailable() 2 استفاده کنید.
val client = AppEngagePublishClient(context)
client.isServiceAvailable().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Handle IPC call success
if(task.result) {
// Service is available on the device, proceed with content publish
// calls.
client.publishRecommendationClusters(recommendationRequest)
} else {
// Service is not available
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
}
خوشههای توصیه و درخواست انتشار
خوشهها گروهبندی منطقی موجودیتها هستند. نمونههای کد زیر نحوه ساخت خوشهها بر اساس ترجیح شما و نحوه ایجاد درخواست انتشار برای همه خوشهها را توضیح میدهد.
// cluster for popular movies
val recommendationCluster1 = RecommendationCluster
.Builder()
.addEntity(movie1)
.addEntity(movie2)
.addEntity(movie3)
.addEntity(movie4)
.addEntity(tvShow)
// This cluster is meant to be used as an individual provider row
.setRecommendationClusterType(TYPE_PROVIDER_ROW)
.setTitle("Popular Movies")
.build()
// cluster for live TV programs
val recommendationCluster2 = RecommendationCluster
.Builder()
.addEntity(liveTvProgramEntity1)
.addEntity(liveTvProgramEntity2)
.addEntity(liveTvProgramEntity3)
.addEntity(liveTvProgramEntity4)
.addEntity(liveTvProgramEntity5)
// This cluster is meant to be used as an individual provider row
.setRecommendationClusterType(TYPE_PROVIDER_ROW)
.setTitle("Popular Live TV Programs")
.build()
// creating a publishing request
val recommendationRequest = PublishRecommendationClustersRequest
.Builder()
.setSyncAcrossDevices(true)
.setAccountProfile(accountProfile)
.addRecommendationCluster(recommendationCluster1)
.addRecommendationCluster(recommendationCluster2)
.build()
ایجاد پروفایل حساب کاربری
برای ایجاد یک تجربه شخصیسازیشده در Google TV، اطلاعات حساب و نمایه را ارائه دهید. از AccountProfile برای ارائه موارد زیر استفاده کنید:
- شناسه حساب: یک شناسه منحصر به فرد که نشان دهنده حساب کاربر در برنامه شما است. این میتواند شناسه واقعی حساب یا یک نسخه مبهمسازی شده مناسب باشد.
- شناسه پروفایل (اختیاری): اگر برنامه شما از چندین پروفایل در یک حساب کاربری پشتیبانی میکند، یک شناسه منحصر به فرد برای پروفایل کاربر خاص ارائه دهید.
- زبان (اختیاری): میتوانید به صورت اختیاری زبان مورد نظر کاربر را وارد کنید. این فیلد در صورتی مفید است که بخواهید
MediaActionFeedEntityدرRecommendationRequestارسال کنید.
// If app only supports account
val accountProfile = AccountProfile.Builder()
.setAccountId("account_id")
.build();
// If app supports both account and profile
val accountProfile = AccountProfile.Builder()
.setAccountId("account_id")
.setProfileId("profile_id")
.build();
// set Locale
val accountProfile = AccountProfile.Builder()
.setAccountId("account_id")
.setProfileId("profile_id")
.setLocale("en-US")
.build();
وقتی سرویس درخواست را دریافت میکند، اقدامات زیر در یک تراکنش انجام میشود:
- دادههای موجود در
RecommendationsClusterاز شریک توسعهدهنده حذف شده است. - دادههای درخواست تجزیه و تحلیل شده و در
RecommendationsClusterبهروزرسانیشده ذخیره میشوند. در صورت بروز خطا، کل درخواست رد شده و وضعیت موجود حفظ میشود.
همگامسازی بین دستگاهی
پرچم SyncAcrossDevices کنترل میکند که آیا دادههای خوشهبندی توصیههای کاربر با Google TV به اشتراک گذاشته شود و در دستگاههای او مانند تلویزیون، تلفن، تبلت در دسترس باشد یا خیر. برای اینکه این توصیه کار کند، باید روی true تنظیم شود.
اخذ رضایت
برنامه رسانه باید تنظیمات واضحی برای فعال یا غیرفعال کردن همگامسازی بین دستگاهها ارائه دهد. مزایای آن را برای کاربر توضیح دهید و ترجیح کاربر را یک بار ذخیره کنید و آن را در درخواست publishRecommendations اعمال کنید. برای بهرهمندی حداکثری از ویژگی بین دستگاهی، تأیید کنید که برنامه رضایت کاربر را دریافت میکند و SyncAcrossDevices روی true فعال میکند.
دادههای کشف ویدیو را حذف کنید
برای حذف دستی دادههای یک کاربر از سرور Google TV قبل از دوره نگهداری استاندارد ۶۰ روزه، از متد client.deleteClusters() استفاده کنید. پس از دریافت درخواست، سرویس تمام دادههای کشف ویدیوی موجود را برای نمایه حساب یا برای کل حساب حذف میکند.
تابع DeleteReason دلیل حذف دادهها را تعریف میکند. کد زیر توصیهها را در هنگام خروج حذف میکند.
// If the user logs out from your media app, you must make the following call
// to remove recommendations data from the current google TV device,
// otherwise, the recommendations data persists on the current
// google TV device until 60 days later.
client.deleteClusters(
new DeleteClustersRequest.Builder()
.setAccountProfile(AccountProfile())
.setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
.build()
)
// If the user revokes the consent to share data with Google TV,
// you must make the following call to remove recommendations data from
// all current google TV devices. Otherwise, the recommendations data persists
// until 60 days later.
client.deleteClusters(
new DeleteClustersRequest.Builder()
.setAccountProfile(AccountProfile())
.setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
.build()
)
ایجاد موجودیتها
SDK برای نمایش هر نوع آیتم، موجودیتهای مختلفی تعریف کرده است. موجودیتهای زیر برای خوشه توصیه پشتیبانی میشوند:
-
MediaActionFeedEntity -
MovieEntity -
TvShowEntity -
LiveTvChannelEntity -
LiveTvProgramEntity
توضیحات
برای هر موجودیت توضیح کوتاهی ارائه دهید؛ این توضیح زمانی که کاربران موس را روی آن موجودیت نگه میدارند نمایش داده میشود و جزئیات بیشتری را در اختیار آنها قرار میدهد.
URI های پخش ویژه پلتفرم
برای هر پلتفرم پشتیبانیشده: اندروید تیوی، اندروید یا iOS، URIهای پخش ایجاد کنید. این به سیستم اجازه میدهد URI مناسب را برای پخش ویدیو در پلتفرم مربوطه انتخاب کند.
در موارد نادری که URI های پخش برای همه پلتفرمها یکسان هستند، آن را برای هر پلتفرم تکرار کنید.
// Required. Set this when you want recommended entities to show up on
// Google TV
val playbackUriTv = PlatformSpecificUri
.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_TV)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_tv"))
.build()
// Optional. Set this when you want recommended entities to show up on
// Google TV Android app
val playbackUriAndroid = PlatformSpecificUri
.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_MOBILE)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_android"))
.build()
// Optional. Set this when you want recommended entities to show up on
// Google TV iOS app
val playbackUriIos = PlatformSpecificUri
.Builder()
.setPlatformType(PlatformType.TYPE_IOS)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_ios"))
.build()
val platformSpecificPlaybackUris =
Arrays.asList(playbackUriTv, playbackUriAndroid, playbackUriIos)
// Provide appropriate rating for the system.
val contentRating = new RatingSystem
.Builder()
.setAgencyName("MPAA")
.setRating("PG-13")
.build()
تصاویر پوستر
تصاویر پوستر به یک URI و ابعاد پیکسلی (ارتفاع و عرض) نیاز دارند. با ارائه چندین تصویر پوستر، فرم فاکتورهای مختلف را هدف قرار دهید، اما برای نمایش صحیح موجودیت «توصیهها»، به ویژه در فضای سرگرمی گوگل، اطمینان حاصل کنید که همه تصاویر نسبت ابعاد ۱۶:۹ و حداقل ارتفاع ۲۰۰ پیکسل را حفظ میکنند. تصاویری با ارتفاع کمتر از ۲۰۰ پیکسل ممکن است نمایش داده نشوند.
Image image1 = new Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image1.png");)
.setImageHeightInPixel(300)
.setImageWidthInPixel(169)
.build()
Image image2 = new Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image2.png");)
.setImageHeightInPixel(640)
.setImageWidthInPixel(360)
.build()
// And other images for different form factors.
val images = Arrays.asList(image1, image2)
دلیل توصیه
در صورت تمایل، دلیل پیشنهادی را ارائه دهید که گوگل تیوی میتواند از آن برای ایجاد دلایلی برای پیشنهاد یک فیلم یا سریال خاص به کاربر استفاده کند.
//Allows us to construct reason: "Because it is top 10 on your Channel"
val topOnPartner = RecommendationReasonTopOnPartner
.Builder()
.setNum(10) //any valid integer value
.build()
//Allows us to construct reason: "Because it is popular on your Channel"
val popularOnPartner = RecommendationReasonPopularOnPartner
.Builder()
.build()
//Allows us to construct reason: "New to your channel, or Just added"
val newOnPartner = RecommendationReasonNewOnPartner
.Builder()
.build()
//Allows us to construct reason: "Because you watched Star Wars"
val watchedSimilarTitles = RecommendationReasonWatchedSimilarTitles
.addSimilarWatchedTitleName("Movie or TV Show Title")
.addSimilarWatchedTitleName("Movie or TV Show Title")
.Builder()
.build()
//Allows us to construct reason: "Recommended for you by ChannelName"
val recommendedForUser = RecommendationReasonRecommendedForUser
.Builder()
.build()
val watchAgain = RecommendationReasonWatchAgain
.Builder()
.build()
val fromUserWatchList = RecommendationReasonFromUserWatchlist
.Builder()
.build()
val userLikedOnPartner = RecommendationReasonUserLikedOnPartner
.Builder()
.setTitleName("Movie or TV Show Title")
.build()
val generic = RecommendationReasonGeneric.Builder().build()
نمایش پنجره زمان
اگر یک موجودیت فقط برای مدت زمان محدودی در دسترس باشد، یک زمان انقضای سفارشی تعیین کنید. بدون زمان انقضای صریح، موجودیتها پس از ۶۰ روز به طور خودکار منقضی و پاک میشوند. بنابراین فقط زمانی که موجودیتها نیاز به انقضای زودتر دارند، زمان انقضا را تعیین کنید. چندین پنجرهی در دسترس بودن از این قبیل را مشخص کنید.
val window1 = DisplayTimeWindow
.Builder()
.setStartTimeStampMillis(now()+ 1.days.toMillis())
.setEndTimeStampMillis(now()+ 30.days.toMillis())
val window2 = DisplayTimeWindow
.Builder()
.setEndTimeStampMillis(now()+ 30.days.toMillis())
val availabilityTimeWindows: List<DisplayTimeWindow> = listof(window1,window2)
شناسه عنصر داده
اگر کاتالوگ رسانه یا فید اکشن رسانه خود را با Google TV ادغام کردهاید، نیازی به ایجاد موجودیتهای جداگانه برای فیلم یا نمایش تلویزیونی ندارید و در عوض میتوانید یک موجودیت MediaActionFeed ایجاد کنید که شامل فیلد مورد نیاز DataFeedElementId باشد. این شناسه باید منحصر به فرد باشد و با شناسه موجود در Media Action Feed مطابقت داشته باشد زیرا به شناسایی محتوای فید مصرف شده و انجام جستجوی محتوای رسانه کمک میکند.
val id = "dataFeedEleemntId"
MovieEntity
در اینجا مثالی از ایجاد یک MovieEntity با تمام فیلدهای مورد نیاز آورده شده است:
val movieEntity = MovieEntity.Builder()
.setName("Movie name")
.setDescription("A sentence describing movie.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
// Suppose the duration is 2 hours, it is 72000000 in milliseconds
.setDurationMills(72000000)
.build()
شما میتوانید دادههای اضافی مانند ژانرها، رتبهبندی محتوا، تاریخ انتشار، دلیل توصیه و بازههای زمانی در دسترس بودن را ارائه دهید که ممکن است توسط Google TV برای نمایشهای پیشرفته یا اهداف فیلترینگ استفاده شود.
val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("pg-13").build();
val contentRatings = Arrays.asList(rating1);
//Suppose release date is 11-02-2025
val releaseDate = 1739233800000L
val movieEntity = MovieEntity.Builder()
...
.addGenres(genres)
.setReleaseDateEpochMillis(releaseDate)
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addAllAvailabilityTimeWindows(availabilityTimeWindows)
.build()
TvShowEntity
در اینجا مثالی از ایجاد یک TvShowEntity با تمام فیلدهای مورد نیاز آورده شده است:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.build();
در صورت تمایل، دادههای اضافی مانند ژانرها، رتبهبندی محتوا، دلیل توصیه، قیمت پیشنهادی، تعداد فصل یا بازه زمانی در دسترس بودن را ارائه دهید که ممکن است توسط Google TV برای نمایشهای پیشرفته یا اهداف فیلترینگ استفاده شود.
val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build();
val price = Price.Builder()
.setCurrentPrice("$14.99")
.setStrikethroughPrice("$16.99")
.build();
val contentRatings = Arrays.asList(rating1);
val seasonCount = 5;
val tvShowEntity = TvShowEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addAllAvailabilityTimeWindows(availabilityTimeWindows)
.setSeasonCount(seasonCount)
.setPrice(price)
.build()
MediaActionFeedEntity
در اینجا مثالی از ایجاد یک MediaActionFeedEntity با تمام فیلدهای مورد نیاز آورده شده است:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.build()
در صورت تمایل، دادههای اضافی مانند توضیحات، دلیل توصیه و پنجره زمانی نمایش را ارائه دهید که ممکن است توسط Google TV برای نمایشهای پیشرفته یا اهداف فیلترینگ استفاده شود.
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setName("Movie name or TV Show name")
.setDescription("A sentence describing an entity")
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addPosterImages(images)
.build()
LiveTvChannelEntity
این نشان دهنده یک کانال تلویزیونی زنده است. در اینجا مثالی از ایجاد یک LiveTvChannelEntity با تمام فیلدهای مورد نیاز آورده شده است:
val liveTvChannelEntity = LiveTvChannelEntity.Builder()
.setName("Channel Name")
// ID of the live TV channel
.setEntityId("https://www.example.com/channel/12345")
.setDescription("A sentence describing this live TV channel.")
// channel playback uri must contain at least PlatformType.TYPE_ANDROID_TV
.addPlatformSpecificPlaybackUri(channelPlaybackUris)
.addLogoImage(logoImage)
.build()
در صورت تمایل، دادههای اضافی مانند رتبهبندی محتوا یا دلیل توصیه را ارائه دهید.
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build()
val contentRatings = Arrays.asList(rating1)
val liveTvChannelEntity = LiveTvChannelEntity.Builder()
...
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner)
.build()
LiveTvProgramEntity
این نشان دهنده یک کارت برنامه تلویزیونی زنده است که در حال پخش است یا قرار است در یک کانال تلویزیونی زنده پخش شود. در اینجا مثالی از ایجاد یک LiveTvProgramEntity با تمام فیلدهای مورد نیاز آورده شده است:
val liveTvProgramEntity = LiveTvProgramEntity.Builder()
// First set the channel information
.setChannelName("Channel Name")
.setChanelId("https://www.example.com/channel/12345")
// channel playback uri must contain at least PlatformType.TYPE_ANDROID_TV
.addPlatformSpecificPlaybackUri(channelPlaybackUris)
.setChannelLogoImage(channelLogoImage)
// Then set the program or card specific information.
.setName("Program Name")
.setEntityId("https://www.example.com/schedule/123")
.setDescription("Program Desccription")
.addAvailabilityTimeWindow(
DisplayTimeWindow.Builder()
.setStartTimestampMillis(1756713600000L)// 2025-09-01T07:30:00+0000
.setEndTimestampMillis(1756715400000L))// 2025-09-01T08:00:00+0000
.addPosterImage(programImage)
.build()
در صورت تمایل، دادههای اضافی مانند رتبهبندی محتوا، ژانرها یا دلیل توصیه را ارائه دهید.
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build()
val contentRatings = Arrays.asList(rating1)
val genres = Arrays.asList("Action", "Science fiction")
val liveTvProgramEntity = LiveTvProgramEntity.Builder()
...
.addContentRatings(contentRatings)
.addGenres(genres)
.setRecommendationReason(topOnPartner)
.build()
با اجرای این مراحل، توسعهدهندگان میتوانند با موفقیت پیشنهادهای محتوای ویدیویی را در گوگل تیوی ادغام کنند، کشف و تعامل کاربر را افزایش دهند و یک تجربه مشاهده ثابت و شخصیسازیشده را برای کاربران در تمام دستگاههایشان فراهم کنند.