เมื่อโต้ตอบกับทีวี ผู้ใช้มักต้องการรับข้อมูลเพียงเล็กน้อยก่อนรับชม เนื้อหา สถานการณ์ที่เหมาะสำหรับผู้ใช้ทีวีจำนวนมากคือการนั่งลง เปิดต่างๆ และดู ขั้นตอนที่น้อยที่สุด ในการพาผู้ใช้ไปยังเนื้อหาที่ตนชื่นชอบมักจะเป็นเส้นทางที่ผู้ใช้ต้องการ
หมายเหตุ: ใช้ API ที่อธิบายไว้ที่นี่เพื่อให้คำแนะนำ ในแอปที่ทำงานใน Android ถึงและรวมถึง Android 7.1 (API ระดับ 25) เท่านั้น การจัดหา คำแนะนำสำหรับแอปที่ทำงานใน Android 8.0 (API ระดับ 26) ขึ้นไป แอปของคุณต้องใช้ ช่องทางแนะนำ
เฟรมเวิร์ก Android ช่วยให้มีการโต้ตอบในการป้อนข้อมูลขั้นต่ำด้วยการระบุแถวคำแนะนำ บนหน้าจอหลัก การแนะนำเนื้อหาจะปรากฏเป็นแถวแรกของหน้าจอหลักของทีวีหลังจาก การใช้งานอุปกรณ์ครั้งแรก การร่วมให้คำแนะนำจากแคตตาล็อกเนื้อหาของแอปอาจช่วยได้ นำผู้ใช้กลับมาที่แอปของคุณ
คู่มือนี้จะสอนวิธีสร้างคำแนะนำและให้คำแนะนำแก่เฟรมเวิร์ก Android เพื่อให้ผู้ใช้ค้นพบและเพลิดเพลินกับเนื้อหาแอปของคุณได้อย่างง่ายดาย และดูตัวอย่างการติดตั้งใช้งานใน เวลา แอปตัวอย่าง Leanback ที่ใช้เวลาเพียง 2 นาที
แนวทางปฏิบัติแนะนำสำหรับคำแนะนำ
คำแนะนำจะช่วยให้ผู้ใช้พบเนื้อหาและแอปที่ชื่นชอบได้อย่างรวดเร็ว กำลังสร้าง คำแนะนำที่มีคุณภาพสูงและมีความเกี่ยวข้องกับผู้ใช้ คือ ปัจจัยสำคัญในการสร้าง ผู้ใช้ได้รับประสบการณ์ที่ยอดเยี่ยม ด้วยแอปทีวีของคุณ ด้วยเหตุนี้ คุณจึงควรพิจารณาอย่างรอบคอบว่า คำแนะนำต่างๆ ที่คุณนำเสนอแก่ผู้ใช้และจัดการคำแนะนำเหล่านั้นอย่างใกล้ชิด
ประเภทของคำแนะนำ
เมื่อคุณสร้างคำแนะนำ คุณควรลิงก์ผู้ใช้กลับไปยังกิจกรรมการดูที่ไม่สมบูรณ์ หรือ เสนอแนะกิจกรรมที่ขยายไปยังเนื้อหาที่เกี่ยวข้อง ต่อไปนี้เป็นประเภทที่เฉพาะเจาะจงของ คำแนะนำที่คุณควรพิจารณา
- คําแนะนําเนื้อหาต่อสําหรับตอนถัดไปเพื่อให้ผู้ใช้กลับมารับชมต่อ ขณะดูซีรีส์ หรือใช้การแนะนำต่อสำหรับภาพยนตร์ รายการทีวี หรือพอดแคสต์ที่หยุดชั่วคราว เพื่อให้ผู้ใช้กลับไปดูเนื้อหาที่หยุดชั่วคราวได้ในไม่กี่คลิก
- การแนะนำเนื้อหาใหม่ เช่น ตอนใหม่ที่ออกฉายครั้งแรก หากผู้ใช้ ดูซีรีส์อื่นจบแล้ว นอกจากนี้ หากแอปของคุณอนุญาตให้ผู้ใช้สมัครติดตาม หรือติดตาม ให้ใช้การแนะนำเนื้อหาใหม่สำหรับรายการที่ยังไม่ได้ดูในรายการเนื้อหาที่ติดตาม
- การแนะนำเนื้อหาที่เกี่ยวข้องซึ่งอิงตามผู้ใช้ พฤติกรรมการรับชมที่ผ่านมา
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีออกแบบการ์ดคําแนะนําเพื่อประสบการณ์ของผู้ใช้ที่ดีที่สุดได้ที่ แถวคำแนะนำในข้อมูลจำเพาะการออกแบบของ Android TV
รีเฟรชคำแนะนำ
เมื่อคุณรีเฟรชคำแนะนำ อย่าเพียงแค่นำคำแนะนำออกและโพสต์ซ้ำ เพราะการทำเช่นนี้จะ คำแนะนำที่จะปรากฏที่ท้ายแถวคำแนะนำ เมื่อรายการเนื้อหา เช่น ภาพยนตร์, เล่นแล้ว, นำออกจากคำแนะนำ
ปรับแต่งคำแนะนำ
คุณปรับแต่งการ์ดคำแนะนำเพื่อสื่อสารข้อมูลของแบรนด์ได้โดยการตั้งค่าอินเทอร์เฟซผู้ใช้ เช่น พื้นหน้าและภาพพื้นหลัง สี ไอคอนแอป ชื่อ และคำบรรยายของการ์ด ดูข้อมูลเพิ่มเติมได้ที่ แถวคำแนะนำในข้อมูลจำเพาะการออกแบบของ Android TV
คำแนะนำกลุ่ม
คุณจะเลือกจัดกลุ่มคำแนะนำตามแหล่งที่มาของคำแนะนำได้ เช่น แอปของคุณ อาจให้คำแนะนำ 2 กลุ่ม ได้แก่ การแนะนำเนื้อหาที่ผู้ใช้ติดตาม และคำแนะนำเกี่ยวกับเนื้อหามาแรงใหม่ๆ ที่ผู้ใช้อาจยังไม่รู้
ระบบจะจัดอันดับและเรียงลำดับคำแนะนำสำหรับแต่ละกลุ่มแยกกันเมื่อสร้างหรืออัปเดต แถวคำแนะนำ การให้ข้อมูลกลุ่มสำหรับการแนะนำจะช่วยให้คุณมั่นใจได้ว่า เพื่อจัดลำดับวิดีโอให้ต่ำกว่า วิดีโอแนะนำที่ไม่เกี่ยวข้อง
ใช้
NotificationCompat.Builder.setGroup()
เพื่อตั้งค่าสตริงคีย์กลุ่มของคำแนะนำ สำหรับ
เช่น เพื่อทำเครื่องหมายคำแนะนำว่าเป็นของกลุ่มที่มีเนื้อหามาแรงใหม่
คุณอาจโทรหา setGroup("trending")
สร้างบริการคำแนะนำ
ระบบสร้างการแนะนำเนื้อหาโดยใช้การประมวลผลในเบื้องหลัง เพื่อให้แอปพลิเคชันของคุณ ให้คำแนะนำ สร้างบริการที่เพิ่มรายชื่อเป็นระยะๆ จาก แคตตาล็อกของแอปพลิเคชันลงในรายการคำแนะนำของระบบ
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีขยาย IntentService
ไปยัง
สร้างบริการคำแนะนำสำหรับแอปพลิเคชันของคุณ:
Kotlin
class UpdateRecommendationsService : IntentService("RecommendationService") { override protected fun onHandleIntent(intent: Intent) { Log.d(TAG, "Updating recommendation cards") val recommendations = VideoProvider.getMovieList() if (recommendations == null) return var count = 0 try { val builder = RecommendationBuilder() .setContext(applicationContext) .setSmallIcon(R.drawable.videos_by_google_icon) for (entry in recommendations.entrySet()) { for (movie in entry.getValue()) { Log.d(TAG, "Recommendation - " + movie.getTitle()) builder.setBackground(movie.getCardImageUrl()) .setId(count + 1) .setPriority(MAX_RECOMMENDATIONS - count) .setTitle(movie.getTitle()) .setDescription(getString(R.string.popular_header)) .setImage(movie.getCardImageUrl()) .setIntent(buildPendingIntent(movie)) .build() if (++count >= MAX_RECOMMENDATIONS) { break } } if (++count >= MAX_RECOMMENDATIONS) { break } } } catch (e: IOException) { Log.e(TAG, "Unable to update recommendation", e) } } private fun buildPendingIntent(movie: Movie): PendingIntent { val detailsIntent = Intent(this, DetailsActivity::class.java) detailsIntent.putExtra("Movie", movie) val stackBuilder = TaskStackBuilder.create(this) stackBuilder.addParentStack(DetailsActivity::class.java) stackBuilder.addNextIntent(detailsIntent) // Ensure a unique PendingIntents, otherwise all // recommendations end up with the same PendingIntent detailsIntent.setAction(movie.getId().toString()) val intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) return intent } companion object { private val TAG = "UpdateRecommendationsService" private val MAX_RECOMMENDATIONS = 3 } }
Java
public class UpdateRecommendationsService extends IntentService { private static final String TAG = "UpdateRecommendationsService"; private static final int MAX_RECOMMENDATIONS = 3; public UpdateRecommendationsService() { super("RecommendationService"); } @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "Updating recommendation cards"); HashMap<String, List<Movie>> recommendations = VideoProvider.getMovieList(); if (recommendations == null) return; int count = 0; try { RecommendationBuilder builder = new RecommendationBuilder() .setContext(getApplicationContext()) .setSmallIcon(R.drawable.videos_by_google_icon); for (Map.Entry<String, List<Movie>> entry : recommendations.entrySet()) { for (Movie movie : entry.getValue()) { Log.d(TAG, "Recommendation - " + movie.getTitle()); builder.setBackground(movie.getCardImageUrl()) .setId(count + 1) .setPriority(MAX_RECOMMENDATIONS - count) .setTitle(movie.getTitle()) .setDescription(getString(R.string.popular_header)) .setImage(movie.getCardImageUrl()) .setIntent(buildPendingIntent(movie)) .build(); if (++count >= MAX_RECOMMENDATIONS) { break; } } if (++count >= MAX_RECOMMENDATIONS) { break; } } } catch (IOException e) { Log.e(TAG, "Unable to update recommendation", e); } } private PendingIntent buildPendingIntent(Movie movie) { Intent detailsIntent = new Intent(this, DetailsActivity.class); detailsIntent.putExtra("Movie", movie); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addParentStack(DetailsActivity.class); stackBuilder.addNextIntent(detailsIntent); // Ensure a unique PendingIntents, otherwise all // recommendations end up with the same PendingIntent detailsIntent.setAction(Long.toString(movie.getId())); PendingIntent intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); return intent; } }
เพื่อให้ระบบจดจำบริการนี้และเรียกใช้งาน ให้ลงทะเบียนโดยใช้ ไฟล์ Manifest ของแอป ข้อมูลโค้ดต่อไปนี้แสดงวิธีประกาศคลาสนี้เป็นบริการ
<manifest ... > <application ... > ... <service android:name="com.example.android.tvleanback.UpdateRecommendationsService" android:enabled="true" /> </application> </manifest>
คำแนะนำในการสร้าง
เมื่อบริการคำแนะนำเริ่มทำงานแล้ว บริการจะต้องสร้างคำแนะนำและส่งไปยัง
เฟรมเวิร์กของ Android เฟรมเวิร์กได้รับคำแนะนำเป็นออบเจ็กต์ Notification
ซึ่งใช้เทมเพลตที่เจาะจงและทำเครื่องหมายด้วย
หมวดหมู่
การตั้งค่า
หากต้องการกำหนดค่าองค์ประกอบ UI สำหรับการ์ดคำแนะนำ คุณจะต้องสร้างคลาสเครื่องมือสร้างดังต่อไปนี้ รูปแบบของเครื่องมือสร้างที่อธิบายดังนี้ ก่อนอื่นให้กำหนดค่าของการ์ดคำแนะนำ จากองค์ประกอบเหล่านี้
Kotlin
class RecommendationBuilder { ... fun setTitle(title: String): RecommendationBuilder { this.title = title return this } fun setDescription(description: String): RecommendationBuilder { this.description = description return this } fun setImage(uri: String): RecommendationBuilder { imageUri = uri return this } fun setBackground(uri: String): RecommendationBuilder { backgroundUri = uri return this } ...
Java
public class RecommendationBuilder { ... public RecommendationBuilder setTitle(String title) { this.title = title; return this; } public RecommendationBuilder setDescription(String description) { this.description = description; return this; } public RecommendationBuilder setImage(String uri) { imageUri = uri; return this; } public RecommendationBuilder setBackground(String uri) { backgroundUri = uri; return this; } ...
สร้างการแจ้งเตือน
เมื่อกำหนดค่าแล้ว คุณสร้างการแจ้งเตือนโดยกำหนดค่าจากเครื่องมือสร้างได้
ไปยังการแจ้งเตือน และโทรหา NotificationCompat.Builder.build()
และอย่าลืมโทรหา
setLocalOnly()
ดังนั้นการแจ้งเตือนNotificationCompat.BigPictureStyle
จะไม่แสดง
บนอุปกรณ์อื่นๆ
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีสร้างคำแนะนำ
Kotlin
class RecommendationBuilder { ... @Throws(IOException::class) fun build(): Notification { ... val notification = NotificationCompat.BigPictureStyle( NotificationCompat.Builder(context) .setContentTitle(title) .setContentText(description) .setPriority(priority) .setLocalOnly(true) .setOngoing(true) .setColor(context.resources.getColor(R.color.fastlane_background)) .setCategory(Notification.CATEGORY_RECOMMENDATION) .setLargeIcon(image) .setSmallIcon(smallIcon) .setContentIntent(intent) .setExtras(extras)) .build() return notification } }
Java
public class RecommendationBuilder { ... public Notification build() throws IOException { ... Notification notification = new NotificationCompat.BigPictureStyle( new NotificationCompat.Builder(context) .setContentTitle(title) .setContentText(description) .setPriority(priority) .setLocalOnly(true) .setOngoing(true) .setColor(context.getResources().getColor(R.color.fastlane_background)) .setCategory(Notification.CATEGORY_RECOMMENDATION) .setLargeIcon(image) .setSmallIcon(smallIcon) .setContentIntent(intent) .setExtras(extras)) .build(); return notification; } }
เรียกใช้บริการคำแนะนำ
บริการแนะนำของแอปต้องทำงานเป็นระยะๆ เพื่อสร้างรายการปัจจุบัน
วิดีโอแนะนำ หากต้องการเรียกใช้บริการ ให้สร้างชั้นเรียนที่เรียกใช้ตัวจับเวลาและเรียกใช้งาน
อย่างสม่ำเสมอ ตัวอย่างโค้ดต่อไปนี้ขยายคลาส BroadcastReceiver
ให้เริ่มการเรียกใช้บริการคำแนะนำเป็นระยะๆ
ทุกครึ่งชั่วโมง:
Kotlin
class BootupActivity : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Log.d(TAG, "BootupActivity initiated") if (intent.action.endsWith(Intent.ACTION_BOOT_COMPLETED)) { scheduleRecommendationUpdate(context) } } private fun scheduleRecommendationUpdate(context: Context) { Log.d(TAG, "Scheduling recommendations update") val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val recommendationIntent = Intent(context, UpdateRecommendationsService::class.java) val alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0) alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, INITIAL_DELAY, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent ) } companion object { private val TAG = "BootupActivity" private val INITIAL_DELAY:Long = 5000 } }
Java
public class BootupActivity extends BroadcastReceiver { private static final String TAG = "BootupActivity"; private static final long INITIAL_DELAY = 5000; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "BootupActivity initiated"); if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) { scheduleRecommendationUpdate(context); } } private void scheduleRecommendationUpdate(Context context) { Log.d(TAG, "Scheduling recommendations update"); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent recommendationIntent = new Intent(context, UpdateRecommendationsService.class); PendingIntent alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0); alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, INITIAL_DELAY, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent); } }
การใช้งานคลาส BroadcastReceiver
นี้ต้องทำงานหลังจากเริ่มต้น
จากอุปกรณ์ทีวีที่ติดตั้งอยู่ หากต้องการดำเนินการนี้ ให้ลงทะเบียนชั้นเรียนนี้ในแอปของคุณ
ไฟล์ Manifest ที่มีตัวกรอง Intent ที่รอฟังการดำเนินการเปิดเครื่องอุปกรณ์จนเสร็จสมบูรณ์
โค้ดตัวอย่างต่อไปนี้แสดงวิธีเพิ่มการกำหนดค่านี้ลงในไฟล์ Manifest
<manifest ... > <application ... > <receiver android:name="com.example.android.tvleanback.BootupActivity" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> </application> </manifest>
สำคัญ: แอปของคุณต้องได้รับการแจ้งเตือนเมื่อเปิดเครื่องเรียบร้อยแล้ว
ขอสิทธิ์ RECEIVE_BOOT_COMPLETED
ดูข้อมูลเพิ่มเติมได้ที่ ACTION_BOOT_COMPLETED
ในชั้นเรียนบริการคำแนะนำ onHandleIntent()
ให้โพสต์คำแนะนำไปยังผู้จัดการ ดังนี้
Kotlin
val notification = notificationBuilder.build() notificationManager.notify(id, notification)
Java
Notification notification = notificationBuilder.build(); notificationManager.notify(id, notification);