Modifier des contacts à l'aide d'intents

Cette leçon vous explique comment utiliser un Intent pour insérer un nouveau contact ou modifier les données d'un contact. Au lieu d'accéder directement au Contacts Provider, un Intent démarre l'application Contacts, qui exécute l'Activity approprié. Pour les actions de modification décrites dans cette leçon, si vous envoyez des données étendues dans l'Intent, elles sont saisies dans l'interface utilisateur de l'Activity qui est démarré.

L'utilisation d'un Intent pour insérer ou mettre à jour un seul contact est la méthode recommandée pour modifier le Contacts Provider, pour les raisons suivantes :

  • Vous gagnez ainsi du temps et de l'énergie, car vous n'avez pas à développer votre propre UI ni votre propre code.
  • Cela évite d'introduire des erreurs causées par des modifications qui ne respectent pas les règles du fournisseur de contacts.
  • Il réduit le nombre d'autorisations que vous devez demander. Votre application n'a pas besoin d'autorisation pour écrire dans le fournisseur de contacts, car elle délègue les modifications à l'application Contacts, qui dispose déjà de cette autorisation.

Insérer un contact à l'aide d'un intent

Vous souhaitez souvent autoriser l'utilisateur à insérer un nouveau contact lorsque votre application reçoit de nouvelles données. Par exemple, une application d'avis sur les restaurants peut permettre aux utilisateurs d'ajouter un restaurant en tant que contact lorsqu'ils l'évaluent. Pour ce faire, créez l'intent en utilisant autant de données que possible, puis envoyez-le à l'application Contacts.

L'insertion d'un contact à l'aide de l'application Contacts insère un nouveau contact brut dans la table ContactsContract.RawContacts du fournisseur de contacts. Si nécessaire, l'application Contacts invite les utilisateurs à indiquer le type de compte et le compte à utiliser lors de la création des coordonnées brutes. L'application Contacts informe également les utilisateurs si les coordonnées brutes existent déjà. Les utilisateurs ont alors la possibilité d'annuler l'insertion, auquel cas aucun contact n'est créé. Pour en savoir plus sur les coordonnées brutes, consultez le guide de l'API Contacts Provider.

Créer un intent

Pour commencer, créez un objet Intent avec l'action Intents.Insert.ACTION. Définissez le type MIME sur RawContacts.CONTENT_TYPE. Exemple :

Kotlin

...
// Creates a new Intent to insert a contact
val intent = Intent(ContactsContract.Intents.Insert.ACTION).apply {
    // Sets the MIME type to match the Contacts Provider
    type = ContactsContract.RawContacts.CONTENT_TYPE
}

Java

...
// Creates a new Intent to insert a contact
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
// Sets the MIME type to match the Contacts Provider
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

Si vous disposez déjà d'informations sur le contact, telles qu'un numéro de téléphone ou une adresse e-mail, vous pouvez les insérer dans l'intent en tant que données étendues. Pour une valeur de clé, utilisez la constante appropriée de Intents.Insert. L'application Contacts affiche les données sur son écran d'insertion, ce qui permet aux utilisateurs d'apporter des modifications et des ajouts supplémentaires.

Kotlin

private var emailAddress: EditText? = null
private var phoneNumber: EditText? = null
...
/* Assumes EditText fields in your UI contain an email address
 * and a phone number.
 *
 */
emailAddress = findViewById(R.id.email)
phoneNumber = findViewById(R.id.phone)
...
/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
intent.apply {
    // Inserts an email address
    putExtra(ContactsContract.Intents.Insert.EMAIL, emailAddress?.text)
    /*
     * In this example, sets the email type to be a work email.
     * You can set other email types as necessary.
     */
    putExtra(
            ContactsContract.Intents.Insert.EMAIL_TYPE,
            ContactsContract.CommonDataKinds.Email.TYPE_WORK
    )
    // Inserts a phone number
    putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber?.text)
    /*
     * In this example, sets the phone type to be a work phone.
     * You can set other phone types as necessary.
     */
    putExtra(
            ContactsContract.Intents.Insert.PHONE_TYPE,
            ContactsContract.CommonDataKinds.Phone.TYPE_WORK
    )
}

Java

private EditText emailAddress = null;
private EditText phoneNumber = null;
...
/* Assumes EditText fields in your UI contain an email address
 * and a phone number.
 *
 */
emailAddress = (EditText) findViewById(R.id.email);
phoneNumber = (EditText) findViewById(R.id.phone);
...
/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
// Inserts an email address
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, emailAddress.getText())
/*
 * In this example, sets the email type to be a work email.
 * You can set other email types as necessary.
 */
      .putExtra(ContactsContract.Intents.Insert.EMAIL_TYPE,
            ContactsContract.CommonDataKinds.Email.TYPE_WORK)
// Inserts a phone number
      .putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber.getText())
/*
 * In this example, sets the phone type to be a work phone.
 * You can set other phone types as necessary.
 */
      .putExtra(ContactsContract.Intents.Insert.PHONE_TYPE,
            ContactsContract.CommonDataKinds.Phone.TYPE_WORK);

Une fois que vous avez créé l'objet Intent, envoyez-le en appelant startActivity().

Kotlin

    /* Sends the Intent
     */
    startActivity(intent)

Java

    /* Sends the Intent
     */
    startActivity(intent);

Cet appel ouvre un écran dans l'application Contacts qui permet aux utilisateurs de saisir un nouveau contact. Le type et le nom du compte du contact sont indiqués en haut de l'écran. Une fois que les utilisateurs ont saisi les données et cliqué sur OK, la liste de contacts de l'application Contacts s'affiche. Les utilisateurs reviennent à votre application en cliquant sur Retour.

Modifier un contact existant à l'aide d'un intent

La modification d'un contact existant à l'aide d'un Intent est utile si l'utilisateur a déjà choisi un contact qui l'intéresse. Par exemple, une application qui recherche des contacts disposant d'une adresse postale, mais pas de code postal, peut permettre aux utilisateurs de rechercher le code, puis de l'ajouter au contact.

Pour modifier un contact existant à l'aide d'un intent, utilisez une procédure semblable à l'insertion d'un contact. Créez un intent comme décrit dans la section Insérer un nouveau contact à l'aide d'un intent, mais ajoutez l'Contacts.CONTENT_LOOKUP_URI du contact et le type MIME Contacts.CONTENT_ITEM_TYPE à l'intent. Si vous souhaitez modifier le contact avec des informations dont vous disposez déjà, vous pouvez les placer dans les données étendues de l'intent. Notez que certaines colonnes de nom ne peuvent pas être modifiées à l'aide d'un intent. Ces colonnes sont répertoriées dans la section récapitulative de la documentation de référence de l'API pour la classe ContactsContract.Contacts sous l'en-tête "Update" (Mettre à jour).

Enfin, envoyez l'intent. En réponse, l'application Contacts affiche un écran de modification. Lorsque l'utilisateur a terminé de modifier et enregistre les modifications, l'application Contacts affiche une liste de contacts. Lorsque l'utilisateur clique sur Retour, votre application s'affiche.

Créer l'intent

Pour modifier un contact, appelez Intent(action) afin de créer un intent avec l'action ACTION_EDIT. Appelez setDataAndType() pour définir la valeur de données de l'intent sur l'URI Contacts.CONTENT_LOOKUP_URI du contact et le type MIME sur le type MIME Contacts.CONTENT_ITEM_TYPE. Comme un appel à setType() écrase la valeur de données actuelle pour Intent, vous devez définir les données et le type MIME en même temps.

Pour obtenir le Contacts.CONTENT_LOOKUP_URI d'un contact, appelez Contacts.getLookupUri(id, lookupkey) avec les valeurs Contacts._ID et Contacts.LOOKUP_KEY du contact comme arguments.

Remarque : La valeur LOOKUP_KEY d'un contact est l'identifiant que vous devez utiliser pour récupérer un contact. Il reste constant, même si le fournisseur modifie l'ID de ligne du contact pour gérer les opérations internes.

L'extrait de code suivant montre comment créer un intent :

Kotlin

    // The Cursor that contains the Contact row
    var mCursor: Cursor? = null
    // The index of the lookup key column in the cursor
    var lookupKeyIndex: Int = 0
    // The index of the contact's _ID value
    var idIndex: Int = 0
    // The lookup key from the Cursor
    var currentLookupKey: String? = null
    // The _ID value from the Cursor
    var currentId: Long = 0
    // A content URI pointing to the contact
    var selectedContactUri: Uri? = null
    ...
    /*
     * Once the user has selected a contact to edit,
     * this gets the contact's lookup key and _ID values from the
     * cursor and creates the necessary URI.
     */
    mCursor?.apply {
        // Gets the lookup key column index
        lookupKeyIndex = getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)
        // Gets the lookup key value
        currentLookupKey = getString(lookupKeyIndex)
        // Gets the _ID column index
        idIndex = getColumnIndex(ContactsContract.Contacts._ID)
        currentId = getLong(idIndex)
        selectedContactUri = ContactsContract.Contacts.getLookupUri(currentId, mCurrentLookupKey)
    }

    // Creates a new Intent to edit a contact
    val editIntent = Intent(Intent.ACTION_EDIT).apply {
        /*
         * Sets the contact URI to edit, and the data type that the
         * Intent must match
         */
        setDataAndType(selectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE)
    }

Java

    // The Cursor that contains the Contact row
    public Cursor mCursor;
    // The index of the lookup key column in the cursor
    public int lookupKeyIndex;
    // The index of the contact's _ID value
    public int idIndex;
    // The lookup key from the Cursor
    public String currentLookupKey;
    // The _ID value from the Cursor
    public long currentId;
    // A content URI pointing to the contact
    Uri selectedContactUri;
    ...
    /*
     * Once the user has selected a contact to edit,
     * this gets the contact's lookup key and _ID values from the
     * cursor and creates the necessary URI.
     */
    // Gets the lookup key column index
    lookupKeyIndex = mCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
    // Gets the lookup key value
    currentLookupKey = mCursor.getString(lookupKeyIndex);
    // Gets the _ID column index
    idIndex = mCursor.getColumnIndex(ContactsContract.Contacts._ID);
    currentId = mCursor.getLong(idIndex);
    selectedContactUri =
            Contacts.getLookupUri(currentId, mCurrentLookupKey);
    ...
    // Creates a new Intent to edit a contact
    Intent editIntent = new Intent(Intent.ACTION_EDIT);
    /*
     * Sets the contact URI to edit, and the data type that the
     * Intent must match
     */
    editIntent.setDataAndType(selectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);

Ajouter l'option de navigation

Dans Android 4.0 (API version 14) et versions ultérieures, un problème dans l'application Contacts entraîne une navigation incorrecte. Lorsque votre application envoie un intent de modification à l'application Contacts, que les utilisateurs modifient et enregistrent un contact, puis qu'ils cliquent sur Retour, l'écran de la liste de contacts s'affiche. Pour revenir à votre application, ils doivent cliquer sur Récents et choisir votre application.

Pour contourner ce problème dans Android 4.0.3 (version d'API 15) et versions ultérieures, ajoutez la clé de données étendue finishActivityOnSaveCompleted à l'intent, avec la valeur true. Les versions d'Android antérieures à Android 4.0 acceptent cette clé, mais elle n'a aucun effet. Pour définir les données étendues, procédez comme suit :

Kotlin

    // Sets the special extended data for navigation
    editIntent.putExtra("finishActivityOnSaveCompleted", true)

Java

    // Sets the special extended data for navigation
    editIntent.putExtra("finishActivityOnSaveCompleted", true);

Ajouter d'autres données étendues

Pour ajouter des données étendues supplémentaires à Intent, appelez putExtra() si nécessaire. Vous pouvez ajouter des données étendues pour les champs de contact courants à l'aide des valeurs de clé spécifiées dans Intents.Insert. N'oubliez pas que certaines colonnes de la table ContactsContract.Contacts ne peuvent pas être modifiées. Ces colonnes sont listées dans la section récapitulative de la documentation de référence de l'API pour la classe ContactsContract.Contacts sous l'en-tête "Update".

Envoyer l'intent

Enfin, envoyez l'intent que vous avez créé. Exemple :

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

Permettre aux utilisateurs de choisir d'insérer ou de modifier à l'aide d'un intent

Vous pouvez permettre aux utilisateurs de choisir d'insérer un contact ou de modifier un contact existant en envoyant un Intent avec l'action ACTION_INSERT_OR_EDIT. Par exemple, une application de messagerie peut permettre aux utilisateurs d'ajouter une adresse e-mail entrante à un nouveau contact ou de l'ajouter en tant qu'adresse supplémentaire pour un contact existant. Définissez le type MIME de cet intent sur Contacts.CONTENT_ITEM_TYPE, mais ne définissez pas l'URI de données.

Lorsque vous envoyez cet intent, l'application Contacts affiche une liste de contacts. Les utilisateurs peuvent insérer un nouveau contact ou sélectionner un contact existant et le modifier. Tous les champs de données étendus que vous ajoutez à l'intent renseignent l'écran qui s'affiche. Vous pouvez utiliser n'importe quelle valeur de clé spécifiée dans Intents.Insert. L'extrait de code suivant montre comment créer et envoyer l'intent :

Kotlin

    // Creates a new Intent to insert or edit a contact
    val intentInsertEdit = Intent(Intent.ACTION_INSERT_OR_EDIT).apply {
        // Sets the MIME type
        type = ContactsContract.Contacts.CONTENT_ITEM_TYPE
    }
    // Add code here to insert extended data, if desired

    // Sends the Intent with an request ID
    startActivity(intentInsertEdit)

Java

    // Creates a new Intent to insert or edit a contact
    Intent intentInsertEdit = new Intent(Intent.ACTION_INSERT_OR_EDIT);
    // Sets the MIME type
    intentInsertEdit.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
    // Add code here to insert extended data, if desired
    ...
    // Sends the Intent with an request ID
    startActivity(intentInsertEdit);