Cette leçon explique comment récupérer les données détaillées d'un contact, telles que les adresses e-mail, les numéros de de chiffres, etc. Il s'agit des informations que les utilisateurs recherchent lorsqu'ils récupèrent un contact. Vous pouvez leur fournir toutes les informations d'un contact ou n'afficher que des informations d'un type particulier, comme les adresses e-mail.
Les étapes de cette leçon supposent que vous disposez déjà d'une ligne ContactsContract.Contacts
pour un contact choisi par l'utilisateur.
La leçon Récupérer les noms des contacts explique comment
récupérer une liste de contacts.
Récupérer tous les détails d'un contact
Pour récupérer tous les détails d'un contact, recherchez
Table ContactsContract.Data
pour toutes les lignes contenant le nom du contact
LOOKUP_KEY
Cette colonne est disponible dans
la table ContactsContract.Data
, car les contacts
Le fournisseur crée une jointure implicite entre ContactsContract.Contacts
et la table ContactsContract.Data
. La colonne LOOKUP_KEY
est décrite plus en détail dans la leçon Récupérer les noms de contact.
Remarque:La récupération de tous les détails d'un contact réduit les performances
appareil, car il doit récupérer toutes les colonnes
ContactsContract.Data
. Tenez compte de l'impact sur les performances avant
vous utilisez cette technique.
Demander des autorisations
Pour que vous puissiez lire des données à partir de Contacts Provider, votre application doit
Autorisation READ_CONTACTS
.
Pour demander cette autorisation, ajoutez l'élément enfant suivant de
<manifest>
à votre fichier manifeste:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Configurer une projection
Selon le type de données qu'une ligne contient, elle peut n'utiliser que quelques colonnes ou beaucoup. De plus, les données sont réparties dans différentes colonnes en fonction du type de données.
Pour vous assurer d'obtenir toutes les colonnes possibles pour tous les types de données possibles, vous devez ajouter tous les noms de colonnes à votre projection. Toujours récupérer
Data._ID
si vous liez le résultat
Cursor
en ListView
; Sinon, la liaison
ne fonctionne pas. Récupérer également Data.MIMETYPE
afin que vous puissiez identifier le type de données
de chaque ligne que vous récupérez. Exemple :
Kotlin
private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 )
Java
private static final String[] PROJECTION = { ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 };
Cette projection récupère toutes les colonnes d'une ligne dans la table ContactsContract.Data
, à l'aide des noms de colonnes définis dans la classe ContactsContract.Data
.
Vous pouvez également utiliser d'autres constantes de colonne définies ou héritées de la classe ContactsContract.Data
. Notez toutefois que les colonnes SYNC1
à SYNC4
sont destinées à être utilisées par les adaptateurs de synchronisation. Leurs données ne sont donc pas utiles.
Définir les critères de sélection
Définissez une constante pour votre clause de sélection, un tableau pour contenir les arguments de sélection et une variable pour contenir la valeur de sélection. Utilisez la colonne Contacts.LOOKUP_KEY
pour trouver le contact. Exemple :
Kotlin
// Defines the selection clause private const val SELECTION: String = "${ContactsContract.Data.LOOKUP_KEY} = ?" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("") /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private var lookupKey: String? = null
Java
// Defines the selection clause private static final String SELECTION = Data.LOOKUP_KEY + " = ?"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" }; /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private lateinit var lookupKey: String
L'utilisation de "?" comme espace réservé dans l'expression de texte de sélection garantit que la recherche générée est générée par liaison plutôt que par compilation SQL. Cette approche élimine une injection SQL malveillante.
Définir l'ordre de tri
Définissez l'ordre de tri souhaité dans le Cursor
obtenu. À
conserver toutes les lignes d'un type de données particulier ensemble, trier par
Data.MIMETYPE
Cet argument de requête regroupe toutes les lignes d'adresse e-mail, toutes les lignes de téléphone, etc. Exemple :
Kotlin
/* * Defines a string that specifies a sort order of MIME type */ private const val SORT_ORDER = ContactsContract.Data.MIMETYPE
Java
/* * Defines a string that specifies a sort order of MIME type */ private static final String SORT_ORDER = ContactsContract.Data.MIMETYPE;
Remarque:Vous ne pouvez pas trier les données par sous-type, car certains types de données n'en utilisent pas.
Vous devez plutôt itérer sur les Cursor
renvoyés, déterminer le type de données de la ligne actuelle et stocker les données des lignes qui utilisent un sous-type. Quand ?
vous avez fini de lire le curseur, vous pouvez ensuite trier chaque type de données par sous-type et afficher le
résultats.
Initialiser le chargeur
Toujours effectuer des récupérations auprès du fournisseur de contacts (et de tous les autres fournisseurs de contenu)
thread d'arrière-plan. Utilisez le framework Loader défini par la classe LoaderManager
et l'interface LoaderManager.LoaderCallbacks
pour effectuer des récupérations en arrière-plan.
Lorsque vous êtes prêt à récupérer les lignes, initialisez le framework Loader en
Appel de initLoader()
en cours. Transmettez un identifiant entier à la méthode. Cet identifiant est transmis aux méthodes LoaderManager.LoaderCallbacks
. L'identifiant vous aide à utiliser plusieurs chargeurs dans une application en vous permettant de les différencier.
L'extrait de code suivant montre comment initialiser le framework du chargeur:
Kotlin
// Defines a constant that identifies the loader private const val DETAILS_QUERY_ID: Int = 0 class DetailsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { ... // Initializes the loader framework loaderManager.initLoader(DETAILS_QUERY_ID, null, this)
Java
public class DetailsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Defines a constant that identifies the loader static int DETAILS_QUERY_ID = 0; ... @Override public void onCreate(Bundle savedInstanceState) { ... // Initializes the loader framework getLoaderManager().initLoader(DETAILS_QUERY_ID, 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()
. Renvoyez un
CursorLoader
de cette méthode. Étant donné que vous recherchez dans la table ContactsContract.Data
, utilisez la constante Data.CONTENT_URI
comme URI de contenu.
Exemple :
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { // Choose the proper action mLoader = when(loaderId) { DETAILS_QUERY_ID -> { // Assigns the selection parameter selectionArgs[0] = lookupKey // Starts the query activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ) } } ... } return mLoader }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // Choose the proper action switch (loaderId) { case DETAILS_QUERY_ID: // Assigns the selection parameter selectionArgs[0] = lookupKey; // Starts the query CursorLoader mLoader = new CursorLoader( getActivity(), ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ); }
Implémenter onLoadFinished() et onLoaderReset()
Implémentez la méthode onLoadFinished()
. Le framework de chargement appelle onLoadFinished()
lorsque le fournisseur de contacts renvoie les résultats de la requête. Exemple :
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor) { when(loader.id) { DETAILS_QUERY_ID -> { /* * Process the resulting Cursor here. */ } ... } }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * Process the resulting Cursor here. */ } break; ... } }
La méthode onLoaderReset()
est appelée lorsque le framework du chargeur détecte que les données qui sauvegardent le résultat
Cursor
a changé. À ce stade, supprimez toutes les références existantes
à Cursor
en les définissant sur "null". Sinon, le framework de chargeur ne détruira pas l'ancien Cursor
, et vous obtiendrez une fuite de mémoire. Exemple :
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { when (loader.id) { DETAILS_QUERY_ID -> { /* * If you have current references to the Cursor, * remove them here. */ } ... } }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * If you have current references to the Cursor, * remove them here. */ } break; }
Récupérer des informations spécifiques sur un contact
La récupération d'un type de données spécifique pour un contact, comme tous les e-mails, suit le même schéma que la récupération de toutes les informations. Ce sont les seules modifications que vous devez apporter au code consultez la section Récupérer tous les détails d'un contact:
- Projection
-
Modifiez votre projection pour récupérer les colonnes spécifiques au type de données. Modifiez également la projection pour utiliser les constantes de nom de colonne définies dans la sous-classe
ContactsContract.CommonDataKinds
correspondant au type de données. - Sélection
-
Modifiez le texte de sélection pour rechercher la valeur
MIMETYPE
spécifique à votre type de données. - Ordre de tri
-
Étant donné que vous ne sélectionnez qu'un seul type de détail, ne regroupez pas les valeurs
Cursor
d'ici leData.MIMETYPE
.
Ces modifications sont décrites dans les sections suivantes.
Définir une projection
Définissez les colonnes que vous souhaitez récupérer à l'aide des constantes de nom de colonne de la sous-classe.
de ContactsContract.CommonDataKinds
pour le type de données.
Si vous prévoyez de lier votre Cursor
à un ListView
, veillez à récupérer la colonne _ID
. Par exemple, pour récupérer des données de messagerie, définissez la projection suivante :
Kotlin
private val PROJECTION: Array<String> = arrayOf( ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL )
Java
private static final String[] PROJECTION = { ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL };
Notez que cette projection utilise les noms de colonne définis dans la classe
ContactsContract.CommonDataKinds.Email
, au lieu des noms de colonnes
défini dans la classe ContactsContract.Data
. L'utilisation de noms de colonnes spécifiques à l'adresse e-mail améliore la lisibilité du code.
Dans la projection, vous pouvez également utiliser n'importe quelle autre colonne définie dans le
ContactsContract.CommonDataKinds
.
Définir les critères de sélection
Définissez une expression de texte de recherche qui récupère les lignes pour les LOOKUP_KEY
d'un contact spécifique et les Data.MIMETYPE
des informations souhaitées. Encadrez la valeur MIMETYPE
entre guillemets simples en concatenant un caractère "'
" (guillemet simple) au début et à la fin de la constante. Sinon, le fournisseur interprète la constante 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
en utilisant une constante plutôt qu'une valeur fournie par l'utilisateur. Exemple :
Kotlin
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private const val SELECTION = "${ContactsContract.Data.LOOKUP_KEY} = ? AND " + "${ContactsContract.Data.MIMETYPE} = '${Email.CONTENT_ITEM_TYPE}'" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("")
Java
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private static final String SELECTION = Data.LOOKUP_KEY + " = ?" + " AND " + Data.MIMETYPE + " = " + "'" + Email.CONTENT_ITEM_TYPE + "'"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" };
Définir un ordre de tri
Définissez un ordre de tri pour l'élément Cursor
renvoyé. Étant donné que vous récupérez un type de données spécifique, omettez le tri sur MIMETYPE
.
Si le type de données détaillées que vous recherchez inclut un sous-type, effectuez un tri en fonction de celui-ci.
Par exemple, pour les données de messagerie, vous pouvez trier sur Email.TYPE
:
Kotlin
private const val SORT_ORDER: String = "${Email.TYPE} ASC"
Java
private static final String SORT_ORDER = Email.TYPE + " ASC ";