Empfehlungen in Android N und früheren Versionen

Bei der Interaktion mit Fernsehern möchten Nutzer in der Regel so wenig wie möglich eingeben, bevor sie sich Inhalte ansehen. Das ideale Szenario für viele TV-Nutzer ist: hinsetzen, einschalten und ansehen. Nutzer bevorzugen in der Regel den Weg mit den wenigsten Schritten , um zu den Inhalten zu gelangen, die ihnen gefallen.

Hinweis:Verwenden Sie die hier beschriebenen APIs nur für Empfehlungen in Apps, die unter Android-Versionen bis einschließlich Android 7.1 (API-Level 25) ausgeführt werden. Wenn Sie Empfehlungen für Apps bereitstellen möchten, die unter Android 8.0 (API-Level 26) und höher ausgeführt werden, muss Ihre App Empfehlungskanäle verwenden.

Das Android-Framework unterstützt die Interaktion mit minimaler Eingabe, indem es eine Empfehlungszeile auf dem Startbildschirm bereitstellt. Contentempfehlungen werden nach der ersten Verwendung des Geräts als erste Zeile des TV-Startbildschirms angezeigt. Wenn Sie Empfehlungen aus dem Contentkatalog Ihrer App beitragen, können Sie Nutzer dazu anregen, Ihre App wieder zu verwenden.

Beispiel für die Empfehlungszeile auf dem Android TV-Startbildschirm
Abbildung 1 Beispiel für die Empfehlungszeile

In diesem Leitfaden erfahren Sie, wie Sie Empfehlungen erstellen und dem Android-Framework zur Verfügung stellen, damit Nutzer Ihre App-Inhalte entdecken und genießen können. Siehe auch die Beispielimplementierung in der Leanback-Beispiel-App .

Best Practices für Empfehlungen

Empfehlungen helfen Nutzern, schnell die Inhalte und Apps zu finden, die ihnen gefallen. Hochwertige und relevante Empfehlungen für Nutzer sind ein wichtiger Faktor für eine gute Nutzererfahrung mit Ihrer TV-App. Aus diesem Grund sollten Sie sorgfältig überlegen, welche Empfehlungen Sie dem Nutzer präsentieren, und diese genau verwalten.

Arten von Empfehlungen

Wenn Sie Empfehlungen erstellen, sollten Sie Nutzer zu unvollständigen Wiedergabeaktivitäten zurückleiten oder Aktivitäten vorschlagen, die diese auf verwandte Inhalte ausweiten. Hier sind einige spezifische Arten von Empfehlungen, die Sie in Betracht ziehen sollten:

  • Empfehlungen für Fortsetzungsinhalte für die nächste Folge, damit Nutzer sich eine Serie weiter ansehen können. Sie können auch Empfehlungen für pausierte Filme, Fernsehsendungen oder Podcasts verwenden, damit Nutzer mit nur wenigen Klicks zu den pausierten Inhalten zurückkehren können.
  • Empfehlungen für neue Inhalte, z. B. für eine neue Folge einer Serie, wenn der Nutzer eine andere Serie zu Ende angesehen hat. Wenn Nutzer in Ihrer App Inhalte abonnieren, folgen oder verfolgen können, verwenden Sie Empfehlungen für neue Inhalte für nicht angesehene Elemente in der Liste der verfolgten Inhalte.
  • Empfehlungen für verwandte Inhalte basierend auf dem bisherigen Wiedergabeverhalten der Nutzer.

Weitere Informationen zum Entwerfen von Empfehlungskarten für die bestmögliche Nutzererfahrung finden Sie in der Android TV Design Specification unter Recommendation Row.

Empfehlungen aktualisieren

Wenn Sie Empfehlungen aktualisieren, entfernen Sie sie nicht einfach und posten Sie sie neu, da sie sonst am Ende der Empfehlungszeile angezeigt werden. Sobald ein Inhalt wie ein Film wiedergegeben wurde, entfernen Sie ihn aus den Empfehlungen.

Empfehlungen anpassen

Sie können Empfehlungskarten anpassen, um Branding-Informationen zu vermitteln, indem Sie Elemente der Benutzeroberfläche wie das Vordergrund- und Hintergrundbild, die Farbe, das App-Symbol, den Titel und den Untertitel der Karte festlegen. Weitere Informationen finden Sie in der Android TV Design Specification unter Recommendation Row.

Gruppenempfehlungen

Optional können Sie Empfehlungen nach Empfehlungsquelle gruppieren. Ihre App kann beispielsweise zwei Gruppen von Empfehlungen bereitstellen: Empfehlungen für Inhalte, die der Nutzer abonniert hat, und Empfehlungen für neue Trendinhalte, die der Nutzer möglicherweise noch nicht kennt.

Das System bewertet und sortiert Empfehlungen für jede Gruppe separat, wenn die Empfehlungszeile erstellt oder aktualisiert wird. Wenn Sie Gruppeninformationen für Ihre Empfehlungen angeben, können Sie dafür sorgen, dass Ihre Empfehlungen nicht unter nicht verwandten Empfehlungen sortiert werden.

Verwenden Sie NotificationCompat.Builder.setGroup(), um den Gruppenschlüsselstring einer Empfehlung festzulegen. Wenn Sie beispielsweise eine Empfehlung als zu einer Gruppe mit neuen Trendinhalten gehörend kennzeichnen möchten, können Sie setGroup("trending") aufrufen.

Empfehlungsdienst erstellen

Contentempfehlungen werden im Hintergrund erstellt. Damit Ihre Anwendung zu Empfehlungen beitragen kann, erstellen Sie einen Dienst, der der Empfehlungsliste des Systems regelmäßig Einträge aus dem Katalog Ihrer App hinzufügt.

Das folgende Codebeispiel zeigt, wie Sie IntentService erweitern, um einen Empfehlungsdienst für Ihre Anwendung zu erstellen:

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;
    }
}

Damit dieser Dienst vom System erkannt und ausgeführt werden kann, registrieren Sie ihn mit Ihrem App-Manifest. Das folgende Code-Snippet zeigt, wie Sie diese Klasse als Dienst deklarieren:

<manifest ... >
  <application ... >
    ...

    <service
            android:name="com.example.android.tvleanback.UpdateRecommendationsService"
            android:enabled="true" />
  </application>
</manifest>

Empfehlungen erstellen

Sobald Ihr Empfehlungsdienst ausgeführt wird, muss er Empfehlungen erstellen und an das Android-Framework übergeben. Das Framework empfängt die Empfehlungen als Notification Objekte, die eine bestimmte Vorlage verwenden und mit einer bestimmten Kategorie gekennzeichnet sind.

Werte festlegen

Um die Werte der UI-Elemente für die Empfehlungskarte festzulegen, erstellen Sie eine Builder-Klasse, die dem folgenden Builder-Muster entspricht. Legen Sie zuerst die Werte der Empfehlungskartenelemente fest.

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;
        }
...

Benachrichtigung erstellen

Nachdem Sie die Werte festgelegt haben, erstellen Sie die Benachrichtigung, weisen ihr die Werte aus der Builder Klasse zu und rufen NotificationCompat.Builder.build() auf.

Rufen Sie außerdem setLocalOnly() auf, damit die NotificationCompat.BigPictureStyle Benachrichtigung nicht auf anderen Geräten angezeigt wird.

Das folgende Codebeispiel zeigt, wie Sie eine Empfehlung erstellen.

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;
    }
}

Empfehlungsdienst ausführen

Der Empfehlungsdienst Ihrer App muss regelmäßig ausgeführt werden, um aktuelle Empfehlungen zu erstellen. Um Ihren Dienst auszuführen, erstellen Sie eine Klasse, die einen Timer ausführt und ihn in regelmäßigen Abständen aufruft. Das folgende Codebeispiel erweitert die Klasse BroadcastReceiver, um alle 30 Minuten eine regelmäßige Ausführung eines Empfehlungsdienstes zu starten:

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);
    }
}

Diese Implementierung der Klasse BroadcastReceiver muss nach dem Start des TV-Geräts ausgeführt werden, auf dem sie installiert ist. Registrieren Sie diese Klasse dazu in Ihrem App Manifest mit einem Intent-Filter, der auf den Abschluss des Geräte-Bootprozesses wartet. Das folgende Beispielcode zeigt, wie Sie diese Konfiguration dem Manifest hinzufügen:

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

Wichtig: Wenn Sie eine Benachrichtigung über den abgeschlossenen Bootprozess erhalten möchten, muss Ihre App die RECEIVE_BOOT_COMPLETED Berechtigung anfordern. Weitere Informationen finden Sie unter ACTION_BOOT_COMPLETED.

Posten Sie die Empfehlung in der Methode onHandleIntent() Ihrer Empfehlungsdienstklasse wie folgt an den Manager:

Kotlin

val notification = notificationBuilder.build()
notificationManager.notify(id, notification)

Java

Notification notification = notificationBuilder.build();
notificationManager.notify(id, notification);