Cette leçon vous explique comment récupérer une liste de contacts dont les données correspondent à tout ou partie d'une chaîne de recherche à l'aide des techniques suivantes:
- Correspondre aux noms des contacts
- Récupérez une liste de contacts en faisant correspondre la chaîne de recherche avec tout ou partie du contact. de noms. Le fournisseur de contacts autorise plusieurs instances du même nom. Cette technique peut donc renvoyer une liste de correspondances.
- Correspondre à un type de données spécifique, comme un numéro de téléphone
- Récupérez une liste de contacts en faisant correspondre la chaîne de recherche à un type particulier de données détaillées, comme une adresse e-mail. Par exemple, cette technique vous permet de lister tous les contacts dont l'adresse e-mail correspond à la chaîne de recherche.
- Mise en correspondance avec n'importe quel type de données
- Récupérez une liste de contacts en faisant correspondre la chaîne de recherche à n'importe quel type de données détaillées, y compris le nom, le numéro de téléphone, l'adresse postale, l'adresse e-mail, etc. Par exemple : cette technique vous permet d'accepter n'importe quel type de données pour une chaîne de recherche, puis de répertorier contacts dont les données correspondent à la chaîne.
Remarque:Tous les exemples de cette leçon utilisent un
CursorLoader
pour récupérer les données des contacts
Fournisseur. Un CursorLoader
exécute sa requête sur un thread distinct du thread d'UI. Cela garantit que la requête ne ralentit pas l'UI
les temps de réponse et nuit à l'expérience utilisateur. Pour en savoir plus, consultez la documentation
cours de formation
Charger des données en arrière-plan
Demander l'autorisation de lire le fournisseur
Pour effectuer un type de recherche du fournisseur de contacts, votre application doit disposer de l'autorisation READ_CONTACTS
.
Pour demander cela, ajoutez cet élément <uses-permission>
à votre fichier manifeste en tant qu'élément enfant de <manifest>
:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Faire correspondre un contact par son nom et lister les résultats
Cette technique tente de faire correspondre une chaîne de recherche au nom d'un ou de plusieurs contacts dans la table ContactsContract.Contacts
du fournisseur de contacts. Vous souhaitez généralement afficher les résultats dans un ListView
, afin de permettre à l'utilisateur de choisir parmi les contacts correspondants.
Définir la mise en page des éléments ListView et des éléments
Pour afficher les résultats de recherche dans une ListView
, vous avez besoin d'un fichier de mise en page principal
qui définit l'ensemble de l'UI, y compris le ListView
et une mise en page d'élément
qui définit une ligne de ListView
. Par exemple, vous pouvez créer
le fichier de mise en page principal res/layout/contacts_list_view.xml
avec
le fichier XML suivant:
<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent"/>
Ce fichier XML utilise le widget Android ListView
intégré
android:id/list
Définissez le fichier de mise en page de l'élément contacts_list_item.xml
avec le code XML suivant:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true"/>
Ce fichier XML utilise le widget Android TextView
intégré android:text1
.
Remarque : Cette leçon ne décrit pas l'UI permettant d'obtenir une chaîne de recherche auprès de l'utilisateur, car vous pouvez obtenir la chaîne indirectement. Par exemple, vous pouvez donner à l'utilisateur la possibilité de rechercher des contacts dont le nom correspond à une chaîne dans un message texte entrant.
Les deux fichiers de mise en page que vous avez écrits définissent une interface utilisateur qui affiche un ListView
. L'étape suivante consiste à écrire du code qui utilise cette interface utilisateur pour afficher un
liste de contacts.
Définir un fragment qui affiche la liste des contacts
Pour afficher la liste des contacts, commencez par définir un Fragment
chargé par un Activity
. Avec un
Fragment
est une technique plus flexible, car vous pouvez utiliser
une Fragment
pour afficher la liste et une seconde
Fragment
pour afficher les détails d'un contact que l'utilisateur
choisit dans la liste. En utilisant cette approche, vous pouvez combiner l'une des techniques présentées dans
cette leçon avec une autre tirée de la leçon
Récupérer les détails d'un contact
Pour découvrir comment utiliser un ou plusieurs objets Fragment
à partir d'un Activity
, consultez la formation Créer une UI dynamique avec des fragments.
Pour vous aider à écrire des requêtes sur Contacts Provider, le framework Android fournit un
la classe des contrats appelée ContactsContract
, qui définit
constantes et méthodes pour accéder au fournisseur. Lorsque vous utilisez cette classe, vous n'avez pas à
définir vos propres constantes pour les URI de contenu, les noms de tables ou les colonnes. Pour utiliser cette classe, incluez l'instruction suivante :
Kotlin
import android.provider.ContactsContract
Java
import android.provider.ContactsContract;
Étant donné que le code utilise un CursorLoader
pour récupérer des données auprès du fournisseur, vous devez spécifier qu'il implémente l'interface de chargeur LoaderManager.LoaderCallbacks
. De plus, pour détecter les contacts
l'utilisateur sélectionne dans la liste des résultats de recherche, implémentez l'interface de l'adaptateur
AdapterView.OnItemClickListener
Exemple :
Kotlin
... import android.support.v4.app.Fragment import android.support.v4.app.LoaderManager import android.widget.AdapterView ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
Java
... import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.widget.AdapterView; ... public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
Définir des variables globales
Définissez des variables globales utilisées dans d'autres parties du code :
Kotlin
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private val FROM_COLUMNS: Array<String> = arrayOf( if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) { ContactsContract.Contacts.DISPLAY_NAME_PRIMARY } else { ContactsContract.Contacts.DISPLAY_NAME } ) /* * Defines an array that contains resource ids for the layout views * that get the Cursor column contents. The id is pre-defined in * the Android framework, so it is prefaced with "android.R.id" */ private val TO_IDS: IntArray = intArrayOf(android.R.id.text1) ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener { ... // Define global mutable variables // Define a ListView object lateinit var contactsList: ListView // Define variables for the contact the user selects // The contact's _ID value var contactId: Long = 0 // The contact's LOOKUP_KEY var contactKey: String? = null // A content URI for the selected contact var contactUri: Uri? = null // An adapter that binds the result Cursor to the ListView private val cursorAdapter: SimpleCursorAdapter? = null
Java
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private final static String[] FROM_COLUMNS = { Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME }; /* * Defines an array that contains resource ids for the layout views * that get the Cursor column contents. The id is pre-defined in * the Android framework, so it is prefaced with "android.R.id" */ private final static int[] TO_IDS = { android.R.id.text1 }; // Define global mutable variables // Define a ListView object ListView contactsList; // Define variables for the contact the user selects // The contact's _ID value long contactId; // The contact's LOOKUP_KEY String contactKey; // A content URI for the selected contact Uri contactUri; // An adapter that binds the result Cursor to the ListView private SimpleCursorAdapter cursorAdapter; ...
Remarque:Puisque
Contacts.DISPLAY_NAME_PRIMARY
nécessite Android 3.0 (version 11 de l'API) ou une version ultérieure. Le paramètre
minSdkVersion
à 10 ou à une version antérieure de l'application génère un avertissement Android Lint dans
Android Studio Pour désactiver cet avertissement, ajoutez l'annotation
@SuppressLint("InlinedApi")
avant la définition de FROM_COLUMNS
.
Initialiser le fragment
Initialisez Fragment
. Ajoutez le constructeur public vide requis par le système Android et gonflez l'UI de l'objet Fragment
dans la méthode de rappel onCreateView()
.
Exemple :
Kotlin
// A UI Fragment must inflate its View override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false) }
Java
// Empty public constructor, required by the system public ContactsFragment() {} // A UI Fragment must inflate its View @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false); }
Configurer CursorAdapter pour ListView
Configurez le SimpleCursorAdapter
qui lie les résultats de la recherche au ListView
. Pour obtenir l'objet ListView
qui affiche les contacts, vous devez appeler Activity.findViewById()
à l'aide de l'activité parente de Fragment
. Utilisez le Context
de l'activité parente lorsque vous appelez setAdapter()
.
Exemple :
Kotlin
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) ... // Gets the ListView from the View list of the parent activity activity?.also { contactsList = it.findViewById<ListView>(R.id.contact_list_view) // Gets a CursorAdapter cursorAdapter = SimpleCursorAdapter( it, R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0 ) // Sets the adapter for the ListView contactsList.adapter = cursorAdapter } }
Java
public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ... // Gets the ListView from the View list of the parent activity contactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); // Gets a CursorAdapter cursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0); // Sets the adapter for the ListView contactsList.setAdapter(cursorAdapter); }
Définir l'écouteur de contact sélectionné
Lorsque vous affichez les résultats d'une recherche, vous souhaitez généralement autoriser l'utilisateur à sélectionner un seul contact pour un traitement ultérieur. Par exemple, lorsque l'utilisateur clique sur un contact, vous pouvez afficher son adresse sur une carte. Pour fournir cette fonctionnalité, vous avez d'abord défini l'Fragment
actuel comme écouteur de clic en spécifiant que la classe implémente AdapterView.OnItemClickListener
, comme indiqué dans la section Définir un fragment qui affiche la liste des contacts.
Pour continuer à configurer l'écouteur, liez-le à ListView
en
Appel de la méthode setOnItemClickListener()
dans onActivityCreated()
Exemple :
Kotlin
fun onActivityCreated(savedInstanceState:Bundle) { ... // Set the item click listener to be the current fragment. contactsList.onItemClickListener = this ... }
Java
public void onActivityCreated(Bundle savedInstanceState) { ... // Set the item click listener to be the current fragment. contactsList.setOnItemClickListener(this); ... }
Comme vous avez spécifié que le Fragment
actuel est le OnItemClickListener
du ListView
, vous devez maintenant implémenter sa méthode requise onItemClick()
, qui gère l'événement de clic. Ce point est décrit dans une section suivante.
Définir une projection
Définissez une constante qui contient les colonnes que vous souhaitez renvoyer à partir de votre requête. Chaque élément dans
ListView
affiche le nom à afficher du contact,
qui contient la forme
principale du nom du contact. Dans Android 3.0 (version 11 de l'API) et versions ultérieures, le nom de cette colonne est Contacts.DISPLAY_NAME_PRIMARY
. Dans les versions antérieures, il est Contacts.DISPLAY_NAME
.
La colonne Contacts._ID
est utilisée par
SimpleCursorAdapter
.
Contacts._ID
et LOOKUP_KEY
sont utilisés ensemble pour créer un URI de contenu pour le contact sélectionné par l'utilisateur.
Kotlin
... @SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Contacts.DISPLAY_NAME_PRIMARY else ContactsContract.Contacts.DISPLAY_NAME )
Java
... @SuppressLint("InlinedApi") private static final String[] PROJECTION = { Contacts._ID, Contacts.LOOKUP_KEY, Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME };
Définir des constantes pour les index de colonne du curseur
Pour obtenir les données d'une colonne individuelle dans un Cursor
, vous avez besoin des éléments suivants :
l'index de la colonne dans Cursor
. Vous pouvez définir des constantes pour les indices des colonnes Cursor
, car les indices sont identiques à l'ordre des noms de colonnes dans votre projection. Exemple :
Kotlin
// The column index for the _ID column private const val CONTACT_ID_INDEX: Int = 0 // The column index for the CONTACT_KEY column private const val CONTACT_KEY_INDEX: Int = 1
Java
// The column index for the _ID column private static final int CONTACT_ID_INDEX = 0; // The column index for the CONTACT_KEY column private static final int CONTACT_KEY_INDEX = 1;
Spécifier les critères de sélection
Pour spécifier les données souhaitées, créez une combinaison d'expressions textuelles et de variables qui indiquent au fournisseur les colonnes de données à rechercher et les valeurs à trouver.
Pour l'expression textuelle, définissez une constante qui liste les colonnes de recherche. Bien que cette peut également contenir des valeurs, il est recommandé de représenter les valeurs avec un "?" . Lors de la récupération, l'espace réservé est remplacé par les valeurs d'un tableau. L'utilisation de "?" comme espace réservé garantit que la spécification de recherche est générée par liaison plutôt que par compilation SQL. Cette pratique élimine la possibilité d'injection SQL malveillante. Exemple :
Kotlin
// Defines the text expression @SuppressLint("InlinedApi") private val SELECTION: String = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE ?" else "${ContactsContract.Contacts.DISPLAY_NAME} LIKE ?" ... // Defines a variable for the search string private val searchString: String = ... // Defines the array to hold values that replace the ? private val selectionArgs = arrayOf<String>(searchString)
Java
// Defines the text expression @SuppressLint("InlinedApi") private static final String SELECTION = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?" : Contacts.DISPLAY_NAME + " LIKE ?"; // Defines a variable for the search string private String searchString; // Defines the array to hold values that replace the ? private String[] selectionArgs = { searchString };
Définir la méthode onItemClick()
Dans une section précédente, vous avez défini l'écouteur de clics de l'élément pour ListView
.
Implémentez maintenant l'action pour l'écouteur en définissant la méthode AdapterView.OnItemClickListener.onItemClick()
:
Kotlin
override fun onItemClick(parent: AdapterView<*>, view: View?, position: Int, id: Long) { // Get the Cursor val cursor: Cursor? = (parent.adapter as? CursorAdapter)?.cursor?.apply { // Move to the selected contact moveToPosition(position) // Get the _ID value contactId = getLong(CONTACT_ID_INDEX) // Get the selected LOOKUP KEY contactKey = getString(CONTACT_KEY_INDEX) // Create the contact's content Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, mContactKey) /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ } }
Java
@Override public void onItemClick( AdapterView<?> parent, View item, int position, long rowID) { // Get the Cursor Cursor cursor = parent.getAdapter().getCursor(); // Move to the selected contact cursor.moveToPosition(position); // Get the _ID value contactId = cursor.getLong(CONTACT_ID_INDEX); // Get the selected LOOKUP KEY contactKey = cursor.getString(CONTACT_KEY_INDEX); // Create the contact's content Uri contactUri = Contacts.getLookupUri(contactId, mContactKey); /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ }
Initialiser le chargeur
Étant donné que vous utilisez un CursorLoader
pour récupérer des données, vous devez initialiser le thread en arrière-plan et d'autres variables qui contrôlent la récupération asynchrone. Effectuez l'initialisation dans onCreate()
comme indiqué dans l'exemple suivant :
Kotlin
class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { // Always call the super method first super.onCreate(savedInstanceState) ... // Initializes the loader loaderManager.initLoader(0, null, this)
Java
public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Called just before the Fragment displays its UI @Override public void onCreate(Bundle savedInstanceState) { // Always call the super method first super.onCreate(savedInstanceState); ... // Initializes the loader getLoaderManager().initLoader(0, null, this);
Implémenter onCreateLoader()
Implémentez la méthode onCreateLoader()
, qui est appelée par le framework de chargeur immédiatement après l'appel de initLoader()
.
Dans onCreateLoader()
, configurez le modèle de chaîne de recherche. Pour transformer une chaîne en modèle, insérez des caractères "%" (pourcentage) pour représenter une séquence de zéro ou plusieurs caractères, ou des caractères "_" (underscore) pour représenter un seul caractère, ou les deux. Exemple : "%Jefferson%"
correspondrait à la fois à "Thomas Jefferson" et Jefferson Davis.
Renvoyez un nouveau CursorLoader
à partir de la méthode. Pour le contenu
URI, utilisez Contacts.CONTENT_URI
.
Cet URI fait référence à l'ensemble de la table, comme illustré dans l'exemple suivant :
Kotlin
... override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%$mSearchString%" // Starts the query return activity?.let { return CursorLoader( it, ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
... @Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%" + searchString + "%"; // Starts the query return new CursorLoader( getActivity(), ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
Implémenter onLoadFinished() et onLoaderReset()
Implémentez le
onLoadFinished()
. Le framework de chargement appelle onLoadFinished()
lorsque le fournisseur de contacts renvoie les résultats de la requête. Dans cette méthode, placez
résultat Cursor
dans
SimpleCursorAdapter
Les résultats de recherche sont automatiquement mis à jour dans ListView
:
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter?.swapCursor(cursor) }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter.swapCursor(cursor); }
La méthode onLoaderReset()
est appelée lorsque le framework du chargeur détecte que la
Le résultat Cursor
contient des données obsolètes. Supprimez la référence SimpleCursorAdapter
à l'Cursor
existante. Sinon, le framework du chargeur
à recycler Cursor
, ce qui entraîne une fuite de mémoire. Exemple :
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { // Delete the reference to the existing Cursor cursorAdapter?.swapCursor(null) }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { // Delete the reference to the existing Cursor cursorAdapter.swapCursor(null); }
Vous disposez désormais des éléments clés d'une application qui associe une chaîne de recherche aux noms de contacts et renvoie
le résultat en ListView
. L'utilisateur peut cliquer sur le nom d'un contact pour le sélectionner.
Cela déclenche un écouteur, dans lequel vous pouvez continuer à travailler avec les données du contact. Par exemple :
vous pouvez récupérer les coordonnées du contact. Pour savoir comment procéder, passez à la leçon suivante, Récupérer les informations d'un contact.
Pour en savoir plus sur les interfaces utilisateur de recherche, consultez le guide de l'API. Créez une interface de recherche.
Les sections restantes de cette leçon présentent d'autres façons de trouver des contacts dans le fournisseur de contacts.
Associer un contact à un type de données spécifique
Cette technique vous permet de spécifier le type de données que vous souhaitez faire correspondre. Récupération... par nom est un exemple spécifique de ce type de requête, mais vous pouvez également le faire pour tous les types de données détaillées associées à un contact. Par exemple, vous pouvez récupérer les contacts ayant un code postal spécifique. Dans ce cas, la chaîne de recherche doit correspondre aux données stockées dans une ligne de code postal.
Pour implémenter ce type de récupération, commencez par implémenter le code suivant, comme indiqué dans sections précédentes:
- Demander l'autorisation de lire le fournisseur.
- Définir les mises en page des éléments ListView et des éléments
- Définissez un fragment qui affiche la liste des contacts.
- Définissez des variables globales.
- Initialisez le fragment.
- Configurez CursorAdapter pour ListView.
- Définissez l'écouteur de contacts sélectionné.
-
Définissez des constantes pour les index de colonne de curseur.
Bien que vous récupériez des données à partir d'une autre table, l'ordre des colonnes dans la projection est le même. Vous pouvez donc utiliser les mêmes index pour le curseur.
- Définissez la méthode onItemClick().
- Initialisez le chargeur.
- Implémentez onLoadFinished() et onLoaderReset().
Les étapes suivantes vous montrent le code supplémentaire dont vous avez besoin pour faire correspondre une chaîne de recherche à un type particulier de données détaillées et afficher les résultats.
Choisir le type de données et le tableau
Pour rechercher un type de données détaillées particulier, vous devez connaître la valeur du type MIME personnalisé pour le type de données. Chaque type de données possède un type MIME unique
valeur définie par une constante CONTENT_ITEM_TYPE
dans la sous-classe de
ContactsContract.CommonDataKinds
associé au type de données.
Les sous-classes portent des noms qui indiquent leur type de données. Par exemple, la sous-classe des données de messagerie est ContactsContract.CommonDataKinds.Email
, et le type MIME personnalisé des données de messagerie est défini par la constante Email.CONTENT_ITEM_TYPE
.
Utilisez le tableau ContactsContract.Data
pour votre recherche. Toutes les constantes dont vous avez besoin pour votre projection, votre clause de sélection et votre ordre de tri sont définies dans ce tableau ou en héritent.
Définir une projection
Pour définir une projection, choisissez une ou plusieurs des colonnes définies dans
ContactsContract.Data
ou des classes dont il hérite. La
Le fournisseur de contacts effectue une jointure implicite entre ContactsContract.Data
et d'autres tables avant
de renvoyer des lignes. Exemple :
Kotlin
@SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Data.DISPLAY_NAME_PRIMARY else ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY )
Java
@SuppressLint("InlinedApi") private static final String[] PROJECTION = { /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Data.DISPLAY_NAME_PRIMARY : ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY // A permanent link to the contact };
Définir des critères de recherche
Pour rechercher une chaîne dans un type de données particulier, créez une clause de sélection à partir des éléments suivants :
-
Nom de la colonne contenant votre chaîne de recherche. Ce nom varie
selon le type de données,
Vous devez donc trouver la sous-classe
ContactsContract.CommonDataKinds
correspondant au type de données puis choisissez le nom de la colonne dans cette sous-classe. Par exemple, pour rechercher des adresses e-mail, utilisez la colonneEmail.ADDRESS
. - La chaîne de recherche proprement dite, représentée par le point d'interrogation (?) dans la clause de sélection.
-
Nom de la colonne contenant la valeur du type MIME personnalisé. Ce nom est toujours
Data.MIMETYPE
. -
Valeur du type MIME personnalisé pour le type de données. Comme décrit précédemment, il s'agit de la constante
CONTENT_ITEM_TYPE
dans la sous-classeContactsContract.CommonDataKinds
. Par exemple, le fichier MIME La valeur type pour les données de messagerie estEmail.CONTENT_ITEM_TYPE
Placez la valeur entre guillemets simples en concaténant une "'
" (guillemet simple) au début et à la fin de la constante. Sinon, le fournisseur interprète la valeur comme un nom de variable plutôt que comme une valeur de chaîne. Vous n'avez pas besoin d'utiliser un espace réservé pour cette valeur, car vous utilisez une constante plutôt qu'une valeur fournie par l'utilisateur.
Exemple :
Kotlin
/* * Constructs search criteria from the search string * and email MIME type */ private val SELECTION: String = /* * Searches for an email address * that matches the search string */ "${Email.ADDRESS} LIKE ? AND " + /* * Searches for a MIME type that matches * the value of the constant * Email.CONTENT_ITEM_TYPE. Note the * single quotes surrounding Email.CONTENT_ITEM_TYPE. */ "${ContactsContract.Data.MIMETYPE } = '${Email.CONTENT_ITEM_TYPE}'"
Java
/* * Constructs search criteria from the search string * and email MIME type */ private static final String SELECTION = /* * Searches for an email address * that matches the search string */ Email.ADDRESS + " LIKE ? " + "AND " + /* * Searches for a MIME type that matches * the value of the constant * Email.CONTENT_ITEM_TYPE. Note the * single quotes surrounding Email.CONTENT_ITEM_TYPE. */ ContactsContract.Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'";
Définissez ensuite des variables pour contenir l'argument de sélection :
Kotlin
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
Java
String searchString; String[] selectionArgs = { "" };
Implémenter onCreateLoader()
Maintenant que vous avez spécifié les données que vous souhaitez et comment les trouver, définissez une requête dans votre implémentation de onCreateLoader()
.
Renvoyer un nouveau CursorLoader
à partir de ce
, en utilisant votre projection, votre expression de texte de sélection et votre tableau de sélection comme
. Pour un URI de contenu, utilisez Data.CONTENT_URI
. Exemple :
Kotlin
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { // OPTIONAL: Makes search string into pattern searchString = "%$mSearchString%" searchString?.also { // Puts the search string into the selection criteria selectionArgs[0] = it } // Starts the query return activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // OPTIONAL: Makes search string into pattern searchString = "%" + searchString + "%"; // Puts the search string into the selection criteria selectionArgs[0] = searchString; // Starts the query return new CursorLoader( getActivity(), Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
Ces extraits de code constituent la base d'une recherche inversée simple basée sur un type spécifique de données détaillées. Il s'agit de la meilleure technique à utiliser si votre application se concentre sur un type de données particulier, tel que que les e-mails, et que vous voulez autoriser les utilisateurs à obtenir les noms associés à un élément de données.
Faire correspondre un contact selon n'importe quel type de données
La récupération d'un contact en fonction de n'importe quel type de données renvoie des contacts si l'une de leurs données correspond à la chaîne de recherche, y compris le nom, l'adresse e-mail, l'adresse postale, le numéro de téléphone, etc. Cela se traduit par un large éventail de résultats de recherche. Par exemple, si la chaîne de recherche est "Doe", alors la recherche de n'importe quel type de données renvoie le contact "John Doe". elle renvoie également contacts qui vivent sur "Doe Street".
Pour implémenter ce type de récupération, commencez par implémenter le code suivant, comme indiqué dans sections précédentes:
- Demander l'autorisation de lire le fournisseur.
- Définir les mises en page des éléments ListView et des éléments
- Définissez un fragment qui affiche la liste des contacts.
- Définissez des variables globales.
- Initialisez le fragment.
- Configurez CursorAdapter pour ListView.
- Définissez l'écouteur de contact sélectionné.
- Définissez une projection.
-
Définissez des constantes pour les index de colonne du curseur.
Pour ce type de récupération, vous utilisez la même table que dans la section Associer un contact par nom et lister les résultats. Utilisez également les mêmes indices de colonne.
- Définissez la méthode onItemClick().
- Initialisez le chargeur.
- Implémentez onLoadFinished() et onLoaderReset().
Les étapes suivantes vous montrent le code supplémentaire dont vous avez besoin pour faire correspondre une chaîne de recherche tout type de données et afficher les résultats.
Supprimer les critères de sélection
Ne définissez pas les constantes SELECTION
ni la variable mSelectionArgs
.
Ils ne sont pas utilisés dans ce type de récupération.
Implémenter onCreateLoader()
Implémenter onCreateLoader()
, ce qui renvoie un nouveau CursorLoader
.
Vous n'avez pas besoin de convertir la chaîne de recherche en modèle, car le fournisseur de contacts
automatiquement. Utilisez Contacts.CONTENT_FILTER_URI
comme URI de base, puis ajoutez votre chaîne de recherche en appelant Uri.withAppendedPath()
. L'utilisation de cet URI déclenche automatiquement la recherche de n'importe quel type de données, comme illustré dans l'exemple suivant :
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ val contentUri: Uri = Uri.withAppendedPath( ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(searchString) ) // Starts the query return activity?.let { CursorLoader( it, contentUri, PROJECTION2, null, null, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ Uri contentUri = Uri.withAppendedPath( Contacts.CONTENT_FILTER_URI, Uri.encode(searchString)); // Starts the query return new CursorLoader( getActivity(), contentUri, PROJECTION, null, null, null ); }
Ces extraits de code constituent la base d'une application qui effectue une recherche étendue dans le fournisseur de contacts. Cette technique est utile pour les applications qui souhaitent implémenter une fonctionnalité semblable à l'écran de liste de contacts de l'application People.