Engage SDK cho tính năng đề xuất video

book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml

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 được đề xuất của họ, sử dụng Engage SDK để điền dữ liệu cho các 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.

Đề 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à có thể có tối đa 7 cụm đề xuất cho mỗi yêu cầu.

Chuẩn bị trước

Hoàn thành hướng dẫn Công việc chuẩn bị trong hướng dẫn Bắt đầu sử dụng.

  1. Thực hiện việc xuất bản trên một dịch vụ trên nền trước.
  2. Xuất bản 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 điều kiện sau:
    • 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 xuất bản cụm đề xuất. Sử dụng phương thức publishRecommendationClusters để xuất bản một đối tượng đề xuất.

Đảm bảo bạn khởi động ứng dụng và kiểm tra xem dịch vụ có hoạt động hay không như mô tả trong Hướng dẫn bắt đầu.

client.publishRecommendationClusters(recommendationRequest)

Thao tác chèn và cập nhật cụm đề xuất

Cụm là nhóm logic của các thực thể. Các ví dụ về mã sau đây giải thích cách tạo các 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 xuất bản cũng như chèn tất cả các cụm.

RecommendationClusterType xác định cách hiển thị cụm.

// 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()

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 vẫn giữ nguyên.

Đồ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ó sẵn trên các thiết bị của họ (chẳng hạn 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.

Ứng dụng đa phương tiện phải cung cấp một 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 lựa chọn ưu tiên của người dùng một lần rồi áp dụng trong publishRecommendations Request 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 rằng ứng dụng có được sự đồng ý của người dùng và cho phép 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 khi hết 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ề hoạt động khám phá video cho hồ sơ tài khoản hoặc cho toàn bộ tài khoản.

Liệt kê DeleteReason xác định lý do xoá dữ liệu. Đoạn mã sau đây sẽ xoá các đề xuất khi người dùng đă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. Các thực thể sau được hỗ trợ cho Cụm đề xuất:

  1. MediaActionFeedEntity
  2. MovieEntity
  3. TvShowEntity
  4. LiveTvChannelEntity
  5. LiveTvProgramEntity

Cung cấp nội dung mô tả

Cung cấp nội dung mô tả ngắ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 lên thực thể, cung cấp cho họ thông tin chi tiết bổ sung.

URI phát lại dành riêng cho từng 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 phù 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 giống nhau cho tất cả các nền tảng, hãy lặp lại URI đó cho từng 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 Không gian giải trí của Google. Hình ảnh có chiều cao dưới 200 pixel có thể không xuất hiện.

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 (không bắt buộc). Google TV có thể dùng lý do này để giải thích cho người dùng biết tại sao nên đề xuất một bộ phim hoặc chương trình truyền hình cụ thể.

//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()

Khoảng thời gian hiển thị

Nếu một thực thể chỉ được cung cấp trong thời gian có hạn, hãy đặt thời gian hết hạn tuỳ 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, bạn chỉ nên đặ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ó thể đặt lịch hẹ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 về nội dung nghe nhìn với Google TV, thì 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 mà có thể tạo một MediaActionFeedEntity bao gồm trường bắt buộc DataFeedElementId. Mã nhận dạng này phải là duy nhất và phải khớp với mã nhận dạng trong Nguồn cấp dữ liệu hành động trên nội dung nghe nhìn vì mã nhận dạng này giúp xác định nội dung nguồn cấp dữ liệu đã được nhập và thực hiện các lượt tìm kiếm nội dung nghe nhìn.

val id = "dataFeedElementId"

MovieEntity

Sau đây là ví dụ về cách tạo MovieEntity với 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 thêm dữ liệu 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 để hiển thị nâng cao hoặc lọc.

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 với 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, mức phân loại nội dung, lý do đề xuất, giá ưu đãi, số phần hoặc khoảng thời gian có sẵn. Google TV có thể sử dụng những dữ liệu này để hiển thị nâng cao hoặc lọc nội dung.

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 một 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 (không bắt buộc) như nội dung mô tả, lý do đề xuất và khung thời gian hiển thị. Google TV có thể dùng dữ liệu này cho mục đích lọc hoặc hiển thị nâng cao.

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

Đây là một kênh truyền hình trực tiếp. Sau đây là ví dụ về cách tạo LiveTvChannelEntity với tất cả các trường bắt buộc:

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()

Bạn có thể cung cấp thêm dữ liệu, chẳng hạn như mức phân loại nội dung hoặc lý do đề xuất.

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

Đây là thẻ chương trình truyền hình trực tiếp đang phát sóng hoặc dự kiến phát sóng trên một kênh truyền hình trực tiếp. Sau đây là ví dụ về cách tạo LiveTvProgramEntity với tất cả các trường bắt buộc:

val liveTvProgramEntity = LiveTvProgramEntity.Builder()
  // First set the channel information
  .setChannelName("Channel Name")
  .setChannelId("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 Description")
  .addAvailabilityTimeWindow(
      DisplayTimeWindow.Builder()
        .setStartTimestampMillis(1756713600000L)// 2025-09-01T07:30:00+0000
        .setEndTimestampMillis(1756715400000L))// 2025-09-01T08:00:00+0000
  .addPosterImage(programImage)
  .build()

Bạn có thể cung cấp thêm dữ liệu như mức phân loại nội dung, thể loại hoặc lý do đề xuất.

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()