Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách đọc tất cả liên hệ (Contacts) trong Android

Giới thiệu

Hướng dẫn truy xuất danh sách toàn bộ liên hệ từ ContactsContract ContentProvider, bao gồm tên và số điện thoại, với xử lý quyền runtime (Android 6.0+).

Các bước thực hiện

Bước 1: Tạo dự án & Giao diện

Layout: ListView hiển thị tên liên hệ.

Bước 2: AndroidManifest.xml - Khai báo quyền

<uses-permission android:name="android.permission.READ_CONTACTS" />

Bước 3: MainActivity.java

package com.example.myapplication;

import android.Manifest;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_READ_CONTACTS = 79;
    ListView listView;
    ArrayList<String> contactNames;

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

        listView = findViewById(R.id.list);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                == PackageManager.PERMISSION_GRANTED) {
            loadContacts();
        } else {
            requestPermission();
        }
    }

    private void loadContacts() {
        contactNames = getAllContactNames();
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                android.R.layout.simple_list_item_1, contactNames);
        listView.setAdapter(adapter);
    }

    private void requestPermission() {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == REQUEST_READ_CONTACTS) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                loadContacts();
            } else {
                // Xử lý từ chối quyền
            }
        }
    }

    private ArrayList<String> getAllContactNames() {
        ArrayList<String> names = new ArrayList<>();
        ContentResolver cr = getContentResolver();

        // Chỉ lấy các cột cần thiết để tối ưu hiệu suất
        String[] projection = {
                ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.Contacts.HAS_PHONE_NUMBER
        };

        Cursor cursor = cr.query(
                ContactsContract.Contacts.CONTENT_URI,
                projection, null, null,
                ContactsContract.Contacts.DISPLAY_NAME + " ASC");

        if (cursor != null && cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                String name = cursor.getString(
                        cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                names.add(name);
            }
            cursor.close();
        }
        return names;
    }
}

Mở rộng: Lấy cả số điện thoại

Nếu cần số điện thoại, truy vấn thêm bảng ContactsContract.CommonDataKinds.Phone:

private void loadContactsWithPhones() {
    ContentResolver cr = getContentResolver();
    String[] projection = {
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME
    };

    Cursor contactCursor = cr.query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null);

    if (contactCursor != null) {
        while (contactCursor.moveToNext()) {
            String id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID));
            String name = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

            // Truy vấn số điện thoại của contact này
            Cursor phoneCursor = cr.query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                    new String[]{id}, null);

            if (phoneCursor != null) {
                while (phoneCursor.moveToNext()) {
                    String phone = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    // Lưu cặp name-phone vào model/list
                }
                phoneCursor.close();
            }
        }
        contactCursor.close();
    }
}

Tối ưu hiệu suất (Best Practices)

  • Chỉ query các cột cần thiết (projection).
  • Dùng CursorLoader (deprecated) hoặc ContentResolver.query() trên background thread (RxJava, Coroutines, Executor).
  • Phân trang (pagination) nếu danh sách lớn.
  • Cache kết quả nếu không thay đổi thường xuyên.

Chạy ứng dụng

Nhấn Run. Cấp quyền READ_CONTACTS → ListView hiển thị tất cả tên liên hệ.

Cách đọc tất cả liên hệ (Contacts) trong Android

Lưu ý phiên bản Android

  • Android 6.0+ (API 23): Bắt buộc xin quyền runtime.
  • Android 10+ (API 29): Cần quyền READ_PRIVILEGED_PHONE_STATE cho một số trường nhạy cảm.
  • Android 11+ (API 30): Package visibility - thêm <queries> trong Manifest nếu dùng Intent.