Изменение контактов с помощью намерений

В этом уроке показано, как использовать Intent для вставки нового контакта или изменения данных контакта. Вместо прямого доступа к поставщику контактов Intent запускает приложение контактов, которое запускает соответствующее Activity . Для действий по модификации, описанных в этом уроке, если вы отправляете расширенные данные в Intent , они вводятся в пользовательский интерфейс запущенного Activity .

Использование Intent для вставки или обновления одного контакта является предпочтительным способом изменения поставщика контактов по следующим причинам:

  • Это экономит ваше время и усилия на разработку собственного пользовательского интерфейса и кода.
  • Это позволяет избежать ошибок, вызванных изменениями, которые не соответствуют правилам поставщика контактов.
  • Это уменьшает количество разрешений, которые необходимо запрашивать. Вашему приложению не требуется разрешение на запись поставщику контактов, поскольку оно делегирует изменения приложению контактов, у которого уже есть такое разрешение.

Вставьте новый контакт, используя намерение

Часто требуется разрешить пользователю вставлять новый контакт, когда ваше приложение получает новые данные. Например, приложение для обзора ресторанов может позволить пользователям добавлять ресторан в список контактов, когда они оставляют его отзыв. Чтобы сделать это с помощью намерения, создайте намерение, используя как можно больше данных, а затем отправьте намерение в приложение контактов.

При вставке контакта с помощью приложения контактов новый необработанный контакт вставляется в таблицу ContactsContract.RawContacts поставщика контактов. При необходимости приложение контактов запрашивает у пользователей тип учетной записи и учетную запись, которые будут использоваться при создании необработанного контакта. Приложение контактов также уведомляет пользователей, если необработанный контакт уже существует. Затем у пользователей есть возможность отменить вставку, и в этом случае контакт не создается. Дополнительные сведения о необработанных контактах см. в руководстве по API поставщика контактов .

Создайте намерение

Для начала создайте новый объект Intent с действием Intents.Insert.ACTION . Установите тип MIME на RawContacts.CONTENT_TYPE . Например:

Котлин

...
// 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
}

Ява

...
// 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);

Если у вас уже есть сведения о контакте, например номер телефона или адрес электронной почты, вы можете вставить их в намерение как расширенные данные. В качестве значения ключа используйте соответствующую константу из Intents.Insert . Приложение контактов отображает данные на экране вставки, позволяя пользователям вносить дальнейшие изменения и дополнения.

Котлин

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
    )
}

Ява

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);

После того, как вы создали Intent , отправьте его, вызвав startActivity() .

Котлин

    /* Sends the Intent
     */
    startActivity(intent)

Ява

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

Этот вызов открывает экран в приложении контактов, на котором пользователи могут ввести новый контакт. Тип учетной записи и имя учетной записи для контакта указаны в верхней части экрана. Как только пользователи введут данные и нажмут «Готово» , появится список контактов приложения «Контакты». Пользователи возвращаются в ваше приложение, нажав кнопку «Назад» .

Редактировать существующий контакт, используя намерение

Редактирование существующего контакта с помощью Intent полезно, если пользователь уже выбрал интересующий контакт. Например, приложение, которое находит контакты, имеющие почтовые адреса, но не имеющие почтового индекса, может предоставить пользователям возможность найти код и затем добавить его к контакту.

Чтобы отредактировать существующий контакт с помощью намерения, используйте процедуру, аналогичную вставке контакта. Создайте намерение, как описано в разделе Вставка нового контакта с помощью намерения , но добавьте в намерение Contacts.CONTENT_LOOKUP_URI контакта и MIME-тип Contacts.CONTENT_ITEM_TYPE . Если вы хотите отредактировать контакт с уже имеющимися у вас данными, вы можете поместить их в расширенные данные намерения. Обратите внимание, что некоторые столбцы имен нельзя редактировать с помощью намерения; эти столбцы перечислены в сводном разделе справочника API для класса ContactsContract.Contacts под заголовком «Обновление».

Наконец, отправьте намерение. В ответ приложение контактов отображает экран редактирования. Когда пользователь завершает редактирование и сохраняет изменения, приложение контактов отображает список контактов. Когда пользователь нажимает «Назад» , отображается ваше приложение.

Создайте намерение

Чтобы отредактировать контакт, вызовите Intent(action) чтобы создать намерение с действием ACTION_EDIT . Вызовите setDataAndType() чтобы установить значение данных для намерения в соответствии с контактом Contacts.CONTENT_LOOKUP_URI и типом MIME для типа Contacts.CONTENT_ITEM_TYPE MIME; поскольку вызов setType() перезаписывает текущее значение данных для Intent , вы должны установить данные и тип MIME одновременно.

Чтобы получить Contacts.CONTENT_LOOKUP_URI контакта, вызовите Contacts.getLookupUri(id, lookupkey) со значениями Contacts._ID и Contacts.LOOKUP_KEY контакта в качестве аргументов.

Примечание. Значение LOOKUP_KEY контакта — это идентификатор, который следует использовать для получения контакта. Он остается постоянным, даже если поставщик меняет идентификатор строки контакта для обработки внутренних операций.

В следующем фрагменте показано, как создать намерение:

Котлин

    // 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)
    }

Ява

    // 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);

Добавьте флаг навигации

В Android 4.0 (API версии 14) и более поздних версиях проблема в приложении контактов приводит к некорректной навигации. Когда ваше приложение отправляет намерение редактирования в приложение контактов, а пользователи редактируют и сохраняют контакт, когда они нажимают «Назад», они видят экран списка контактов. Чтобы вернуться к вашему приложению, им нужно нажать «Недавние» и выбрать ваше приложение.

Чтобы обойти эту проблему в Android 4.0.3 (API версии 15) и более поздних версиях, добавьте к намерению расширенный ключ данных finishActivityOnSaveCompleted со значением true . Версии Android до Android 4.0 принимают этот ключ, но он не имеет никакого эффекта. Чтобы установить расширенные данные, выполните следующие действия:

Котлин

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

Ява

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

Добавить другие расширенные данные

Чтобы добавить дополнительные расширенные данные в Intent , вызовите putExtra() по желанию. Вы можете добавить расширенные данные для общих полей контактов, используя значения ключей, указанные в Intents.Insert . Помните, что некоторые столбцы в таблице ContactsContract.Contacts нельзя изменить. Эти столбцы перечислены в сводном разделе справочника по API для класса ContactsContract.Contacts под заголовком «Обновление».

Отправить намерение

Наконец, отправьте созданное вами намерение. Например:

Котлин

    // Sends the Intent
    startActivity(editIntent)

Ява

    // Sends the Intent
    startActivity(editIntent);

Разрешить пользователям выбирать вставку или редактирование с использованием намерения

Вы можете разрешить пользователям выбирать, вставлять ли контакт или редактировать существующий, отправив Intent с помощью действия ACTION_INSERT_OR_EDIT . Например, приложение-клиент электронной почты может позволить пользователям добавлять адрес входящей электронной почты к новому контакту или добавлять его в качестве дополнительного адреса для существующего контакта. Установите тип MIME для этого намерения Contacts.CONTENT_ITEM_TYPE , но не задавайте URI данных.

Когда вы отправляете это намерение, приложение контактов отображает список контактов. Пользователи могут либо вставить новый контакт, либо выбрать существующий контакт и отредактировать его. Любые расширенные поля данных, которые вы добавляете в намерение, заполняют появившийся экран. Вы можете использовать любое из значений ключа, указанных в Intents.Insert . В следующем фрагменте кода показано, как создать и отправить намерение:

Котлин

    // 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)

Ява

    // 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);