คู่มือนี้มีวิธีการสำหรับนักพัฒนาแอปในการผสานรวมเนื้อหาวิดีโอที่แนะนำโดยใช้ Engage SDK เพื่อแสดงประสบการณ์การแนะนำในแพลตฟอร์มต่างๆ ของ Google เช่น ทีวี อุปกรณ์เคลื่อนที่ และแท็บเล็ต
คำแนะนำจะใช้คลัสเตอร์คำแนะนำเพื่อแสดงภาพยนตร์และรายการทีวีจากแอปหลายแอปในการจัดกลุ่ม UI เดียว พาร์ทเนอร์นักพัฒนาแอปแต่ละรายสามารถ ออกอากาศเอนทิตีได้สูงสุด25 รายการในคลัสเตอร์คำแนะนำแต่ละรายการ และมีคลัสเตอร์คำแนะนำได้สูงสุด7 รายการต่อคำขอ
สิ่งที่ต้องเตรียมก่อนดำเนินการ
ก่อนเริ่มต้น ให้ทำตามขั้นตอนต่อไปนี้ 1. ตรวจสอบว่าแอปกำหนดเป้าหมายเป็น API ระดับ 19 ขึ้นไปสำหรับการผสานรวมนี้
เพิ่มไลบรารี
com.google.android.engageลงในแอปมี SDK แยกต่างหากให้ใช้ในการผสานรวม โดย SDK หนึ่งสำหรับแอปบนมือถือ และอีก SDK หนึ่งสำหรับแอป TV
สำหรับอุปกรณ์เคลื่อนที่
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สำหรับ 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 เพื่อระบุข้อมูลต่อไปนี้
- รหัสบัญชี: ตัวระบุที่ไม่ซ้ำกันซึ่งแสดงถึงบัญชีของผู้ใช้ภายในแอปพลิเคชันของคุณ ซึ่งอาจเป็นรหัสบัญชีจริงหรือเวอร์ชันที่ปรับให้ยากต่อการอ่าน (Obfuscate) อย่างเหมาะสมก็ได้
- รหัสโปรไฟล์ (ไม่บังคับ): หากแอปพลิเคชันรองรับหลายโปรไฟล์ภายในบัญชีเดียว ให้ระบุตัวระบุที่ไม่ซ้ำกันสำหรับโปรไฟล์ผู้ใช้ที่เฉพาะเจาะจง
- Locale(ไม่บังคับ): คุณระบุภาษาที่ผู้ใช้ต้องการได้
ฟิลด์นี้มีประโยชน์หากคุณส่ง
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 Flag ควบคุมว่าระบบจะแชร์ข้อมูลคลัสเตอร์คำแนะนำของผู้ใช้กับ Google TV และพร้อมใช้งานในอุปกรณ์ต่างๆ เช่น ทีวี โทรศัพท์ แท็บเล็ต หรือไม่ ต้องตั้งค่าเป็น "จริง" เพื่อให้คำแนะนำทำงานได้
ขอความยินยอม
แอปพลิเคชันสื่อต้องมีการตั้งค่าที่ชัดเจนเพื่อเปิดหรือปิดใช้การซิงค์ข้ามอุปกรณ์ อธิบายสิทธิประโยชน์ให้ผู้ใช้ทราบและจัดเก็บค่ากำหนดของผู้ใช้เพียงครั้งเดียว แล้วนำไปใช้ในpublishRecommendationsคำขอตามนั้น หากต้องการใช้ฟีเจอร์ข้ามอุปกรณ์ให้เกิดประโยชน์สูงสุด โปรดยืนยันว่าแอปได้รับความยินยอมจากผู้ใช้และเปิดใช้ SyncAcrossDevices เป็น true
ลบข้อมูลการค้นพบวิดีโอ
หากต้องการลบข้อมูลของผู้ใช้จากเซิร์ฟเวอร์ Google TV ด้วยตนเองก่อนระยะเวลาเก็บรักษามาตรฐาน 60 วัน ให้ใช้เมธอด 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 ได้กำหนดเอนทิตีต่างๆ เพื่อแสดงรายการแต่ละประเภท ระบบรองรับเอนทิตีต่อไปนี้สำหรับคลัสเตอร์คำแนะนำ
MediaActionFeedEntityMovieEntityTvShowEntityLiveTvChannelEntityLiveTvProgramEntity
คำอธิบาย
ระบุคำอธิบายสั้นๆ สำหรับแต่ละเอนทิตี คำอธิบายนี้จะแสดงเมื่อผู้ใช้วางเมาส์เหนือเอนทิตี เพื่อให้ผู้ใช้ทราบรายละเอียดเพิ่มเติม
URI การเล่นเฉพาะแพลตฟอร์ม
สร้าง URI การเล่นสำหรับแต่ละแพลตฟอร์มที่รองรับ ได้แก่ Android TV, Android หรือ iOS ซึ่งจะช่วยให้ระบบเลือก 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 และขนาดพิกเซล (ความสูงและความกว้าง) โปรดกำหนดเป้าหมายรูปแบบของอุปกรณ์หลายๆ แบบ โดยจัดให้มีภาพโปสเตอร์หลายภาพ และตรวจสอบว่าภาพทั้งหมดมีสัดส่วนการแสดงผล 16:9 และมีความสูงอย่างน้อย 200 พิกเซล เพื่อให้แสดงผลเอนทิตี "รายการแนะนำ" ได้อย่างถูกต้องโดยเฉพาะภายใน Entertainment Space ของ Google ทั้งนี้ระบบอาจไม่แสดงรูปภาพที่มีความสูงน้อยกว่า 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 สามารถใช้เพื่อสร้างเหตุผลในการแนะนำภาพยนตร์หรือรายการทีวีที่เฉพาะเจาะจงแก่ ผู้ใช้
//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 แล้ว คุณไม่จำเป็นต้องสร้างเอนทิตีแยกต่างหากสำหรับภาพยนตร์หรือรายการทีวี แต่สามารถ สร้างเอนทิตี MediaActionFeed ซึ่งมี ฟิลด์ DataFeedElementId ที่จำเป็นแทนได้ รหัสนี้ต้องไม่ซ้ำกันและต้องตรงกับรหัสในฟีดการดำเนินการกับสื่อ เนื่องจากจะช่วยระบุเนื้อหาฟีดที่ส่งผ่านข้อมูลแล้วและ ทำการค้นหาเนื้อหาสื่อ
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()
การทำตามขั้นตอนเหล่านี้จะช่วยให้นักพัฒนาแอปผสานรวมคำแนะนำเนื้อหาวิดีโอเข้ากับ Google TV ได้สำเร็จ ซึ่งจะช่วยเพิ่มการค้นพบและการมีส่วนร่วมของผู้ใช้ รวมถึงมอบประสบการณ์การรับชมที่สอดคล้องกันและปรับเปลี่ยนในแบบของคุณสำหรับผู้ใช้ในอุปกรณ์ทั้งหมด