Додавання контактів
Продовжимо роботу з проектом з минулої теми і додамо в нього можливість додавання нових контактів. Додавання контактів являє собою запит на зміну списку контактів, тобто його запис. Тому нам треба встановити відповідний дозвіл у файлі маніфесту. Візьмемо проєкт із минулої теми і додамо в нього у файл 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 із додаванням контакту:
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);
Перед запуском, якщо раніше (у минулій темі) застосунок було встановлено, то його необхідно видалити, щоб встановити для застосунку нові дозволи (дозвіл на запис контактів).
Запустимо додаток і додамо новий контакт:
