Афоризм
Да, невесёлым получился некролог.
Наталья Резник
Последние статьи

 • RawContacts
Необработанные контакты в Android
 • javax.crypto.Cypher
Cимметричное шифрование и дешифрирование
 • Random, Math.random
Генерация случайных чисел
 • Компонент JDatePicker
Описание и пример компонента JDatePicker
 • Компонент Tree
Описание и пример дерева Tree библиотеки base-gui
 • Grid с навигатором
Описание и пример Gridp с навигатором
 • Компонент Grid
Описание и пример Grid библиотеки base-gui
 • Библиотека base-gui
Описание компонентов библиотеки base-gui
 • Оператор SELECT
Использование SQL-оператора SELECT

Основы Contacts API в Android

Интерфейс работы с контактами изменился начиная с 5-ой версии API Android SDK : провайдер Contacts и все его составляющие получили статус @Deprecated. Теперь за работу с контактами отвечает провайдер ContactsContract, который внёс изменения в структуру хранения контактов, более адаптированную для Android устройств, позволяющую хранить контакты из разных источников и предоставлять их пользователю как единую сущность. В настоящее время объект описания контакта на мобильном устройстве включает не только имя и номер телефона, но и Email, Twitter, Facebook и т.д. Новый ContactsContract API позволяет системе агрегировать похожие контакты и выдавать их пользователю в одной записи, а также связывать контакт с разного рода данными.

Пользовательские данные хранятся в центральном репозитории устройства, которым управляет поставщик контактов — эффективный и гибкий компонент Android. Поставщик контактов — это источник данных, которые отображаются в приложении «Контакты» на Вашем устройстве.

Структура поставщика контактов

Поставщик контактов содержит в себе три типа данных о пользователе, как это представлено на рисунке. Каждый тип данных хранится в отдельной таблице :

В качестве наименований таблиц обычно используются названия соответствующих классов-контрактов ContactsContract. Эти классы определяют константы для URI контента, названий столбцов и значений в столбцах этих таблиц :

ContactsContract.Contacts
Строки в таблице Contacts содержат данные о пользователях, полученные путем агрегации строк необработанных контактов.

ContactsContract.RawContacts
Строки в таблице RawContacts содержат сводные данные о пользователях, относящиеся к пользовательским учетным записям и их типам.

ContactsContract.Data
Строки в таблице Data содержат сведения о необработанных контактах, например email или номера телефонов.

Имеются и другие таблицы, представленные классами-контрактами ContactsContract и представляющие собой вспомогательные таблицы. Эти таблицы поставщик контактов использует для управления своими операциями и поддержки определенных функций, имеющихся в приложении устройства «Контакты» или приложениях для телефонной связи.

Разрешения на доступ к поставщику контактов

Приложения, которым требуется доступ к поставщику контактов для чтения или записи, должны определить разрешения в файле манифеста приложения :


// Доступ на чтение записей
<uses-permission 
    android:name="android.permission.READ_CONTACTS">

// Доступ на внесение и обновление записей
<uses-permission 
    android:name="android.permission.WRITE_CONTACTS">
 

Профиль пользователя

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

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

Строка контактов профиля связана со строкой необработанных контактов в каждой из систем, в которой используется профиль. В каждой строке необработанного контакта профиля может содержаться несколько строк данных. Константы для доступа к профилю пользователя представлены в классе ContactsContract.Profile.

Для доступа к профилю пользователя требуются отдельные разрешения. Наряду с разрешениями READ_CONTACTS и WRITE_CONTACTS (чтение и запись контакта) для доступа к профилю пользователя необходимы разрешения android.Manifest.permission#READ_PROFILE и android.Manifest.permission#WRITE_PROFILE на чтение и запись соответственно.

Помните, что профиль пользователя представляет собой конфиденциальную информацию. При запросе доступа к личной информации на устройстве пользователя обязательно укажите, для чего вам требуется доступ к профилю пользователя.

// Определение полей для чтения профиля
mProjection = new String[] {
    Profile._ID,
    Profile.DISPLAY_NAME_PRIMARY,
    Profile.LOOKUP_KEY,
    Profile.PHOTO_THUMBNAIL_URI
};

// Чтение профиля поставщика контактов
mProfileCursor = getContentResolver().query(
                        Profile.CONTENT_URI,
                        mProjection,
                        null,
                        null,
                        null);

Примечание : если при получении нескольких строк контактов необходимо определить, какая из них является профилем пользователя, анализируйте значение столбца IS_USER_PROFILE этой строки. Для профиля пользователя значение должно быть «1».

Пример чтения контактов

Рассмотрим простой пример чтения списка контактов и вывода их в журнал Log. Ниже представлен листинг метода onCreate главного модуля приложения MainActivity.

public class MainActivity extends AppCompatActivity
{
    private final String   TAG = "CONTACT";
    private final int PERMISSIONS_REQUEST_READ_CONTACTS = 10;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Проверка разрешения
        if (ContextCompat.checkSelfPermission(this, 
                        Manifest.permission.READ_CONTACTS) == 
                        PackageManager.PERMISSION_GRANTED)
        {
            // Разрешения чтения контактов имеются
            Log.d(TAG, "Permission is granted");
            readContacts(this);
        } else {
            // Разрешений нет
            Log.d(TAG, "Permission is not granted");

            // Запрос разрешений
            Log.d(TAG, "Request permissions");

            ActivityCompat.requestPermissions(this,
                                     new String[]{
                                     Manifest.permission
                                             .READ_CONTACTS},
                          PERMISSIONS_REQUEST_READ_CONTACTS);
        }
    }
}

Перед выполнением запроса проверим, имеются ли у нас необходимые разрешения на доступ к контактам. Для этого используем метод ContextCompat.checkSelfPermission, которому в качестве параметров передадим контекст модуля и идентификатор разрешений списка контактов. Если приложение имеет разрешения (permission), то метод вернет значение PERMISSION_GRANTED, в противном случае PERMISSION_DENIED.

При наличии необходимых разрешений вызываем метод чтения контактов readContacts, представленный ниже. В противном случае запросим необходимые разрешения методом ActivityCompat.requestPermissions, которому в качестве параметров необходимо передать контекст модуля, список запрашиваемых разрешений и «определенную в модуле константу» (PERMISSIONS_REQUEST_READ_CONTACTS).

Примечание : при запросе приложением «разрешения» методом requestPermissions(), система открывает стандартное диалоговое окно подтверждения доступа. Приложение не может изменить интерфейс диалогового окна. Если имеется необходимость представить пользователю дополнительную информацию, то это желательно сделать перед открытием окна запроса подтверждения. После запроса первого подтверждения и получения положительного ответа система запоминает результат ответа и больше не открывает окно подтверждения доступа.

Результат выполнения запроса на получение разрешений система возвращает вызовом callback метода onRequestPermissionsResult, листинг которого представлен ниже.

Листинг callback метода запроса разрешений

Система вызывает callback метод onRequestPermissionsResult при запросе разрешений методом requestPermissions. В качестве параметров методу передается массив запрошенных permissions и массив разрешений grantResults.

В примере проверяем результат полученного от системы ответа. При наличии необходимых разрешений вызывается метод readContacts.

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String[] permissions,
                                       int[] grantResults)
{
    switch (requestCode) {
        case PERMISSIONS_REQUEST_READ_CONTACTS : {
            // При отмене запроса массив результатов пустой
            if ((grantResults.length > 0) && 
                       (grantResults[0] == 
                        PackageManager.PERMISSION_GRANTED)) {
                // Разрешения получены
                Log.d(TAG, "Permission was granted!");

                // Чтение контактов
                readContacts(this);
            } else {
                // Разрешения НЕ получены. 
                Log.d(TAG, "Permission denied!");
            }
            return;
        }
        // другой 'case' получения permissions
    }
}

Листинг метода чтения контактов

Метод чтения контактов readContacts в качестве параметра получает контекст приложения, используемый для вызова метода getContentResolver().query и получения результата в виде курсора. Если курсор содержит список контактов, то метод в цикле перебирает этот список и выводит в Log параметры контактов (id, name, phone). Метод можно доработать, чтобы он возвращал список контактов в виде List<Contact>.

private void readContacts(Context context)
{
    Contact contact;
    Cursor cursor=context.getContentResolver().query(
                    ContactsContract.Contacts.CONTENT_URI,
                    null, null, null, null);

    if(cursor.getCount() > 0) {
        while(cursor.moveToNext()) {
            contact = new Contact();
            String id = cursor.getString(
                             cursor.getColumnIndex(
                             ContactsContract.Contacts._ID));
            contact.setId(id);

            String name = cursor.getString(
                             cursor.getColumnIndex(
                             ContactsContract.Contacts
                                             .DISPLAY_NAME));
            contact.setName(name);

            String has_phone = cursor.getString(
                                  cursor.getColumnIndex(
                                  ContactsContract.Contacts
                                         .HAS_PHONE_NUMBER))
            if (Integer.parseInt(has_phone) > 0) {
                // extract phone number
                Cursor pCur;
                pCur = context.getContentResolver().query(
                          ContactsContract.CommonDataKinds
                                          .Phone.CONTENT_URI,
                          null,
                          ContactsContract.CommonDataKinds
                                   .Phone.CONTACT_ID + " = ?",
                          new String[]{id},
                          null);
                while(pCur.moveToNext()) {
                    String phone = pCur.getString(
                                   pCur.getColumnIndex(
                                      ContactsContract.
                                         CommonDataKinds.
                                               Phone.NUMBER));
                   contact.setPhone(phone);
                }
                pCur.close();
            }
            Log.d(TAG, "Contact id="  + contact.getId()    + 
                           ", name="  + contact.getName () +
                           ", phone=" + contact.getPhone());
        }
    }
}

Листинг класса Contact

Класс описания контакта, используемого в методе чтения контактов устройства.

public class Contact
{
    private String id;
    private String name  = "";
    private String phone = "";

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}

Связанные страницы

Отладка приложения, Logcat
Необработанные контакты

  Рейтинг@Mail.ru