באינטראקציה עם טלוויזיות, המשתמשים בדרך כלל מעדיפים לתת קלט מינימלי לפני הצפייה תוכן. תרחיש אידיאלי למשתמשים רבים בטלוויזיה הוא: לשבת, להפעיל ולצפות. השלבים הכי מעטים כדי להביא משתמשים לתוכן שהם אוהבים הוא בדרך כלל הנתיב שהם מעדיפים.
הערה: מומלץ להשתמש בממשקי ה-API שמתוארים כאן ליצירת המלצות באפליקציות שפועלות בגרסאות Android עד גרסה 7.1 (רמת API 25) בלבד, כולל Android 7.1. לספק המלצות לאפליקציות שפועלות בגרסת Android 8.0 (רמת API 26) ואילך, האפליקציה חייבת להשתמש בהן ערוצי המלצות.
ה-framework של Android מספק שורת המלצות כדי לעזור באינטראקציה מינימלית של קלט במסך הבית. המלצות על תוכן מופיעות בשורה הראשונה במסך הבית של הטלוויזיה אחרי בפעם הראשונה במכשיר. המלצות מקטלוג התוכן של האפליקציה יכולות לעזור להחזיר משתמשים לאפליקציה.
במדריך הזה מוסבר איך ליצור המלצות ולספק אותן ל-framework של Android כדי שמשתמשים יוכלו לגלות את תוכן האפליקציה שלך וליהנות ממנו בקלות. מידע נוסף על הטמעה לדוגמה ב ה אפליקציה לדוגמה של Leanback הקצר הזה. התשובות שלך יעזרו לנו להשתפר.
שיטות מומלצות לעבודה עם המלצות
ההמלצות עוזרות למשתמשים למצוא במהירות את התוכן והאפליקציות שהם אוהבים. בתהליך יצירה איכותיות ורלוונטיות למשתמשים, הן גורם חשוב ביצירת חוויית משתמש מעולה עם אפליקציית הטלוויזיה שלכם. לכן, צריך לשקול בזהירות המלצות שאתם מציגים למשתמש ומנהלים אותן מקרוב.
סוגים של המלצות
כשיוצרים המלצות, צריך לקשר את המשתמשים לפעילויות צפייה שלא הושלמו, או להציע פעילויות שכוללות גם תוכן קשור. הנה כמה סוגים ספציפיים של המלצות שכדאי לשקול:
- המלצות של תוכן המשך לפרק הבא כדי שהמשתמשים יוכלו להמשיך כשצופים בסדרה. לחלופין, אפשר להשתמש בהמלצות המשך לסרטים, לתוכניות טלוויזיה או לפודקאסטים מושהים כדי שהמשתמשים יוכלו לחזור ולצפות בתוכן מושהה בכמה לחיצות בלבד.
- המלצות לתוכן חדש, כמו פרק חדש בהפעלה ראשונה, אם המשתמשים סיימה לצפות בסדרה אחרת. בנוסף, אם האפליקציה מאפשרת למשתמשים להירשם כמנויים ל סרטונים, לעקוב אחריהם או לעקוב אחריהם להשתמש בהמלצות חדשות לתוכן עבור פריטים שלא נצפו ברשימת התוכן במעקב.
- המלצות של תוכן קשור על סמך המשתמשים בהתנהגות הצפייה ההיסטורית.
אפשר לקרוא מידע נוסף על עיצוב כרטיסי המלצות כך שיתנו את חוויית המשתמש הטובה ביותר. שורת המלצה במפרט העיצוב של Android TV.
רענון ההמלצות
כשמרעננים את ההמלצות, אין להסיר אותן ולפרסם אותן מחדש, כי הפעולה הזו גורמת ההמלצות שמופיעות בסוף השורה של ההמלצות. אחרי שפריט תוכן, כמו סרט, הופעל, להסיר אותו מההמלצות.
התאמה אישית של המלצות
אפשר להתאים אישית את כרטיסי ההמלצות כדי להעביר את פרטי המיתוג באמצעות הגדרת ממשק משתמש רכיבים כמו תמונת הרקע ותמונת הרקע של הכרטיס, הצבע, סמל האפליקציה, הכותרת וכותרת המשנה. מידע נוסף זמין במאמר הבא: שורת המלצה במפרט העיצוב של Android TV.
המלצות לקבוצות
אפשר לקבץ המלצות לפי מקור ההמלצות. לדוגמה, האפליקציה שלך יכול לספק שתי קבוצות של המלצות: המלצות לתוכן שהמשתמש רשום אליו, והמלצות לתוכן חדש ופופולרי שאולי המשתמש לא מודע לו.
המערכת מדרגת ומסדרת את ההמלצות לכל קבוצה בנפרד בזמן יצירה או עדכון את שורת ההמלצה. על ידי מתן מידע קבוצתי עבור ההמלצות שלך, אתה יכול לוודא שההמלצות שלכם לא מסודרות לפי המלצות לא קשורות.
כדאי להשתמש
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 ... > <application ... > ... <service android:name="com.example.android.tvleanback.UpdateRecommendationsService" android:enabled="true" /> </application> </manifest>
יצירת המלצות
אחרי ששירות ההמלצות יתחיל לפעול, המערכת תצטרך ליצור המלצות ולהעביר אותן אל
המסגרת של Android. ה-framework מקבל את ההמלצות כ-Notification
אובייקטים שמשתמשים בתבנית ספציפית ומסומנים באמצעות מאפיין ספציפי
בקטגוריה שלכם.
הגדרת הערכים
כדי להגדיר את הערכים של רכיבי ממשק המשתמש בכרטיס ההמלצה, יוצרים מחלקה של builder לפי תבנית ה-builder שמתוארת בהמשך. קודם כול מגדירים את הערכים של כרטיס ההמלצות רכיבים.
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; } ...
יצירת ההתראה
אחרי שמגדירים את הערכים, יוצרים את ההתראה ומקצה את הערכים מה-builder.
את הכיתה, ולהתקשר אל 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
חייבת לפעול אחרי ההתחלה
מכשיר הטלוויזיה שבו היא מותקנת. כדי לעשות זאת, צריך לרשום את הכיתה הזו באפליקציה
מניפסט עם מסנן Intent שמזהה את השלמת תהליך ההפעלה של המכשיר.
הקוד לדוגמה הבא מדגים איך להוסיף את ההגדרה הזו למניפסט:
<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);