Hướng dẫn này cung cấp cho nhà phát triển thông tin về cách tích hợp nội dung video đề xuất bằng Engage SDK để điền sẵn trải nghiệm đề xuất trên các nền tảng của Google, chẳng hạn như TV, thiết bị di động và máy tính bảng.
Tính năng Đề xuất tận dụng Cụm đề xuất để hiển thị các bộ phim và chương trình truyền hình từ nhiều ứng dụng trong một nhóm giao diện người dùng. Mỗi đối tác nhà phát triển có thể thông báo về tối đa 25 thực thể trong mỗi cụm đề xuất và mỗi yêu cầu có thể có tối đa 7 cụm đề xuất.
Chuẩn bị trước
Trước khi bắt đầu, hãy hoàn tất các bước sau. 1. Xác minh rằng ứng dụng của bạn nhắm đến API cấp 19 trở lên để tích hợp.
Thêm thư viện
com.google.android.engage
vào ứng dụng của bạn.Có các SDK riêng biệt để sử dụng trong quá trình tích hợp: một SDK cho ứng dụng di động và một SDK cho ứng dụng TV.
Đối với thiết bị di động
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
cho TV
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
Đặt môi trường dịch vụ Engage thành môi trường phát hành chính thức trong tệp
AndroidManifest.xml
.Đối với tệp APK dành cho thiết bị di động
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Đối với tệp APK dành cho TV
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Thực thi việc phát hành trên một dịch vụ trên nền trước.
Phát hành dữ liệu Đề xuất tối đa một lần mỗi ngày, được kích hoạt bởi một trong hai
- Lần đăng nhập đầu tiên của người dùng trong ngày. (hoặc)
- Khi người dùng bắt đầu tương tác với ứng dụng.
Tích hợp
AppEngagePublishClient
phát hành cụm đề xuất. Sử dụng phương thức publishRecommendationClusters
để phát hành đối tượng đề xuất.
Sử dụng isServiceAvailable()
2 để kiểm tra xem dịch vụ có thể tích hợp hay không.
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.
}
}
Cụm đề xuất và yêu cầu xuất bản
Cụm là nhóm các thực thể theo logic. Các ví dụ về mã sau đây giải thích cách tạo cụm dựa trên lựa chọn ưu tiên của bạn và cách tạo yêu cầu phát hành cho tất cả cụm.
// cluster for popular movies
val recommendationCluster1 = RecommendationCluster
.Builder()
.addEntity(movie)
.addEntity(tvShow)
.setTitle("Popular Movies")
.build()
// cluster for top searches
val recommendationCluster2 = RecommendationCluster
.Builder()
.addEntity(movie)
.addEntity(tvShow)
.setTitle("Top Searches")
.build()
// creating a publishing request
val recommendationRequest = PublishRecommendationClustersRequest
.Builder()
.setSyncAcrossDevices(true)
.setAccountProfile(accountProfile)
.addRecommendationCluster(recommendationCluster1)
.addRecommendationCluster(recommendationCluster2)
.build()
Tạo hồ sơ tài khoản
Để có trải nghiệm phù hợp trên Google TV, hãy cung cấp thông tin về tài khoản và hồ sơ. Sử dụng AccountProfile
để cung cấp:
- Mã tài khoản: Giá trị nhận dạng duy nhất đại diện cho tài khoản của người dùng trong ứng dụng của bạn. Đây có thể là mã tài khoản thực tế hoặc một phiên bản được làm rối mã nguồn một cách thích hợp.
- Mã hồ sơ (không bắt buộc): Nếu ứng dụng của bạn hỗ trợ nhiều hồ sơ trong một tài khoản, hãy cung cấp giá trị nhận dạng duy nhất cho hồ sơ người dùng cụ thể.
- Ngôn ngữ(không bắt buộc): Bạn có thể cung cấp ngôn ngữ mà người dùng ưu tiên.
Trường này hữu ích nếu bạn gửi
MediaActionFeedEntity
trongRecommendationRequest
.
// 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();
Khi dịch vụ nhận được yêu cầu, các hành động sau đây sẽ diễn ra trong một giao dịch:
- Dữ liệu
RecommendationsCluster
hiện có của đối tác nhà phát triển sẽ bị xoá. - Dữ liệu của yêu cầu được phân tích cú pháp và lưu trữ trong
RecommendationsCluster
đã cập nhật. Trong trường hợp xảy ra lỗi, toàn bộ yêu cầu sẽ bị từ chối và trạng thái hiện tại sẽ được duy trì.
Đồng bộ hoá trên nhiều thiết bị
Cờ SyncAcrossDevices
kiểm soát việc dữ liệu cụm đề xuất của người dùng có được chia sẻ với Google TV và có trên các thiết bị của họ như TV, điện thoại, máy tính bảng hay không. Để đề xuất hoạt động, bạn phải đặt giá trị này thành true.
Yêu cầu đồng ý
Ứng dụng đa phương tiện phải cung cấp chế độ cài đặt rõ ràng để bật hoặc tắt tính năng đồng bộ hoá trên nhiều thiết bị. Giải thích lợi ích cho người dùng và lưu trữ lựa chọn ưu tiên của người dùng một lần, sau đó áp dụng lựa chọn đó trong Yêu cầu publishRecommendations
cho phù hợp. Để khai thác tối đa tính năng trên nhiều thiết bị, hãy xác minh ứng dụng có được sự đồng ý của người dùng và bật SyncAcrossDevices
thành true
.
Xoá dữ liệu khám phá video
Để xoá dữ liệu của người dùng khỏi máy chủ Google TV theo cách thủ công trước khoảng thời gian lưu giữ tiêu chuẩn là 60 ngày, hãy sử dụng phương thức client.deleteClusters()
. Khi nhận được yêu cầu, dịch vụ sẽ xoá tất cả dữ liệu hiện có về tính năng Khám phá video cho hồ sơ tài khoản hoặc cho toàn bộ tài khoản.
Enum DeleteReason
xác định lý do xoá dữ liệu.
Mã sau đây sẽ xoá các đề xuất khi đăng xuất.
// 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()
)
Tạo thực thể
SDK đã xác định các thực thể khác nhau để đại diện cho từng loại mục. Sau đây là các thực thể được hỗ trợ cho cụm Đề xuất:
MediaActionFeedEntity
MovieEntity
TvShowEntity
Mô tả
Cung cấp nội dung mô tả ngắn gọn cho từng thực thể; nội dung mô tả này sẽ xuất hiện khi người dùng di chuột qua thực thể, cung cấp cho họ thêm thông tin chi tiết.
URI phát lại dành riêng cho nền tảng
Tạo URI phát cho từng nền tảng được hỗ trợ: Android TV, Android hoặc iOS. Điều này cho phép hệ thống chọn URI thích hợp để phát video trên nền tảng tương ứng.
Trong trường hợp hiếm gặp khi URI phát lại giống nhau cho tất cả nền tảng, hãy lặp lại URI đó cho mọi nền tảng.
// 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()
Hình ảnh áp phích
Hình ảnh áp phích cần có URI và kích thước pixel (chiều cao và chiều rộng). Nhắm đến nhiều kiểu dáng bằng cách cung cấp nhiều hình ảnh áp phích, nhưng hãy xác minh rằng tất cả hình ảnh đều duy trì tỷ lệ khung hình 16:9 và chiều cao tối thiểu là 200 pixel để hiển thị chính xác thực thể "Đề xuất", đặc biệt là trong Entertainment Space của Google. Hình ảnh có chiều cao dưới 200 pixel có thể không hiển thị.
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)
Lý do đề xuất
Bạn có thể cung cấp lý do đề xuất mà Google TV có thể sử dụng để xây dựng lý do đề xuất một Phim hoặc Chương trình truyền hình cụ thể cho người dùng.
//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()
Hiển thị khoảng thời gian
Nếu một thực thể chỉ có sẵn trong một khoảng thời gian giới hạn, hãy đặt thời gian hết hạn tùy chỉnh. Nếu không có thời gian hết hạn rõ ràng, các thực thể sẽ tự động hết hạn và bị xoá sau 60 ngày. Vì vậy, hãy chỉ đặt thời gian hết hạn khi các thực thể cần hết hạn sớm hơn. Chỉ định nhiều khoảng thời gian có sẵn như vậy.
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)
DataFeedElementId
Nếu đã tích hợp Danh mục nội dung nghe nhìn hoặc Nguồn cấp dữ liệu hành động nội dung nghe nhìn với Google TV, bạn không cần tạo các thực thể riêng biệt cho Phim hoặc Chương trình truyền hình. Thay vào đó, bạn có thể tạo Thực thể MediaActionFeed bao gồm trường bắt buộc DataFeedElementId. Mã này phải là duy nhất và phải khớp với mã trong nguồn cấp dữ liệu Hành động đa phương tiện vì mã này giúp xác định nội dung nguồn cấp dữ liệu đã nhập và thực hiện tra cứu nội dung đa phương tiện.
val id = "dataFeedEleemntId"
MovieEntity
Sau đây là ví dụ về cách tạo MovieEntity
có tất cả các trường bắt buộc:
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()
Bạn có thể cung cấp dữ liệu bổ sung như thể loại, mức phân loại nội dung, ngày phát hành, lý do đề xuất và khoảng thời gian có sẵn. Google TV có thể sử dụng những dữ liệu này cho mục đích hiển thị hoặc lọc nâng cao.
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
Sau đây là ví dụ về cách tạo TvShowEntity
có tất cả các trường bắt buộc:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.build();
Bạn có thể cung cấp thêm dữ liệu như thể loại, điểm xếp hạng nội dung, lý do đề xuất, giá ưu đãi, số lượng phần hoặc khoảng thời gian phát sóng. Google TV có thể sử dụng những dữ liệu này để hiển thị hoặc lọc nội dung hiệu quả hơn.
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
Sau đây là ví dụ về cách tạo MediaActionFeedEntity
có tất cả các trường bắt buộc:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.build()
Bạn có thể cung cấp thêm dữ liệu như nội dung mô tả, lý do đề xuất và khoảng thời gian hiển thị. Google TV có thể sử dụng những dữ liệu này cho mục đích hiển thị nâng cao hoặc lọc.
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setName("Movie name or TV Show name")
.setDescription("A sentence describing an entity")
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addPosterImages(images)
.build()
Bằng cách triển khai các bước này, nhà phát triển có thể tích hợp thành công nội dung đề xuất video vào Google TV, giúp người dùng khám phá và tương tác nhiều hơn, đồng thời mang đến trải nghiệm xem nhất quán và được cá nhân hoá cho người dùng trên tất cả thiết bị của họ.