Utilisation du fournisseur de contenu Media Store

Android Media Store est un référentiel géré de fichiers audio, vidéo et image. Chaque fois que vous ajoutez un nouveau fichier multimédia au système de fichiers, vous devez également l'ajouter à Media Store ; cela l'exposera à d'autres applications, notamment les lecteurs multimédias. Dans la plupart des cas, il n’est pas nécessaire (ni recommandé) de modifier directement le contenu du fournisseur de contenu Media Store. Pour accéder aux médias disponibles dans le Media Store, la classe MediaStore comprend les sous-classes Audio, Vidéo et Images, qui contiennent à leur tour des sous-classes utilisées pour fournir les noms de colonne et les URI de contenu aux fournisseurs de médias correspondants. Le Media Store sépare les médias conservés sur les volumes internes et externes du périphérique hôte. Chaque sous-classe Media Store fournit un URI pour le média stocké en interne ou en externe à l'aide des formulaires:

  • MediaStore.<mediatype>.Media.EXTERNAL_CONTENT_URI
  • MediaStore.<mediatype>.Media.INTERNAL_CONTENT_URI

Listing 10-19 shows a simple code snippet used to find the song title and album name for each piece of audio stored on the internal volume.

LISTING 10-19 : Accéder au fournisseur de contenu Media Store

  1. // Get a Cursor over every piece of audio on the external volume, // extracting the song title and album name.
  2. String[] projection = new String[] {
  3. MediaStore.Audio.AudioColumns.ALBUM,
  4. MediaStore.Audio.AudioColumns.TITLE
  5. } ;
  6. Uri contentUri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
  7. Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
  8. // Get the index of the columns we need.
  9. int albumIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ALBUM);
  10. int titleIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.TITLE);
  11. // Create an array to store the result set.
  12. String[] result = new String[cursor.getCount()];
  13. // Iterate over the Cursor, extracting each album name and song title.
  14. while (cursor.moveToNext()) {
  15. // Extract the song title.
  16. String title = cursor.getString(titleIdx);
  17. // Extract the album name.
  18. String album = cursor.getString(albumIdx);
  19. result[cursor.getPosition()] = title + " (" + album + ")";
  20. }
  21. // Close the Cursor.
  22. cursor.close();
  23.  

 

REMARQUE 

Vous apprendrez à lire les ressources audio et vidéo stockées dans le magasin de médias en spécifiant l'URI d'un élément multimédia particulier, ainsi qu'à ajouter correctement un média au magasin de médias. 


Utilisation du fournisseur de contenu des contacts

Android met la base de données complète des informations de contact à la disposition de toute application disposant de l'autorisation READ_CONTACTS. Le fournisseur ContactsContract fournit une base de données extensible contenant des informations relatives aux contacts. Cela permet aux utilisateurs d'utiliser et de combiner plusieurs sources pour leurs informations de contact. Plus important encore, il permet aux développeurs d'étendre de manière arbitraire les données stockées pour chaque contact, voire même de devenir un fournisseur alternatif pour les contacts et les détails de contact. Plutôt que de fournir une table unique et entièrement définie de colonnes de détails de contact, le fournisseur de contrats de contacts utilise un modèle de données à trois niveaux pour stocker les données, les associer à un contact et les agréger à une seule personne à l'aide des sous-classes suivantes:

Données : chaque ligne du tableau sous-jacent définit un ensemble de données personnelles (numéros de téléphone, adresses de messagerie, etc.), séparées par le type MIME. Bien qu'il existe un ensemble prédéfini de noms de colonnes communs pour chaque type de données personnelles disponible (ainsi que les types MIME appropriés des sous-classes de ContactsContract.CommonDataKinds), cette table peut être utilisée pour stocker toute valeur. Le type de données stockées dans une ligne particulière est déterminé par le type MIME spécifié pour cette ligne. Une série de colonnes génériques est ensuite utilisée pour stocker jusqu'à 15 types de données différents, en fonction du type MIME. Lorsque vous ajoutez de nouvelles données à la table de données, vous spécifiez un contact brut auquel un ensemble de données sera associé.

RawContacts : les utilisateurs peuvent ajouter plusieurs fournisseurs de comptes de contacts à leur appareil, par exemple s'ils ont ajouté plusieurs comptes Gmail. Chaque ligne de la table Contacts bruts définit un compte auquel un ensemble de valeurs de données est associé.

Contacts : l’application Contacts Android regroupe et expose tous les contacts, de tous lescompte sur l'appareil, dans une liste unique. Il est possible que la même personne soit incluse en tant que contact dans plusieurs comptes. Par exemple, votre autre personne importante peut apparaître en tant qu’entrée dans vos comptes Gmail personnel et professionnel. La table Contacts représente l'agrégation de plusieurs lignes de contacts bruts décrivant la même personne. Elles apparaissent donc sous la forme d'une entrée dans l'application Contacts Android.Le contenu de chacune de ces tables est agrégé comme indiqué à la figure 10-1.  

FIGURE 10-1

En règle générale, vous utiliserez la table de données pour ajouter, supprimer ou modifier les données stockées sur un compte de contact existant, la table de contacts bruts pour créer et gérer des comptes, ainsi que les tables de contact et de données pour interroger la base de données afin d'extraire les détails du contact.

 

Lecture des détails de contact

Pour accéder à l'un des fournisseurs de contrat de contact, vous devez inclure l'autorisation READ_CONTACTS uses- dans votre manifeste d'application:

  1. < uses-permission android:name="android.permission.READ_CONTACTS"/ >

 Les appareils Android exécutant Android 6.0 Marshmallow (API niveau 23) requièrent également l'autorisation d'exécution correspondante:

  1. int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);

Utilisez le résolveur de contenu pour interroger l’un des trois fournisseurs de contrats de contact décrits précédemment à l’aide de leurs constantes statiques CONTENT_URI respectives. Chaque classe inclut ses noms de colonne sous forme de propriétés statiques.

La liste 10-20 interroge la table des contacts pour trouver un curseur auprès de chaque personne du carnet d'adresses, créant ainsi un tableau de chaînes contenant le nom et l'ID unique de chaque contact.

LISTING 10-20 : Accéder au fournisseur de contenu du contrat Contacts

  1. // Create a projection that limits the result Cursor
  2. // to the required columns.
  3. String[] projection = {
  4. ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME
  5. } ;
  6. // Get a Cursor over the Contacts Provider.
  7. Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null);
  8. // Get the index of the columns.
  9. int nameIdx = cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME);
  10. int idIdx = cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID);
  11. // Initialize the result set.
  12. String[] result = new String[cursor.getCount()];
  13. // Iterate over the result Cursor.
  14. while(cursor.moveToNext()) {
  15. // Extract the name.
  16. String name = cursor.getString(nameIdx);
  17. // Extract the unique ID.
  18. String id = cursor.getString(idIdx);
  19. result[cursor.getPosition()] = name + " (" + id + ")";
  20. }
  21. // Close the Cursor. cursor.close();

Le fournisseur de contenu ContactsContract.Data est utilisé pour stocker toutes les informations de contact, telles que les adresses, les numéros de téléphone et les adresses électroniques. Dans la plupart des cas, vous demanderez probablement des informations de contact basées sur un nom de contact complet ou partiel.

Pour simplifier cette recherche, Android fournit l'URI de la requête ContactsContract.Contacts.CONTENT_FILTER_URI. Ajoutez le nom complet ou partiel à cette recherche en tant que segment de chemin supplémentaire à l'URI. Pour extraire les détails du contact associé, recherchez la valeur _ID du curseur renvoyé et utilisez-la pour créer une requête sur la table de données.

Le contenu de chaque colonne avec une ligne dans la table de données dépend du type MIME spécifié pour cette ligne. Par conséquent, toute requête de la table de données doit filtrer les lignes par type MIME pour extraire les données de manière significative.

Le Listing 10-21 montre comment utiliser les noms de colonne de détail de contact disponibles dans les sous-classes CommonDataKinds pour extraire le nom complet et le numéro de téléphone mobile du tableau de données d'un contact particulier.

LISTING 10-21 : Recherche des coordonnées d'un nom de contact

  1. ContentResolver cr = getContentResolver();
  2. String[] result = null;
  3. // Find a contact using a partial name match
  4. String searchName = "john";
  5. Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI,searchName);
  6. // Create a projection of the required column names.
  7. String[] projection = new String[] {
  8. ContactsContract.Contacts._ID
  9. } ;
  10. // Get a Cursor that will return the ID(s) of the matched name.
  11. Cursor idCursor = cr.query(lookupUri, projection, null, null, null);
  12. // Extract the first matching ID if it exists.
  13. String id = null; if (idCursor.moveToFirst()) {
  14. int idIdx = idCursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID);
  15. id = idCursor.getString(idIdx); }
  16. // Close that Cursor. idCursor.close();
  17. // Create a new Cursor searching for the data associated
  18. // with the returned Contact ID.
  19. if (id != null) {
  20. // Return all the PHONE data for the contact.
  21. String where = ContactsContract.Data.CONTACT_ID + " = " + id + " AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'";
  22. projection = new String[] {
  23. ContactsContract.Data.DISPLAY_NAME,
  24. ContactsContract.CommonDataKinds.Phone.NUMBER
  25. };
  26. Cursor dataCursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, where, null, null);
  27. // Get the indexes of the required columns.
  28. int nameIdx = dataCursor.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME);
  29. int phoneIdx = dataCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER); result = new String[dataCursor.getCount()];
  30. while(dataCursor.moveToNext()) {
  31. // Extract the name.
  32. String name = dataCursor.getString(nameIdx);
  33. // Extract the phone number.
  34. String number = dataCursor.getString(phoneIdx);
  35. result[dataCursor.getPosition()] = name + " (" + number + ")"; }
  36. dataCursor.close(); }

 

La sous-classe Contacts propose également un URI de recherche de numéro de téléphone pour vous aider à trouver un contact associé à un numéro de téléphone particulier. Cette requête est hautement optimisée pour renvoyer des résultats rapides pour la notification d'identification de l'appelant.

Utilisez ContactsContract.PhoneLookup.CONTENT_FILTER_URI, en ajoutant le numéro à rechercher en tant que segment de chemin supplémentaire, comme indiqué dans l'extrait 10-22.

LISTING 10-22 : Effectuer une recherche d'identification de l'appelant

  1. String incomingNumber = "(555) 123-4567";
  2. String result = "Not Found";
  3. Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,incomingNumber);
  4. String[] projection = new String[] {
  5. ContactsContract.Contacts.DISPLAY_NAME
  6. } ;
  7. Cursor cursor = getContentResolver().query(lookupUri, projection, null, null, null);
  8. if (cursor.moveToFirst()) {
  9. int nameIdx = cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME);
  10. result = cursor.getString(nameIdx);
  11. }
  12. cursor.close();

 

Utilisation de l'API Intents pour le fournisseur de contenu des contacts

Le fournisseur de contenu de contrat de contacts comprend un mécanisme basé sur l'intention qui peut être utilisé pour afficher, insérer ou sélectionner un contact à l'aide d'une application de contact existante (généralement, l'application de contact natif).

Il s’agit de la meilleure approche pratique et présente l’avantage de présenter à l’utilisateur une interface cohérente pour effectuer la même tâche, en évitant les ambiguïtés et en améliorant l’expérience globale de l’utilisateur. Étant donné que l'utilisateur a le pouvoir d'annuler l'action sans affecter le fournisseur de contenu, vous n'avez besoin d'aucune autorisation spéciale pour utiliser cette technique pour sélectionner ou créer de nouveaux contacts.

 

Accéder aux contacts à l'aide d'intentions

Pour afficher une liste de contacts pour vos utilisateurs, vous pouvez utiliser l'action Intent.ACTION_PICK et utiliser la méthode setType pour indiquer le type MIME des données de contact que vous souhaitez utiliser.

La liste 10-23 demande que nous choisissions un contact avec un numéro de téléphone.

LISTING 10-23 : Choisir un contact

  1. private static int PICK_CONTACT = 0;
  2. private void pickContact() {
  3. Intent intent = new Intent(Intent.ACTION_PICK);
  4. intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
  5. startActivityForResult(intent, PICK_CONTACT);
  6. }

 Cela affichera une vue en liste des contacts disponibles (comme illustré à la figure 10-2).

Lorsque l'utilisateur sélectionne un contact, celui-ci est renvoyé en tant qu'URI de recherche dans la propriété data de l'intention renvoyée. Pour récupérer des détails de contact spécifiques, utilisez le résolveur de contenu pour effectuer une requête à l'aide de l'URI de recherche, puis extrayez les détails requis, comme indiqué dans cette extension du Listing 10-23:

  1. @Override
  2. protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data);
  3. if ((requestCode == PICK_CONTACT) &amp;&amp; (resultCode == RESULT_OK)) {
  4. Uri selectedContact = data.getData();
  5. Cursor cursor = getContentResolver().query(selectedContact,
  6. null, null, null, null);
  7. // If the cursor returned is valid, get the phone number
  8. if (cursor != null &amp;&amp; cursor.moveToFirst()) {
  9. int numberIndex = cursor.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER);
  10. String number = cursor.getString(numberIndex);
  11. int nameIndex = cursor.getColumnIndex( ContactsContract.CommonDataKinds.Identity.DISPLAY_NAME);
  12. String name = cursor.getString(nameIndex);
  13. // TODO: Do something with the selected name and phone number.
  14. }
  15. }
  16. }

 

Les délégués de l'application Contacts lisent et écrivent des autorisations sur cet URI de contenu pour la vie de votre Activité, ce qui signifie que vous pouvez l’utiliser pour accéder aux données associées sans demander d’autorisation spéciale.

 

Insertion ou modification de contacts avec intention

Pour insérer un nouveau contact, vous utiliserez une intention spécifiant un numéro de téléphone ou une adresse e-mail, ainsi que des extras permettant de pré-renseigner le nouveau formulaire de contact.

L’action ContactsContract.Intents.SHOW_OR_CREATE_CONTACT va rechercher dans le fournisseur de contacts une adresse de messagerie ou un URI de numéro de téléphone particulier, en proposant d’insérer une nouvelle entrée uniquement si un contact avec l’adresse de contact spécifiée n’existe pas. Si le contact existe, il sera affiché.

Utilisez les constantes de la classe ContactsContract.Intents.Insert pour inclure les extras d’intention pouvant être utilisés pour pré-renseigner les détails du contact, y compris le nom, la société, le courrier électronique, le numéro de téléphone, les notes et l'adresse postale du nouveau contact. montré dans le Listing 10-24.

LISTING 10-24 : Insertion d'un nouveau contact à l'aide d'une intention

  1. Intent intent = new Intent(ContactsContract.Intents.SHOW_OR_CREATE_CONTACT,ContactsContract.Contacts.CONTENT_URI);
  2. intent.setData(Uri.parse("tel:(650)253-0000")); intent.putExtra(ContactsContract.Intents.Insert.COMPANY, "Google"); intent.putExtra(ContactsContract.Intents.Insert.POSTAL, "1600 Amphitheatre Parkway, Mountain View, California");
  3. startActivity(intent);