Android TV utilise l'interface de recherche d'Android. pour récupérer les données de contenu des applications installées et fournir des résultats de recherche à l'utilisateur. Votre application des données de contenu peuvent être incluses dans ces résultats pour permettre à l'utilisateur d'accéder instantanément au contenu votre application.
Votre appli doit fournir à Android TV les champs de données à partir desquels Android TV peut générer des suggestions de recherche
à mesure que l'utilisateur saisit des caractères dans la boîte de dialogue de recherche. Pour ce faire, votre application doit implémenter
Fournisseur de contenu qui diffuse
les suggestions ainsi qu'un
searchable.xml
, qui décrit le contenu
sur le fournisseur d'accès et d'autres informations essentielles pour Android TV. Vous avez également besoin d'une activité qui gère
qui se déclenche lorsque l'utilisateur sélectionne un résultat de recherche suggéré. Pour
pour en savoir plus, consultez la section Ajouter
les suggestions de recherche personnalisées. Ce guide aborde les principaux points spécifiques aux applications Android TV.
Avant de lire ce guide, assurez-vous de bien maîtriser les concepts expliqués dans le Guide de l'API Search Consultez également Ajouter une fonctionnalité de recherche.
L'exemple de code présenté dans ce guide provient du <ph type="x-smartling-placeholder"></ph> Exemple d'application Leanback pour en savoir plus.
Identifier les colonnes
Le SearchManager
décrit les champs de données attendus en les représentant comme
colonnes d'une base
de données locale. Quel que soit le format de vos données, vous devez mapper vos champs de données avec
ces colonnes, généralement dans la classe qui
accède à vos données de contenu. Pour en savoir plus sur la création
une classe qui mappe vos données existantes aux champs obligatoires, consultez
<ph type="x-smartling-placeholder"></ph>
Créer une table de suggestions
La classe SearchManager
comprend plusieurs colonnes pour Android TV. Certaines des
les colonnes les plus importantes sont décrites dans le tableau suivant.
Valeur | Description |
---|---|
SUGGEST_COLUMN_TEXT_1 |
Nom de votre contenu (obligatoire) |
SUGGEST_COLUMN_TEXT_2 |
Une description textuelle de votre contenu |
SUGGEST_COLUMN_RESULT_CARD_IMAGE |
Image, poster ou couverture de votre contenu |
SUGGEST_COLUMN_CONTENT_TYPE |
Type MIME de votre contenu multimédia. |
SUGGEST_COLUMN_VIDEO_WIDTH |
La largeur et la résolution de votre contenu multimédia |
SUGGEST_COLUMN_VIDEO_HEIGHT |
La hauteur et la résolution de votre contenu multimédia |
SUGGEST_COLUMN_PRODUCTION_YEAR |
Année de production de votre contenu (obligatoire) |
SUGGEST_COLUMN_DURATION |
Durée de votre contenu multimédia en millisecondes (obligatoire) |
Le framework de recherche requiert les colonnes suivantes:
Lorsque les valeurs de ces colonnes pour votre contenu correspondent aux valeurs du même contenu provenant d'autres par les serveurs Google, le système fournit lien profond vers votre application dans les détails consulter le contenu, ainsi que des liens vers les applications d'autres fournisseurs. Ce sujet est abordé plus en détail dans la section Lien profond vers votre application dans l'écran d'informations.
La classe de base de données de votre application peut définir les colonnes comme suit:
Kotlin
class VideoDatabase { companion object { // The columns we'll include in the video database table val KEY_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1 val KEY_DESCRIPTION = SearchManager.SUGGEST_COLUMN_TEXT_2 val KEY_ICON = SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE val KEY_DATA_TYPE = SearchManager.SUGGEST_COLUMN_CONTENT_TYPE val KEY_IS_LIVE = SearchManager.SUGGEST_COLUMN_IS_LIVE val KEY_VIDEO_WIDTH = SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH val KEY_VIDEO_HEIGHT = SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT val KEY_AUDIO_CHANNEL_CONFIG = SearchManager.SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG val KEY_PURCHASE_PRICE = SearchManager.SUGGEST_COLUMN_PURCHASE_PRICE val KEY_RENTAL_PRICE = SearchManager.SUGGEST_COLUMN_RENTAL_PRICE val KEY_RATING_STYLE = SearchManager.SUGGEST_COLUMN_RATING_STYLE val KEY_RATING_SCORE = SearchManager.SUGGEST_COLUMN_RATING_SCORE val KEY_PRODUCTION_YEAR = SearchManager.SUGGEST_COLUMN_PRODUCTION_YEAR val KEY_COLUMN_DURATION = SearchManager.SUGGEST_COLUMN_DURATION val KEY_ACTION = SearchManager.SUGGEST_COLUMN_INTENT_ACTION ... } ... }
Java
public class VideoDatabase { // The columns we'll include in the video database table public static final String KEY_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1; public static final String KEY_DESCRIPTION = SearchManager.SUGGEST_COLUMN_TEXT_2; public static final String KEY_ICON = SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE; public static final String KEY_DATA_TYPE = SearchManager.SUGGEST_COLUMN_CONTENT_TYPE; public static final String KEY_IS_LIVE = SearchManager.SUGGEST_COLUMN_IS_LIVE; public static final String KEY_VIDEO_WIDTH = SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH; public static final String KEY_VIDEO_HEIGHT = SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT; public static final String KEY_AUDIO_CHANNEL_CONFIG = SearchManager.SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG; public static final String KEY_PURCHASE_PRICE = SearchManager.SUGGEST_COLUMN_PURCHASE_PRICE; public static final String KEY_RENTAL_PRICE = SearchManager.SUGGEST_COLUMN_RENTAL_PRICE; public static final String KEY_RATING_STYLE = SearchManager.SUGGEST_COLUMN_RATING_STYLE; public static final String KEY_RATING_SCORE = SearchManager.SUGGEST_COLUMN_RATING_SCORE; public static final String KEY_PRODUCTION_YEAR = SearchManager.SUGGEST_COLUMN_PRODUCTION_YEAR; public static final String KEY_COLUMN_DURATION = SearchManager.SUGGEST_COLUMN_DURATION; public static final String KEY_ACTION = SearchManager.SUGGEST_COLUMN_INTENT_ACTION; ...
Lorsque vous créez la carte à partir des colonnes SearchManager
vers vos champs de données, vous
doit également spécifier _ID
pour attribuer un identifiant unique à chaque ligne.
Kotlin
companion object { .... private fun buildColumnMap(): MapS<tring, String> { return mapOf( KEY_NAME to KEY_NAME, KEY_DESCRIPTION to KEY_DESCRIPTION, KEY_ICON to KEY_ICON, KEY_DATA_TYPE to KEY_DATA_TYPE, KEY_IS_LIVE to KEY_IS_LIVE, KEY_VIDEO_WIDTH to KEY_VIDEO_WIDTH, KEY_VIDEO_HEIGHT to KEY_VIDEO_HEIGHT, KEY_AUDIO_CHANNEL_CONFIG to KEY_AUDIO_CHANNEL_CONFIG, KEY_PURCHASE_PRICE to KEY_PURCHASE_PRICE, KEY_RENTAL_PRICE to KEY_RENTAL_PRICE, KEY_RATING_STYLE to KEY_RATING_STYLE, KEY_RATING_SCORE to KEY_RATING_SCORE, KEY_PRODUCTION_YEAR to KEY_PRODUCTION_YEAR, KEY_COLUMN_DURATION to KEY_COLUMN_DURATION, KEY_ACTION to KEY_ACTION, BaseColumns._ID to ("rowid AS " + BaseColumns._ID), SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID to ("rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID), SearchManager.SUGGEST_COLUMN_SHORTCUT_ID to ("rowid AS " + SearchManager.SUGGEST_COLUMN_SHORTCUT_ID) ) } }
Java
... private static HashMap<String, String> buildColumnMap() { HashMap<String, String> map = new HashMap<String, String>(); map.put(KEY_NAME, KEY_NAME); map.put(KEY_DESCRIPTION, KEY_DESCRIPTION); map.put(KEY_ICON, KEY_ICON); map.put(KEY_DATA_TYPE, KEY_DATA_TYPE); map.put(KEY_IS_LIVE, KEY_IS_LIVE); map.put(KEY_VIDEO_WIDTH, KEY_VIDEO_WIDTH); map.put(KEY_VIDEO_HEIGHT, KEY_VIDEO_HEIGHT); map.put(KEY_AUDIO_CHANNEL_CONFIG, KEY_AUDIO_CHANNEL_CONFIG); map.put(KEY_PURCHASE_PRICE, KEY_PURCHASE_PRICE); map.put(KEY_RENTAL_PRICE, KEY_RENTAL_PRICE); map.put(KEY_RATING_STYLE, KEY_RATING_STYLE); map.put(KEY_RATING_SCORE, KEY_RATING_SCORE); map.put(KEY_PRODUCTION_YEAR, KEY_PRODUCTION_YEAR); map.put(KEY_COLUMN_DURATION, KEY_COLUMN_DURATION); map.put(KEY_ACTION, KEY_ACTION); map.put(BaseColumns._ID, "rowid AS " + BaseColumns._ID); map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); map.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_SHORTCUT_ID); return map; } ...
Dans l'exemple précédent, notez le mappage avec SUGGEST_COLUMN_INTENT_DATA_ID
.
. Il s'agit de la partie de l'URI qui pointe vers le contenu unique aux données de cette
ligne qui correspond à la dernière partie de l'URI, décrivant l'emplacement de stockage du contenu. La première partie de l'URI,
lorsqu'il est commun à toutes les lignes de la table, est défini dans
searchable.xml
en tant que
<ph type="x-smartling-placeholder"></ph>
android:searchSuggestIntentData
, comme décrit dans les
Gérer les suggestions de recherche.
Si la première partie de l'URI est différente pour chaque ligne de
mappez cette valeur avec le champ SUGGEST_COLUMN_INTENT_DATA
.
Lorsque l'utilisateur sélectionne ce contenu, l'intent qui se déclenche fournit les données d'intent à partir de
combinaison de SUGGEST_COLUMN_INTENT_DATA_ID
et soit l'attribut android:searchSuggestIntentData
, soit
Valeur du champ SUGGEST_COLUMN_INTENT_DATA
.
Fournir des données de suggestion de recherche
Implémenter un fournisseur de contenu
pour renvoyer des suggestions de termes de recherche dans la boîte de dialogue de recherche d'Android TV. Le système interroge votre contenu
pour obtenir des suggestions en appelant la méthode query()
à chaque fois
une lettre est tapée. Dans votre implémentation de query()
, votre contenu
Le fournisseur recherche vos données de suggestion et renvoie un Cursor
qui pointe vers
les lignes que vous avez désignées pour les suggestions.
Kotlin
fun query(uri: Uri, projection: Array<String>, selection: String, selectionArgs: Array<String>, sortOrder: String): Cursor { // Use the UriMatcher to see what kind of query we have and format the db query accordingly when (URI_MATCHER.match(uri)) { SEARCH_SUGGEST -> { Log.d(TAG, "search suggest: ${selectionArgs[0]} URI: $uri") if (selectionArgs == null) { throw IllegalArgumentException( "selectionArgs must be provided for the Uri: $uri") } return getSuggestions(selectionArgs[0]) } else -> throw IllegalArgumentException("Unknown Uri: $uri") } } private fun getSuggestions(query: String): Cursor { val columns = arrayOf<String>( BaseColumns._ID, VideoDatabase.KEY_NAME, VideoDatabase.KEY_DESCRIPTION, VideoDatabase.KEY_ICON, VideoDatabase.KEY_DATA_TYPE, VideoDatabase.KEY_IS_LIVE, VideoDatabase.KEY_VIDEO_WIDTH, VideoDatabase.KEY_VIDEO_HEIGHT, VideoDatabase.KEY_AUDIO_CHANNEL_CONFIG, VideoDatabase.KEY_PURCHASE_PRICE, VideoDatabase.KEY_RENTAL_PRICE, VideoDatabase.KEY_RATING_STYLE, VideoDatabase.KEY_RATING_SCORE, VideoDatabase.KEY_PRODUCTION_YEAR, VideoDatabase.KEY_COLUMN_DURATION, VideoDatabase.KEY_ACTION, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID ) return videoDatabase.getWordMatch(query.toLowerCase(), columns) }
Java
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Use the UriMatcher to see what kind of query we have and format the db query accordingly switch (URI_MATCHER.match(uri)) { case SEARCH_SUGGEST: Log.d(TAG, "search suggest: " + selectionArgs[0] + " URI: " + uri); if (selectionArgs == null) { throw new IllegalArgumentException( "selectionArgs must be provided for the Uri: " + uri); } return getSuggestions(selectionArgs[0]); default: throw new IllegalArgumentException("Unknown Uri: " + uri); } } private Cursor getSuggestions(String query) { query = query.toLowerCase(); String[] columns = new String[]{ BaseColumns._ID, VideoDatabase.KEY_NAME, VideoDatabase.KEY_DESCRIPTION, VideoDatabase.KEY_ICON, VideoDatabase.KEY_DATA_TYPE, VideoDatabase.KEY_IS_LIVE, VideoDatabase.KEY_VIDEO_WIDTH, VideoDatabase.KEY_VIDEO_HEIGHT, VideoDatabase.KEY_AUDIO_CHANNEL_CONFIG, VideoDatabase.KEY_PURCHASE_PRICE, VideoDatabase.KEY_RENTAL_PRICE, VideoDatabase.KEY_RATING_STYLE, VideoDatabase.KEY_RATING_SCORE, VideoDatabase.KEY_PRODUCTION_YEAR, VideoDatabase.KEY_COLUMN_DURATION, VideoDatabase.KEY_ACTION, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID }; return videoDatabase.getWordMatch(query, columns); } ...
Dans votre fichier manifeste, le fournisseur de contenu reçoit un traitement spécial. Plutôt que d'être
marquée comme une activité, elle est décrite comme
<provider>
La
Le fournisseur inclut l'attribut android:authorities
pour indiquer au système
de votre fournisseur de contenu. Vous devez également définir son attribut android:exported
sur
"true"
afin que la recherche globale Android puisse utiliser les résultats qu'elle renvoie.
<provider android:name="com.example.android.tvleanback.VideoContentProvider" android:authorities="com.example.android.tvleanback" android:exported="true" />
Gérer les suggestions de recherche
Votre application doit inclure un élément .
res/xml/searchable.xml
pour configurer les paramètres des suggestions de recherche.
Dans le fichier res/xml/searchable.xml
, incluez
le
android:searchSuggestAuthority
pour indiquer au système l'espace de noms de votre
fournisseur de contenu. Il doit correspondre à la valeur de chaîne spécifiée dans
android:authorities
attribut du <provider>
dans votre fichier AndroidManifest.xml
.
Incluez également un libellé, qui est le nom de l'application. Les paramètres de recherche du système utilisent ce libellé pour l'énumération dans les applications de recherche.
Le fichier searchable.xml
doit également inclure le paramètre
android:searchSuggestIntentAction
avec la valeur "android.intent.action.VIEW"
pour définir l'action d'intent pour fournir une suggestion personnalisée. Ceci est différent de l'intent
pour indiquer un terme de recherche, comme décrit dans la section suivante.
Pour les autres façons de déclarer l'action d'intent pour les suggestions,
consultez la section Déclarer
une action d'intent.
En plus de l'action d'intent, votre application doit fournir les données d'intent que vous spécifiez à l'aide de l'attribut
<ph type="x-smartling-placeholder"></ph>
android:searchSuggestIntentData
. Il s'agit de la première partie
de l'URI qui pointe
au contenu, qui décrit la partie de l'URI commune à toutes les lignes de la table de mappage pour cette
contenus. La partie de l'URI unique à chaque ligne est établie à l'aide du champ SUGGEST_COLUMN_INTENT_DATA_ID
,
comme décrit dans la section Identifier les colonnes.
Pour connaître d'autres façons de déclarer les données d'intent pour les suggestions, consultez
Déclaration
les données d'intent.
L'attribut android:searchSuggestSelection=" ?"
spécifie la valeur transmise.
en tant que paramètre selection
de query()
.
. La valeur du point d'interrogation (?
) est remplacée par le texte de la requête.
Enfin, vous devez également inclure le paramètre
android:includeInGlobalSearch
avec la valeur "true"
. Voici un exemple :
Fichier searchable.xml
:
<searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/search_label" android:hint="@string/search_hint" android:searchSettingsDescription="@string/settings_description" android:searchSuggestAuthority="com.example.android.tvleanback" android:searchSuggestIntentAction="android.intent.action.VIEW" android:searchSuggestIntentData="content://com.example.android.tvleanback/video_database_leanback" android:searchSuggestSelection=" ?" android:searchSuggestThreshold="1" android:includeInGlobalSearch="true"> </searchable>
Gérer les termes de recherche
Dès que la boîte de dialogue de recherche contient un mot correspondant à la valeur de l'une des colonnes de votre application, comme
décrit dans la section Identifier les colonnes, le système déclenche la
Intent ACTION_SEARCH
.
L'activité dans votre application qui gère cela
intent recherche dans le dépôt les colonnes contenant le mot donné dans ses valeurs et renvoie une liste
d'éléments de contenu avec ces colonnes. Dans votre fichier AndroidManifest.xml
, vous désignez
activité qui gère les ACTION_SEARCH
comme illustré dans l'exemple suivant:
... <activity android:name="com.example.android.tvleanback.DetailsActivity" android:exported="true"> <!-- Receives the search request. --> <intent-filter> <action android:name="android.intent.action.SEARCH" /> <!-- No category needed, because the Intent will specify this class component --> </intent-filter> <!-- Points to searchable meta data. --> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity> ... <!-- Provides search suggestions for keywords against video meta data. --> <provider android:name="com.example.android.tvleanback.VideoContentProvider" android:authorities="com.example.android.tvleanback" android:exported="true" /> ...
L'activité doit également décrire la configuration incluse dans l'index de recherche et faire référence au
searchable.xml
.
Pour utiliser la boîte de dialogue de recherche globale :
le fichier manifeste doit décrire l'activité qui doit recevoir des requêtes de recherche. Le fichier manifeste doit également
décrivez <provider>
, tel qu'il est décrit dans le fichier searchable.xml
.
Créer un lien profond vers votre application dans l'écran d'informations
Si vous avez défini la configuration de la recherche comme décrit dans la section Gérer la recherche
suggestions et a mis en correspondance les SUGGEST_COLUMN_TEXT_1
,
SUGGEST_COLUMN_PRODUCTION_YEAR
et
Champs SUGGEST_COLUMN_DURATION
comme décrit dans
la section Identifier les colonnes, un
un lien profond vers une action de visionnage pour votre contenu apparaît dans l'écran d'informations qui se lance lorsque
l'utilisateur sélectionne un résultat de recherche:
![Lien profond dans l'écran d'informations](https://developer.android.com/static/images/tv/deep-link.png?authuser=19&hl=fr)
Lorsque l'utilisateur sélectionne le lien vers votre application, identifié par le bouton **Disponible le** dans le
écran d'informations, le système lance l'activité qui gère le ACTION_VIEW
Définir en tant que
android:searchSuggestIntentAction
avec la valeur "android.intent.action.VIEW"
dans
le fichier searchable.xml
.
Vous pouvez également configurer un intent personnalisé pour lancer votre activité. Cela est illustré dans la
<ph type="x-smartling-placeholder"></ph>
Exemple d'application Leanback
pour en savoir plus. Notez que l'application exemple lance son propre LeanbackDetailsFragment
pour
afficher les détails du média sélectionné ; dans vos applications, lancez l'activité qui lit le contenu multimédia
immédiatement pour faire gagner
un ou deux clics à l'utilisateur.
Comportement de recherche
La recherche est disponible sur Android TV depuis l'écran d'accueil et depuis votre application. Résultats de recherche sont différents dans ces deux cas.
Rechercher depuis l'écran d'accueil
Lorsque l'utilisateur effectue une recherche depuis l'écran d'accueil, le premier résultat apparaît dans une fiche d'entité. S'il y a applications pouvant lire ce contenu, un lien vers chacune d'elles s'affiche au bas de la fiche:
![Lecture des résultats de recherche TV](https://developer.android.com/static/images/tv/tv-search-playback.png?authuser=19&hl=fr)
Vous ne pouvez pas placer une application par programmation dans la fiche de l'entité. À inclure en tant que l'option de lecture, les résultats de recherche d'une application doivent correspondre au titre, à l'année et à la durée le contenu recherché.
D'autres résultats de recherche peuvent être disponibles sous la carte. Pour les voir, l'utilisateur doit appuyer sur le et faites défiler l'écran vers le bas. Les résultats pour chaque application s'affichent sur une ligne distincte. Vous ne pouvez pas contrôler l’ordre des lignes. Applis compatibles actions de visionnage sont répertoriées en premier.
![Résultats de recherche TV](https://developer.android.com/static/images/tv/tv-search-results.gif?authuser=19&hl=fr)
Effectuer une recherche depuis votre application
L'utilisateur peut également lancer une recherche depuis votre application en activant le micro à partir de la télécommande ou manette de jeu. Les résultats de recherche sont affichés sur une seule ligne au-dessus du contenu de l'application. Votre application génère des résultats de recherche à l'aide de son propre moteur de recherche global.
![Résultats de recherche dans l'application TV](https://developer.android.com/static/images/tv/tv-search-in-app.png?authuser=19&hl=fr)
En savoir plus
Pour en savoir plus sur la recherche d'une appli TV, consultez Intégrer les fonctionnalités de recherche Android dans votre application Ajoutez une fonctionnalité de recherche.
Pour en savoir plus sur la personnalisation de l'expérience de recherche dans l'application avec un SearchFragment
, consultez
Effectuer des recherches dans les applications TV