동영상 맞춤 동영상을 위한 Engage SDK

이 가이드에는 개발자가 Engage SDK를 사용하여 맞춤 동영상 콘텐츠를 통합하여 TV, 모바일, 태블릿과 같은 Google 표시 경로 전반에서 맞춤 동영상 환경을 채우는 방법에 관한 안내가 포함되어 있습니다.

맞춤 콘텐츠는 맞춤 콘텐츠 클러스터를 활용하여 여러 앱의 영화와 TV 프로그램을 하나의 UI 그룹으로 표시합니다. 각 개발자 파트너는 각 맞춤 콘텐츠 클러스터에서 최대 25개의 항목을 브로드캐스트할 수 있으며 요청당 맞춤 콘텐츠 클러스터는 최대 7개까지 있을 수 있습니다.

사전 작업

시작하기 전에 다음 단계를 완료하세요. 1. 이 통합을 위해 앱이 API 수준 19 이상을 타겟팅하는지 확인합니다.

  1. com.google.android.engage 라이브러리를 앱에 추가합니다.

    통합에 사용할 수 있는 SDK는 모바일 앱용 SDK와 TV 앱용 SDK로 각각 다릅니다.

    모바일용

    
      dependencies {
        implementation 'com.google.android.engage:engage-core:1.5.5
      }
    

    TV의 경우

    
      dependencies {
        implementation 'com.google.android.engage:engage-tv:1.0.2
      }
    
  2. AndroidManifest.xml 파일에서 Engage 서비스 환경을 프로덕션으로 설정합니다.

    모바일 APK

    
    <meta-data
          android:name="com.google.android.engage.service.ENV"
          android:value="PRODUCTION">
    </meta-data>
    

    TV용 APK

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. 포그라운드 서비스에서 게시를 실행합니다.

  4. 다음 중 하나에 의해 트리거되어 하루에 한 번 이하로 맞춤 콘텐츠 데이터를 게시합니다.

    1. 사용자가 하루 중 처음 로그인한 시간입니다. (또는)
    2. 사용자가 애플리케이션과 상호작용을 시작할 때

통합

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

계정 프로필 만들기

Google TV에서 맞춤설정된 환경을 사용하려면 계정 및 프로필 정보를 제공하세요. AccountProfile를 사용하여 다음을 제공합니다.

  1. 계정 ID: 애플리케이션 내에서 사용자의 계정을 나타내는 고유 식별자입니다. 실제 계정 ID이거나 적절하게 난독화된 버전일 수 있습니다.
  2. 프로필 ID (선택사항): 애플리케이션이 단일 계정 내에서 여러 프로필을 지원하는 경우 특정 사용자 프로필의 고유 식별자를 제공합니다.
  3. 언어(선택사항): 원하는 경우 사용자의 선호 언어를 제공할 수 있습니다. 이 필드는 RecommendationRequest에서 MediaActionFeedEntity를 전송하는 경우에 유용합니다.
// 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와 공유되고 TV, 휴대전화, 태블릿과 같은 기기에서 사용할 수 있는지 여부를 제어합니다. 맞춤 콘텐츠가 작동하려면 이 값을 true로 설정해야 합니다.

미디어 애플리케이션은 교차 기기 동기화를 사용 설정하거나 사용 중지하는 명확한 설정을 제공해야 합니다. 사용자에게 이점을 설명하고 사용자의 환경설정을 한 번 저장한 후 publishRecommendations 요청에 적용합니다. 교차 기기 기능을 최대한 활용하려면 앱이 사용자 동의를 얻고 SyncAcrossDevicestrue로 사용 설정했는지 확인합니다.

동영상 탐색 데이터 삭제

표준 60일 보관 기간이 지나기 전에 Google TV 서버에서 사용자의 데이터를 수동으로 삭제하려면 client.deleteClusters() 메서드를 사용하세요. 서비스는 요청을 수신하면 계정 프로필 또는 전체 계정의 기존 동영상 검색 데이터를 모두 삭제합니다.

DeleteReason enum은 데이터 삭제 이유를 정의합니다. 다음 코드는 로그아웃 시 맞춤 콘텐츠를 삭제합니다.

// 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는 각 항목 유형을 나타내는 여러 항목을 정의했습니다. 맞춤 콘텐츠 클러스터에서 지원되는 항목은 다음과 같습니다.

  1. MediaActionFeedEntity
  2. MovieEntity
  3. TvShowEntity

설명

각 항목에 대한 간단한 설명을 제공합니다. 이 설명은 사용자가 항목 위로 마우스를 가져가면 표시되어 추가 세부정보를 제공합니다.

플랫폼별 재생 URI

지원되는 각 플랫폼(Android TV, Android, 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 및 픽셀 크기 (높이 및 너비)가 필요합니다. 여러 포스터 이미지를 제공하여 다양한 폼 팩터를 타겟팅하되, 특히 Google의 엔터테인먼트 스페이스 내에서 '추천' 항목을 올바르게 표시하려면 모든 이미지가 16:9 가로세로 비율과 최소 200픽셀의 높이를 유지하는지 확인하세요. 높이가 200픽셀 미만인 이미지는 표시되지 않을 수 있습니다.

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)

추천 이유

원하는 경우 Google TV에서 사용자에게 특정 영화 또는 TV 프로그램을 추천하는 이유를 구성하는 데 사용할 수 있는 추천 이유를 제공합니다.

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

표시 기간

항목을 한시적으로만 사용할 수 있는 경우 맞춤 만료 시간을 설정합니다. 명시적인 만료 시간이 없으면 항목은 60일 후에 자동으로 만료되고 삭제됩니다. 따라서 항목이 더 빨리 만료되어야 하는 경우에만 만료 시간을 설정하세요. 이러한 사용 가능 시간대를 여러 개 지정합니다.

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

미디어 카탈로그 또는 미디어 작업 피드를 Google TV와 통합한 경우 영화 또는 TV 프로그램에 대해 별도의 항목을 만들 필요가 없으며 대신 필수 입력란인 DataFeedElementId가 포함된 MediaActionFeed 항목을 만들 수 있습니다. 이 ID는 고유해야 하며 미디어 작업 피드의 ID와 일치해야 합니다. 처리된 피드 콘텐츠를 식별하고 미디어 콘텐츠 조회를 실행하는 데 도움이 되기 때문입니다.

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

개발자는 이 단계를 구현하여 동영상 콘텐츠 추천을 Google TV에 통합하고 사용자 검색 및 참여도를 높이며 모든 기기에서 사용자에게 일관되고 맞춤화된 시청 환경을 제공할 수 있습니다.