Добавление контактов

Последнее обновление: 18.10.2021

Продолжим работу с проектом из прошлой темы и добавим в него возможность добавления новых контактов. Добавление контактов представляет собой запрос на изменение списка контактов, то есть его запись. Поэтому нам надо установить соответствующее разрешение в файле манифеста. Возьмем проект из прошлой темы и добавим в него в файл AndroidManifest.xml разрешение android.permission.WRITE_CONTACTS:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.contactsapp">
	
    <uses-permission android:name="android.permission.READ_CONTACTS"  />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ContactsApp">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Для добавления контакта добавим изменим файл activity_main.xml, определив в нем текстовое поле для ввода данных:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/newContact"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@id/header"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/addBtn"
        app:layout_constraintTop_toTopOf="parent" />
    <Button
        android:id="@+id/addBtn"
        android:text="Add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onAddContact"
        app:layout_constraintBottom_toTopOf="@id/header"
        app:layout_constraintLeft_toRightOf="@id/newContact"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/header"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Контакты"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@id/contactList"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/newContact" />

    <ListView
        android:id="@+id/contactList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/header" />

</androidx.constraintlayout.widget.ConstraintLayout>

В коде MainActivity пропишем обработчик onAddContact с добавлением контакта:

package com.example.contactsapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE_READ_CONTACTS=1;
    private static boolean READ_CONTACTS_GRANTED =false;
    ArrayList<String> contacts = new ArrayList<>();
    Button addBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        addBtn = findViewById(R.id.addBtn);
        // получаем разрешения
        int hasReadContactPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
        // если устройство до API 23, устанавливаем разрешение
        if(hasReadContactPermission == PackageManager.PERMISSION_GRANTED){
            READ_CONTACTS_GRANTED = true;
        }
        else{
            // вызываем диалоговое окно для установки разрешений
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_READ_CONTACTS);
        }
        // если разрешение установлено, загружаем контакты
        if (READ_CONTACTS_GRANTED){
            loadContacts();
        }

        addBtn.setEnabled(READ_CONTACTS_GRANTED);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){

		super.onRequestPermissionsResult(requestCode, permissions, grantResults);
		
        if (requestCode == REQUEST_CODE_READ_CONTACTS) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                READ_CONTACTS_GRANTED = true;
            }
            addBtn.setEnabled(READ_CONTACTS_GRANTED);
        }
        if(READ_CONTACTS_GRANTED){
            loadContacts();
        }
        else{
            Toast.makeText(this, "Требуется установить разрешения", Toast.LENGTH_LONG).show();
        }
    }
    public void onAddContact(View v) {
        ContentValues contactValues = new ContentValues();
        EditText contactText = findViewById(R.id.newContact);
        String newContact = contactText.getText().toString();
        contactText.setText("");
        contactValues.put(ContactsContract.RawContacts.ACCOUNT_NAME, newContact);
        contactValues.put(ContactsContract.RawContacts.ACCOUNT_TYPE, newContact);
        Uri newUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, contactValues);
        long rawContactsId = ContentUris.parseId(newUri);
        contactValues.clear();
        contactValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactsId);
        contactValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
        contactValues.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, newContact);
        getContentResolver().insert(ContactsContract.Data.CONTENT_URI, contactValues);
        Toast.makeText(getApplicationContext(), newContact + " добавлен в список контактов", Toast.LENGTH_LONG).show();
        loadContacts();
    }
    private void loadContacts(){
        contacts.clear();
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        if(cursor!=null){
            while (cursor.moveToNext()) {

                // получаем каждый контакт
                String contact = cursor.getString(
                        cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
                // добавляем контакт в список
                contacts.add(contact);
            }
            cursor.close();
        }
        // создаем адаптер
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                android.R.layout.simple_list_item_1, contacts);
        // устанавливаем для списка адаптер
        ListView contactList = findViewById(R.id.contactList);
        contactList.setAdapter(adapter);
    }
}

Сразу стоит отметить, что для работы с контактами не надо отдельно получать разрешения на чтение и отдельно на изменение контактов. Пользователь один раз согласие для установки сразу двух разрешений. Однако на уровне кода нам необходимо перечислить через запятую устанавливаемые разрешения:

 // вызываем диалоговое окно для установки разрешений
ActivityCompat.requestPermissions(this, new String[]{
		Manifest.permission.READ_CONTACTS, 
		Manifest.permission.WRITE_CONTACTS
	}, 
	REQUEST_CODE_READ_CONTACTS);

Однако мы опять же можем управлять разрешением, например, установить доступность кнопки:

addBtn.setEnabled(READ_CONTACTS_GRANTED);

Если разрешение не получено, то переменная READ_CONTACTS_GRANTED будет иметь значение false, и соответственно кнопка будет недоступна, и мы не сможем добавить новый контакт.

Весь код добавления находится в обработчике нажатия кнопки onAddContact. В Android контакты распределяются по трем таблицам: contacts, raw contacts и data. И нам надо добавить новый контакт в две последне таблицы. В таблицу contact в силу настроек мы добавить не можем, но это и не нужно.

Данные контакта представляют объект ContentValues, который состоит из ключей и их значений, то есть объект словаря. После его создания происходит добавление в него пары элементов:

contactValues.put(RawContacts.ACCOUNT_NAME, newContact);
contactValues.put(RawContacts.ACCOUNT_TYPE, newContact);

Здесь устанавливается название и тип контакта. В качестве ключей выставляются значения RawContacts.ACCOUNT_NAME и RawContacts.ACCOUNT_TYPE, а в качестве их значения - текст из текстового поля.

Далее этот объект добавляется в таблицу RawContacts с помощью метода insert():

Uri newUri = getContentResolver().insert(RawContacts.CONTENT_URI, contactValues);

Метод insert() возвращает URI - ссылку на добавленный объект в таблице, у которого мы можем получить id. Затем после очистки мы подготавливаем объект для доабвления в таблицу Data, вновь наполняя его данными:

contactValues.put(Data.RAW_CONTACT_ID, rawContactsId);
contactValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
contactValues.put(StructuredName.DISPLAY_NAME, newContact);

И опять добавление производит метод insert():

getContentResolver().insert(Data.CONTENT_URI, contactValues);

Перед запуском, если ранее (в прошлой теме) приложение было установлено, то его необходимо удалить, чтобы установить для приложения новые разрешения (разрешение на запись контактов).

Запустим приложение и добавим новый контакт:

Новый контакт в Android
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850