lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Trình cung cấp Danh bạ

Trình cung cấp Danh bạ là một thành phần Android mạnh mẽ và linh hoạt có chức năng quản lý kho dữ liệu trung tâm về con người của thiết bị. Trình cung cấp Danh bạ là nguồn của những dữ liệu mà bạn thấy trong ứng dụng danh bạ của thiết bị, và bạn cũng có thể truy cập dữ liệu của nó trong ứng dụng của chính mình và chuyển dữ liệu giữa thiết bị và các dịch vụ trực tuyến. Trình cung cấp chứa đủ loại nguồn dữ liệu và cố gắng quản lý nhiều dữ liệu nhất có thể cho mỗi người, kết quả là tổ chức của nó trở nên phức tạp. Vì điều này, API của trình cung cấp bao gồm một tập mở rộng gồm các lớp hợp đồng và giao diện tạo điều kiện cho việc truy xuất và sửa đổi dữ liệu.

Hướng dẫn này trình bày những nội dung sau:

  • Cấu trúc cơ bản của trình cung cấp.
  • Cách truy xuất dữ liệu từ trình cung cấp.
  • Cách sửa đổi dữ liệu trong trình cung cấp.
  • Cách ghi một trình điều hợp đồng bộ để đồng bộ hóa dữ liệu từ máy chủ của bạn với Trình cung cấp Danh bạ.

Hướng dẫn này giả sử rằng bạn biết những nội dung cơ bản về trình cung cấp nội dung Android. Để tìm hiểu thêm về trình cung cấp nội dung Android, hãy đọc hướng dẫn Nội dung Cơ bản về Trình cung cấp Nội dung. Ứng dụng mẫu Trình điều hợp Đồng bộ Mẫu là một ví dụ về cách sử dụng một trình điều hợp đồng bộ để chuyển dữ liệu giữa Trình cung cấp Danh bạ và ứng dụng mẫu được lưu trữ bởi Dịch vụ Web Google.

Tổ chức Trình cung cấp Danh bạ

Trình cung cấp Danh bạ là một thành phần của trình cung cấp nội dung Android. Nó chứa ba loại dữ liệu về một người, từng loại tương ứng với một bảng do trình cung cấp đưa ra, như được minh họa trong hình 1:

Hình 1. Cấu trúc bảng của Trình cung cấp Danh bạ.

Ba bảng này thường được đề cập theo tên các lớp hợp đồng của chúng. Các lớp này sẽ định nghĩa các hằng số cho URI nội dung, tên cột và giá trị cột được sử dụng bởi các bảng:

Bảng ContactsContract.Contacts
Hàng thể hiện những người khác nhau dựa trên tổng hợp của các hàng liên lạc thô.
Bảng ContactsContract.RawContacts
Hàng chứa một bản tổng hợp dữ liệu về một người, liên quan tới tài khoản và loại người dùng.
Bảng ContactsContract.Data
Hàng chứa các thông tin chi tiết về liên lạc thô, chẳng hạn như địa chỉ e-mail hoặc số điện thoại.

Các bảng khác được đại diện bởi các lớp hợp đồng trong ContactsContract là bảng phụ mà Trình cung cấp Danh bạ sử dụng để quản lý thao tác của nó hoặc hỗ trợ các chức năng cụ thể trong ứng dụng danh bạ hoặc điện thoại của thiết bị.

Liên lạc thô

Một liên lạc thô thể hiện dữ liệu của một người xuất phát từ một loại tài khoản và tên tài khoản riêng. Vì Trình cung cấp Danh bạ cho phép nhiều hơn một dịch vụ trực tuyến làm nguồn dữ liệu cho một người, Trình cung cấp Danh bạ cho phép nhiều liên lạc thô cho cùng một người. Nhiều liên lạc thô cũng cho phép người dùng kết hợp dữ liệu của một người từ nhiều hơn một tài khoản từ cùng loại tài khoản.

Hầu hết dữ liệu của một liên lạc thô không được lưu giữ trong bảng ContactsContract.RawContacts. Thay vào đó, nó được lưu giữ trong một hoặc nhiều hàng trong bảng ContactsContract.Data. Mỗi hàng dữ liệu có một cột Data.RAW_CONTACT_ID chứa giá trị android.provider.BaseColumns#_ID RawContacts._ID của hàng ContactsContract.RawContacts mẹ của nó.

Các cột liên lạc thô quan trọng

Các cột quan trọng trong bảng ContactsContract.RawContacts được liệt kê trong bảng 1. Hãy đọc các lưu ý theo sau bảng dưới đây:

Bảng 1. Các cột liên lạc thô quan trọng.

Tên cột Sử dụng Lưu ý
ACCOUNT_NAME Tên tài khoản cho loại tài khoản là nguồn của liên lạc thô này. Ví dụ, tên tài khoản của một tài khoản Google là một trong các địa chỉ Gmail của chủ sở hữu thiết bị. Xem mục nhập tiếp theo cho ACCOUNT_TYPE để biết thêm thông tin. Định dạng của tên này áp dụng theo loại tài khoản của nó. Đó không nhất thiết là một địa chỉ e-mail.
ACCOUNT_TYPE Loại tài khoản là nguồn của liên lạc thô này. Ví dụ, loại tài khoản của một tài khoản Google là com.google. Luôn xác định loại tài khoản của bạn bằng một mã định danh miền cho một miền mà bạn sở hữu hoặc kiểm soát. Điều này đảm bảo rằng loại tài khoản của bạn là duy nhất. Một loại tài khoản cung cấp dữ liệu danh bạ thường có một trình điều hợp đồng bộ liên kết để đồng bộ hoá với Trình điều hợp Đồng bộ.
DELETED Cờ "đã xóa" cho một liên lạc thô. Cờ này cho phép Trình cung cấp Danh bạ duy trì hàng bên trong tới khi trình điều hợp đồng bộ có thể xóa hàng đó khỏi máy chủ của chúng rồi cuối cùng là xóa hàng khỏi kho lưu giữ.

Lưu ý

Sau đây là các ghi chú quan trọng về bảng ContactsContract.RawContacts:

  • Tên của liên lạc thô không được lưu giữ trong hàng của nó trong ContactsContract.RawContacts. Thay vào đó, nó được lưu giữ trong bảng ContactsContract.Data, trong một hàng ContactsContract.CommonDataKinds.StructuredName. Liên lạc thô chỉ có một hàng thuộc loại này trong bảng ContactsContract.Data.
  • Chú ý: Để sử dụng dữ liệu tài khoản của chính bạn trong một hàng liên lạc thô, trước tiên dữ liệu phải được đăng ký với AccountManager. Để làm điều này, hãy nhắc người dùng thêm loại tài khoản và tên tài khoản của chúng vào danh sách tài khoản. Nếu bạn không làm vậy, Trình cung cấp Danh bạ sẽ tự động xóa hàng liên lạc thô của bạn.

    Ví dụ, nếu bạn muốn ứng dụng của mình duy trì dữ liệu danh bạ cho dịch vụ dựa trên nền web của mình với miền com.example.dataservice, và tài khoản của người dùng cho dịch vụ của bạn là becky.sharp@dataservice.example.com, trước tiên, người dùng phải thêm "loại" tài khoản (com.example.dataservice) và "tên" tài khoản (becky.smart@dataservice.example.com) trước khi ứng dụng của bạn có thể thêm hàng liên lạc thô. Bạn có thể giải thích yêu cầu này với người dùng bằng tài liệu, hoặc bạn có thể nhắc người dùng thêm loại và tên này, hoặc cả hai. Loại tài khoản và tên tài khoản được trình bày chi tiết hơn trong phần sau.

Các nguồn dữ liệu liên lạc thô

Để hiểu cách hoạt động của liên lạc thô, hãy xét người dùng "Emily Dickinson", cô ta có ba tài khoản người dùng sau được xác định trên thiết bị của mình:

  • emily.dickinson@gmail.com
  • emilyd@gmail.com
  • Tài khoản Twitter "belle_of_amherst"

Người dùng này đã kích hoạt Đồng bộ Danh bạ cho cả ba tài khoản này trong cài đặt Tài khoản.

Giả sử Emily Dickinson mở một cửa sổ trình duyệt, đăng nhập vào Gmail bằng tài khoản emily.dickinson@gmail.com, mở Danh bạ, và thêm "Thomas Higginson". Sau đó, cô đăng nhập vào Gmail bằng tài khoản emilyd@gmail.com và gửi một e-mail tới "Thomas Higginson", làm vậy sẽ tự động thêm người này làm một liên lạc. Cô ấy cũng theo dõi "colonel_tom" (ID Twitter của Thomas Higginson) trên Twitter.

Trình cung cấp Danh bạ sẽ tạo ba liên lạc thô do kết quả của việc làm này:

  1. Một liên lạc thô cho "Thomas Higginson" liên kết với emily.dickinson@gmail.com. Loại tài khoản người dùng là Google.
  2. Một liên lạc thô thứ hai cho "Thomas Higginson" liên kết với emilyd@gmail.com. Loại tài khoản người dùng cũng là Google. Có một liên lạc thô thứ hai ngay cả khi tên giống với một tên trước đó, vì người này đã được thêm cho một tài khoản người dùng khác.
  3. Một liên lạc thô thứ ba cho "Thomas Higginson" liên kết với "belle_of_amherst". Loại tài khoản người dùng là Twitter.

Dữ liệu

Như đề cập trước đó, dữ liệu của một liên lạc thô được lưu giữ trong một hàng ContactsContract.Data được liên kết với giá trị _ID của liên lạc thô. Điều này cho phép một liên lạc thô có nhiều thực thể cùng loại dữ liệu chẳng hạn như địa chỉ e-mail hay số điện thoại. Ví dụ, nếu "Thomas Higginson" của emilyd@gmail.com (hàng liên lạc thô cho Thomas Higginson liên kết với tài khoản Google emilyd@gmail.com) có một địa chỉ e-mail nhà là thigg@gmail.com và một địa chỉ e-mail cơ quan là thomas.higginson@gmail.com, Trình cung cấp Danh bạ sẽ lưu trữ hai hàng địa chỉ e-mail đó và liên kết cả hai với liên lạc thô.

Để ý rằng các loại dữ liệu khác nhau được lưu giữ trong một bảng này. Các hàng tên hiển thị, số điện thoại, e-mail, địa chỉ gửi thư, ảnh và chi tiết trang web đều được tìm thấy trong bảng ContactsContract.Data. Để giúp quản lý điều này, bảng ContactsContract.Data có một số cột có tên mô tả, và các cột còn lại có tên chung. Các nội dung của cột tên mô tả có cùng ý nghĩa không phụ thuộc vào loại dữ liệu trong hàng, trong khi nội dung của cột tên chung có ý nghĩa khác nhau tùy vào loại dữ liệu.

Tên cột mô tả

Một số ví dụ về tên cột mô tả là:

RAW_CONTACT_ID
Giá trị của cột _ID của liên lạc thô đối với dữ liệu này.
MIMETYPE
Loại dữ liệu được lưu giữ trong hàng này, được thể hiện dưới dạng một kiểu MIME tùy chỉnh. Trình cung cấp Danh bạ sử dụng các kiểu MIME được định nghĩa trong lớp con của ContactsContract.CommonDataKinds. Các kiểu MIME là nguồn mở, và có thể được sử dụng bởi bất kỳ ứng dụng hay trình điều hợp đồng bộ nào hoạt động với Trình cung cấp Danh bạ.
IS_PRIMARY
Nếu kiểu hàng dữ liệu này có thể xảy ra nhiều hơn một lần đối với một liên lạc thô, cột IS_PRIMARY sẽ gắn cờ hàng dữ liệu chứa dữ liệu sơ cấp cho kiểu đó. Ví dụ, nếu người dùng nhấn giữ một số điện thoại cho một liên lạc và chọn Đặt mặc định, khi đó hàng ContactsContract.Data chứa số đó có cột tương ứng IS_PRIMARY được đặt thành một giá trị khác 0.

Tên cột chung

Có 15 cột chung được đặt tên DATA1 thông qua DATA15 thường có sẵn và thêm bốn cột chung SYNC1 thông qua SYNC4 mà chỉ được sử dụng bởi trình điều hợp đồng bộ. Các hằng số tên cột chung luôn có tác dụng, không phụ thuộc vào loại dữ liệu mà hàng đó chứa.

Cột DATA1 được đánh chỉ mục. Trình cung cấp Danh bạ luôn sử dụng cột này cho dữ liệu mà trình cung cấp kỳ vọng sẽ là đối tượng truy vấn thường xuyên nhất. Ví dụ, trong một hàng e-mail, cột này chứa địa chỉ e-mail thực sự.

Theo quy ước, cột DATA15 được dành để lưu giữ dữ liệu Binary Large Object (BLOB) chẳng hạn như hình thu nhỏ của ảnh.

Tên cột theo kiểu

Để tạo điều kiện làm việc với các cột đối với một kiểu hàng cụ thể, Trình cung cấp Danh bạ cũng cung cấp các hằng số tên cột theo kiểu, được định nghĩa trong các lớp con của ContactsContract.CommonDataKinds. Các hằng số chỉ cấp một tên hằng số khác cho cùng tên cột, điều này giúp bạn truy cập dữ liệu trong một hàng thuộc một kiểu cụ thể.

Ví dụ, lớp ContactsContract.CommonDataKinds.Email định nghĩa các hằng số tên cột theo kiểu cho một hàng ContactsContract.Data mà có kiểu MIME Email.CONTENT_ITEM_TYPE. Lớp chứa hằng số ADDRESS cho cột địa chỉ e-mail. Giá trị thực sự của ADDRESS là "data1", giá trị này giống hệt như tên chung của cột.

Chú ý: Không được thêm dữ liệu tùy chỉnh của chính bạn vào bảng ContactsContract.Data bằng cách sử dụng một hàng có một trong các kiểu MIME được xác định trước của trình cung cấp. Nếu làm vậy, bạn có thể làm mất dữ liệu hoặc khiến trình cung cấp gặp trục trặc. Ví dụ, bạn không nên thêm một hàng có kiểu MIME Email.CONTENT_ITEM_TYPE mà chứa tên người dùng thay vì địa chỉ e-mail trong cột DATA1. Nếu sử dụng kiểu MIME tùy chỉnh của mình cho hàng, khi đó bạn được tự do định nghĩa tên cột theo kiểu của chính mình và sử dụng các cột theo cách bạn muốn.

Hình 2 minh họa cách các cột mô tả và cột dữ liệu xuất hiện trong hàng ContactsContract.Data, và cách mà tên cột theo kiểu "phủ lên" tên cột chung

How type-specific column names map to generic column names

Hình 2. Tên cột theo kiểu và tên cột chung.

Lớp tên cột theo kiểu

Bảng 2 liệt kê các lớp tên cột theo kiểu thường được sử dụng nhất:

Bảng 2. Lớp tên cột theo kiểu

Lớp ánh xạ Kiểu dữ liệu Lưu ý
ContactsContract.CommonDataKinds.StructuredName Dữ liệu tên của liên lạc thô liên kết với hàng dữ liệu này. Một liên lạc thô chỉ có một trong những hàng này.
ContactsContract.CommonDataKinds.Photo Ảnh chính của liên lạc thô được liên kết với hàng dữ liệu này. Một liên lạc thô chỉ có một trong những hàng này.
ContactsContract.CommonDataKinds.Email Địa chỉ e-mail của liên lạc thô được liên kết với hàng dữ liệu này. Một liên lạc thô có thể có nhiều địa chỉ e-mail.
ContactsContract.CommonDataKinds.StructuredPostal Địa chỉ cổng của liên lạc thô được liên kết với hàng dữ liệu này. Một liên lạc thô có thể có nhiều địa chỉ cổng.
ContactsContract.CommonDataKinds.GroupMembership Mã định danh liên kết liên lạc thô với một trong các nhóm trong Trình cung cấp Danh bạ. Nhóm là một tính năng tùy chọn của loại tài khoản và tên tài khoản. Chúng được mô tả chi tiết hơn trong phần Nhóm liên lạc.

Danh bạ

Trình cung cấp Danh bạ kết hợp các hàng liên lạc thô giữa tất cả các loại tài khoản và tên tài khoản để tạo thành một liên lạc. Điều này tạo điều kiện để hiển thị và sửa đổi tất cả dữ liệu mà một người dùng đã thu thập cho một người. Trình cung cấp Danh bạ quản lý việc tạo các hàng liên lạc mới và tổng hợp các liên lạc thô với hàng liên lạc hiện có. Ứng dụng lẫn trình điều hợp đồng bộ đều không được cho phép thêm liên lạc và một số cột trong một hàng liên lạc là cột chỉ đọc.

Lưu ý: Nếu bạn cố gắng thêm một liên lạc vào Trình cung cấp Danh bạ có một insert(), bạn sẽ gặp lỗi ngoại lệ UnsupportedOperationException. Nếu bạn cố gắng cập nhật một cột mà được liệt kê là "chỉ đọc," cập nhật sẽ bị bỏ qua.

Trình cung cấp Danh bạ tạo một liên lạc mới để hồi đáp lại việc thêm một liên lạc thô mới không khớp với bất kỳ liên lạc nào hiện có. Trình cung cấp cũng làm vậy nếu dữ liệu của một liên lạc thô hiện có thay đổi sao cho nó không còn khớp với liên lạc mà trước đó nó được gắn với. Nếu một ứng dụng hoặc trình điều hợp đồng bộ tạo một liên lạc thô mới mà khớp với một liên lạc hiện tại, liên lạc thô mới sẽ được tổng hợp vào liên lạc hiện có.

Trình cung cấp Danh bạ sẽ liên kết một hàng liên lạc với các hàng liên lạc thô của nó bằng cột _ID của hàng liên lạc đó trong bảng Contacts . Cột CONTACT_ID của bảng liên lạc thô ContactsContract.RawContacts chứa các giá trị _ID cho các hàng liên lạc liên kết với từng hàng liên lạc thô.

Bảng ContactsContract.Contacts cũng có cột android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY mà là một liên kết "cố định" với hàng liên lạc đó. Vì Trình cung cấp Danh bạ tự động duy trì các liên lạc, nó có thể thay đổi giá trị android.provider.BaseColumns#_ID của một hàng liên lạc hồi đáp lại một sự tổng hợp hoặc đồng bộ. Ngay cả khi điều này xảy ra, URI nội dung CONTENT_LOOKUP_URI kết hợp với android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY của liên lạc sẽ vẫn chỉ về hàng liên lạc đó, vì thế bạn có thể sử dụng android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY để duy trì các liên kết đến liên lạc "yêu thích", v.v. Cột này có định dạng riêng không liên quan tới định dạng của cột android.provider.BaseColumns#_ID.

Hình 3 minh họa mối liên quan giữa ba bảng chính này với nhau.

Contacts provider main tables

Hình 3. Mối quan hệ giữa các bảng Danh bạ, Liên lạc Thô, và Chi tiết.

Dữ liệu từ Trình điều hợp Đồng bộ

Người dùng nhập dữ liệu danh bạ trực tiếp vào thiết bị, nhưng dữ liệu cũng đi đến Trình cung cấp Danh bạ từ các dịch vụ web thông qua trình điều hợp đồng bộ, giúp tự động chuyển dữ liệu giữa thiết bị và các dịch vụ. Trình điều hợp đồng bộ chạy ngầm dưới sự kiểm soát của hệ thống, và chúng gọi các phương pháp ContentResolver để quản lý dữ liệu.

Trong Android, dịch vụ web mà một trình điều hợp đồng bộ làm việc cùng sẽ được xác định bằng một loại tài khoản. Mỗi trình điều hợp đồng bộ làm việc với một loại tài khoản, nhưng nó có thể hỗ trợ nhiều tên tài khoản cho loại đó. Các loại tài khoản và tên tài khoản được mô tả sơ qua trong phần Các nguồn dữ liệu liên lạc thô. Các định nghĩa sau trình bày chi tiết hơn và mô tả mối liên quan giữa loại và tên tài khoản với các trình điều hợp đồng bộ và dịch vụ.

Loại tài khoản
Xác định một dịch vụ mà người dùng đã lưu giữ dữ liệu trong đó. Trong phần lớn thời gian, người dùng phải xác thực dịch vụ. Ví dụ, Google Contacts là một loại tài khoản được xác định bởi mã google.com. Giá trị này tương ứng với loại tài khoản được sử dụng bởi AccountManager.
Tên tài khoản
Xác định một tài khoản hoặc đăng nhập cụ thể cho một loại tài khoản. Tài khoản Google Contacts giống như tài khoản Google, chúng có một địa chỉ e-mail làm tên tài khoản. Các dịch vụ khác có thể sử dụng tên người dùng là một từ hoặc id chữ số.

Loại tài khoản không nhất thiết phải duy nhất. Một người dùng có thể cấu hình nhiều tài khoản Google Contacts và tải xuống dữ liệu của chúng vào Trình cung cấp Danh bạ; điều này có thể xảy ra nếu người dùng có một tập hợp các liên lạc cá nhân cho một tên tài khoản cá nhân, và một tập hợp khác cho cơ quan. Tên tài khoản thường là duy nhất. Cùng nhau, chúng xác định một dòng dữ liệu cụ thể giữa Trình cung cấp Danh bạ và một dịch vụ bên ngoài.

Nếu muốn chuyển dữ liệu từ dịch vụ của bạn sang Trình cung cấp Danh bạ, bạn cần ghi vào trình điều hợp đồng bộ của chính mình. Điều này được mô tả chi tiết hơn trong phần Trình điều hợp Đồng bộ Trình cung cấp Danh bạ.

Hình 4 minh họa cách mà Trình cung cấp Danh bạ phù hợp với dòng dữ liệu về con người. Trong hộp được đánh dấu "trình điều hợp đồng bộ," mỗi trình điều hợp được ghi nhãn theo loại tài khoản của nó.

Flow of data about people

Hình 4. Luồng dữ liệu của Trình cung cấp Danh bạ.

Quyền được Yêu cầu

Những ứng dụng muốn truy cập Trình cung cấp Danh bạ phải yêu cầu các quyền sau:

Quyền truy cập đọc vào một hoặc nhiều bảng
READ_CONTACTS, được quy định trong AndroidManifest.xml với phần tử <uses-permission><uses-permission android:name="android.permission.READ_CONTACTS">.
Quyền truy cập ghi vào một hoặc nhiều bảng
WRITE_CONTACTS, được quy định trong AndroidManifest.xml với phần tử <uses-permission><uses-permission android:name="android.permission.WRITE_CONTACTS">.

Những quyền này không mở rộng sang dữ liệu hồ sơ người dùng. Hồ sơ người dùng và các quyền được yêu cầu được đề cập trong phần sau, Hồ sơ Người dùng.

Nhớ rằng dữ liệu danh bạ của người dùng là dữ liệu cá nhân và nhạy cảm. Người dùng quan tâm về quyền riêng tư của họ, vì thế họ không muốn các ứng dụng thu thập dữ liệu về mình hoặc danh bạ của mình. Nếu không rõ ràng về lý do bạn cần quyền truy cập dữ liệu danh bạ của họ, họ có thể cho ứng dụng của bạn đánh giá thấp hoặc từ chối cài đặt ứng dụng.

Hồ sơ Người dùng

Bảng ContactsContract.Contacts có một hàng đơn chứa dữ liệu hồ sơ cho người dùng của thiết bị. Dữ liệu này mô tả user của thiết bị chứ không phải của một trong các liên lạc của người dùng. Hàng liên lạc hồ sơ được liên kết với hàng liên lạc thô đối với từng hệ thống sử dụng hồ sơ. Mỗi hàng liên lạc thô của hồ sơ có thể có nhiều hàng dữ liệu. Các hằng số để truy cập hồ sơ người dùng có sẵn trong lớp ContactsContract.Profile.

Truy cập hồ sơ người dùng đòi hỏi phải có các quyền đặc biệt. Ngoài các quyền READ_CONTACTSWRITE_CONTACTS cần để đọc và ghi, truy cập hồ sơ người dùng còn yêu cầu quyền android.Manifest.permission#READ_PROFILEandroid.Manifest.permission#WRITE_PROFILE tương ứng cho quyền truy cập đọc và ghi.

Nhớ rằng bạn nên coi hồ sơ của một người dùng là nội dung nhạy cảm. Quyền android.Manifest.permission#READ_PROFILE cho phép bạn truy cập dữ liệu xác định cá nhân của người dùng thiết bị. Chắc chắn phải nói cho người dùng biết lý do tại sao bạn cần các quyền truy cập hồ sơ người dùng trong phần mô tả ứng dụng của mình.

Để truy xuất hàng liên lạc chứa hồ sơ của người dùng, hãy gọi ContentResolver.query(). Đặt URI nội dung thành CONTENT_URI và không cung cấp bất kỳ tiêu chí lựa chọn nào. Bạn cũng có thể sử dụng URI nội dung này làm URI cơ sở để truy xuất các liên lạc thô hoặc dữ liệu cho hồ sơ. Ví dụ, đoạn mã HTML này truy xuất dữ liệu cho hồ sơ:

// Sets the columns to retrieve for the user profile
mProjection = new String[]
    {
        Profile._ID,
        Profile.DISPLAY_NAME_PRIMARY,
        Profile.LOOKUP_KEY,
        Profile.PHOTO_THUMBNAIL_URI
    };

// Retrieves the profile from the Contacts Provider
mProfileCursor =
        getContentResolver().query(
                Profile.CONTENT_URI,
                mProjection ,
                null,
                null,
                null);

Lưu ý: Nếu bạn truy xuất nhiều hàng liên lạc và muốn xác định xem một trong số chúng có phải là hồ sơ người dùng không, hãy kiểm tra cột IS_USER_PROFILE của hàng. Cột này được đặt thành "1" nếu liên lạc là hồ sơ người dùng.

Siêu dữ liệu Trình cung cấp Danh bạ

Trình cung cấp Danh bạ quản lý dữ liệu theo dõi trạng thái của dữ liệu danh bạ trong kho lưu giữ. Siêu dữ liệu về kho lưu giữ này được lưu giữ ở nhiều nơi khác nhau, bao gồm các hàng bảng Liên lạc Thô, Dữ liệu, và Danh bạ, bảng ContactsContract.Settings, và bảng ContactsContract.SyncState. Bảng sau đây cho biết ảnh hưởng của từng mục trong siêu dữ liệu này:

Bảng 3. Siêu dữ liệu trong Trình cung cấp Danh bạ

Bảng Cột Giá trị Ý nghĩa
ContactsContract.RawContacts DIRTY "0" - không thay đổi kể từ lần đồng bộ cuối cùng. Đánh dấu các liên lạc thô đã được thay đổi trên thiết bị và phải được đồng bộ trở lại máy chủ. Giá trị được đặt tự động bởi Trình cung cấp Danh bạ khi các ứng dụng Android cập nhật một hàng.

Các trình điều hợp đồng bộ sửa đổi bảng liên lạc thô hoặc dữ liệu nên luôn nối xâu CALLER_IS_SYNCADAPTER với URI nội dung mà chúng sử dụng. Làm vậy sẽ ngăn không cho trình cung cấp đánh dấu hàng là không tốt. Nếu không, các sửa đổi trình điều hợp đồng bộ xem như sửa đổi cục bộ và được gửi tới máy chủ, ngay cả khi máy chủ là nguồn sửa đổi.

"1" - đã thay đổi kể từ lần đồng bộ cuối cùng, cần được đồng bộ lại máy chủ.
ContactsContract.RawContacts VERSION Số phiên bản của hàng này. Trình cung cấp Danh bạ tự động tăng dần giá trị này bất cứ khi nào hàng hoặc dữ liệu có liên quan của hàng thay đổi.
ContactsContract.Data DATA_VERSION Số phiên bản của hàng này. Trình cung cấp Danh bạ tự động tăng dần giá trị này bất cứ khi nào hàng dữ liệu bị thay đổi.
ContactsContract.RawContacts SOURCE_ID Một xâu giá trị xác định duy nhất liên lạc thô này cho tài khoản mà nó được tạo trong đó. Khi một trình điều hợp đồng bộ tạo một liên lạc thô mới, cột này nên được đặt thành ID duy nhất của máy chủ dành cho liên lạc thô đó. Khi một ứng dụng Android tạo một liên lạc thô mới, ứng dụng đó sẽ để trống cột này. Điều này báo hiệu với trình điều hợp đồng bộ rằng nó nên tạo một liên lạc thô mới trên máy chủ, và lấy một giá trị cho SOURCE_ID.

Cụ thể, id nguồn phải là duy nhất đối với từng loại tài khoản và nên ổn định giữa các lần đồng bộ:

  • Duy nhất: Mỗi liên lạc thô đối với một tài khoản phải có id nguồn riêng của mình. Nếu không thi hành điều này, bạn sẽ gây ra sự cố trong ứng dụng danh bạ. Để ý rằng hai liên lạc thô đối với cùng loại tài khoản có thể có cùng id nguồn. Ví dụ, liên lạc thô "Thomas Higginson" đối với tài khoản emily.dickinson@gmail.com được cho phép có cùng id nguồn như liên lạc thô "Thomas Higginson" đối với tài khoản emilyd@gmail.com.
  • Ổn định: Id nguồn là một bộ phận cố định của dữ liệu từ dịch vụ trực tuyến đối với liên lạc thô. Ví dụ, nếu người dùng xóa Lưu trữ Danh bạ khỏi cài đặt Ứng dụng và đồng bộ lại, các liên lạc thô được khôi phục sẽ có cùng id nguồn như trước. Nếu bạn không thi hành điều này, các lối tắt sẽ dừng hoạt động.
ContactsContract.Groups GROUP_VISIBLE "0" - Các liên lạc trong nhóm này không nên được hiển thị trong UI ứng dụng Android. Cột này dành cho tính tương thích với các máy chủ mà cho phép người dùng ẩn các liên lạc trong một số nhóm.
"1" - Các liên lạc trong nhóm này được cho phép hiển thị trong UI ứng dụng.
ContactsContract.Settings UNGROUPED_VISIBLE "0" - Đối với tài khoản và loại tài khoản này, những liên lạc không thuộc về nhóm được ẩn đối với UI ứng dụng Android. Theo mặc định, các liên lạc được hiển thị nếu không có liên lạc thô nào của chúng thuộc về một nhóm (Tư cách thành viên nhóm đối với một liên lạc thô được thể hiện bằng một hoặc nhiều hàng ContactsContract.CommonDataKinds.GroupMembership trong bảng ContactsContract.Data). Bằng cách đặt cờ này trong hàng bảng ContactsContract.Settings đối với một loại tài khoản và tài khoản, bạn có thể buộc những liên lạc không có nhóm phải hiển thị. Một công dụng của cờ này đó là để hiển thị liên lạc từ các máy chủ không sử dụng nhóm.
"1" - Đối với tài khoản và loại tài khoản này, những liên lạc không thuộc về nhóm sẽ được hiển thị đối với UI ứng dụng.
ContactsContract.SyncState (tất cả) Sử dụng bảng này để lưu giữ siêu dữ liệu cho trình điều hợp đồng bộ của bạn. Với bảng này, bạn có thể lưu giữ trạng thái đồng bộ và các dữ liệu khác liên quan tới đồng bộ một cách lâu dài trên thiết bị.

Truy cập Trình cung cấp Danh bạ

Phần này mô tả các hướng dẫn về truy cập dữ liệu từ Trình cung cấp Danh bạ, tập trung vào những nội dung sau:

  • Truy vấn thực thể.
  • Sửa đổi hàng loạt.
  • Truy xuất và sửa đổi bằng ý định.
  • Toàn vẹn dữ liệu.

Thực hiện sửa đổi từ một trình điều hợp đồng bộ cũng được đề cập chi tiết hơn trong phần Trình điều hợp Đồng bộ Trình cung cấp Danh bạ.

Truy vấn thực thể

Vì các bảng của Trình cung cấp Danh bạ được tổ chức theo một phân cấp, thường sẽ hữu ích nếu truy xuất một hàng và tất cả hàng "con" được liên kết với nó. Ví dụ, để hiển thị tất cả thông tin cho một người, bạn có thể muốn truy xuất tất cả hàng ContactsContract.RawContacts đối với một hàng ContactsContract.Contacts đơn, hoặc tất cả hàng ContactsContract.CommonDataKinds.Email đối với một hàng ContactsContract.RawContacts đơn. Để tạo điều kiện cho điều này, Trình cung cấp Danh bạ sẽ cung cấp các cấu trúc thực thể đóng vai trò như liên kết cơ sở dữ liệu giữa các bảng.

Thực thể giống như một bảng bao gồm các cột được chọn từ một bảng mẹ và bảng con của nó. Khi bạn truy vấn một thực thể, bạn cung cấp một dự thảo và các tiêu chí dựa trên các cột có sẵn từ thực thể. Kết quả là một Cursor trong đó chứa một hàng cho từng hàng bảng con được truy xuất. Ví dụ, nếu bạn truy vấn ContactsContract.Contacts.Entity cho một tên liên lạc và tất cả hàng ContactsContract.CommonDataKinds.Email đối với tất cả liên lạc thô cho tên đó, bạn sẽ nhận lại một Cursor chứa một hàng cho mỗi hàng ContactsContract.CommonDataKinds.Email.

Các thực thể sẽ đơn giản hóa việc truy vấn. Bằng cách sử dụng một thực thể, bạn có thể truy xuất ngay lập tức tất cả dữ liệu danh bạ cho một liên lạc hoặc liên lạc thô, thay vì phải truy vấn bảng mẹ trước để nhận một ID, và rồi phải truy xuất bảng con bằng ID đó. Đồng thời, Trình cung cấp Danh bạ xử lý một truy vấn đối với một thực thể trong một giao tác đơn, điều này đảm bảo rằng dữ liệu được truy xuất sẽ được nhất quán trong nội bộ.

Lưu ý: Một thực thể thường không chứa tất cả cột của bảng mẹ và bảng con. Nếu bạn cố gắng làm việc với một tên cột không có trong danh sách các hằng số tên cột đối với thực thể đó, bạn sẽ nhận được một Exception.

Đoạn mã HTML sau cho biết cách truy xuất tất cả hàng liên lạc thô cho một liên lạc. Đoạn mã HTML là bộ phận của một ứng dụng lớn hơn có hai hoạt động, "chính" và "chi tiết". Hoạt động chính hiển thị một danh sách các hàng liên lạc; khi người dùng chọn một hàng, hoạt động sẽ gửi ID của hàng tới hoạt động chi tiết. Hoạt động chi tiết sử dụng ContactsContract.Contacts.Entity để hiển thị tất cả hàng dữ liệu từ tất cả liên lạc thô được liên kết với liên lạc đã chọn.

Đoạn mã HTML này được lấy từ hoạt động "chi tiết":

...
    /*
     * Appends the entity path to the URI. In the case of the Contacts Provider, the
     * expected URI is content://com.google.contacts/#/entity (# is the ID value).
     */
    mContactUri = Uri.withAppendedPath(
            mContactUri,
            ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);

    // Initializes the loader identified by LOADER_ID.
    getLoaderManager().initLoader(
            LOADER_ID,  // The identifier of the loader to initialize
            null,       // Arguments for the loader (in this case, none)
            this);      // The context of the activity

    // Creates a new cursor adapter to attach to the list view
    mCursorAdapter = new SimpleCursorAdapter(
            this,                        // the context of the activity
            R.layout.detail_list_item,   // the view item containing the detail widgets
            mCursor,                     // the backing cursor
            mFromColumns,                // the columns in the cursor that provide the data
            mToViews,                    // the views in the view item that display the data
            0);                          // flags

    // Sets the ListView's backing adapter.
    mRawContactList.setAdapter(mCursorAdapter);
...
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    /*
     * Sets the columns to retrieve.
     * RAW_CONTACT_ID is included to identify the raw contact associated with the data row.
     * DATA1 contains the first column in the data row (usually the most important one).
     * MIMETYPE indicates the type of data in the data row.
     */
    String[] projection =
        {
            ContactsContract.Contacts.Entity.RAW_CONTACT_ID,
            ContactsContract.Contacts.Entity.DATA1,
            ContactsContract.Contacts.Entity.MIMETYPE
        };

    /*
     * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw
     * contact collated together.
     */
    String sortOrder =
            ContactsContract.Contacts.Entity.RAW_CONTACT_ID +
            " ASC";

    /*
     * Returns a new CursorLoader. The arguments are similar to
     * ContentResolver.query(), except for the Context argument, which supplies the location of
     * the ContentResolver to use.
     */
    return new CursorLoader(
            getApplicationContext(),  // The activity's context
            mContactUri,              // The entity content URI for a single contact
            projection,               // The columns to retrieve
            null,                     // Retrieve all the raw contacts and their data rows.
            null,                     //
            sortOrder);               // Sort by the raw contact ID.
}

Khi hoàn thành việc tải, LoaderManager gọi ra một lệnh gọi lại đến onLoadFinished(). Một trong các tham đối đến với phương pháp này là một Cursor với các kết quả của truy vấn. Trong ứng dụng của chính mình, bạn có thể nhận dữ liệu từ Cursor này để hiển thị nó hoặc thao tác thêm với nó.

Sửa đổi hàng loạt

Bất cứ khi nào có thể, bạn nên chèn, cập nhật và xóa dữ liệu trong Trình cung cấp Danh bạ trong "chế độ hàng loạt", bằng cách tạo một ArrayList của các đối tượng ContentProviderOperation và gọi applyBatch(). Vì Trình cung cấp Danh bạ thực hiện tất cả thao tác trong một applyBatch() trong một giao tác đơn, các sửa đổi của bạn sẽ không bao giờ ra khỏi kho lưu giữ danh bạ một cách không nhất quán. Sửa đổi hàng loạt cũng tạo điều kiện cho việc chèn một liên lạc thô và dữ liệu chi tiết của liên lạc tại cùng thời điểm.

Lưu ý: Để sửa đổi một liên lạc thô đơn, hãy xét gửi một ý định tới ứng dụng danh bạ của thiết bị thay vì xử lý sửa đổi trong ứng dụng của bạn. Việc làm này được mô tả chi tiết hơn trong phần Truy xuất và sửa đổi bằng ý định.

Điểm kết quả

Sửa đổi hàng loạt chứa nhiều thao tác có thể chặn các tiến trình khác, dẫn đến trải nghiệm người dùng tổng thể không tốt. Để sắp xếp tổ chức tất cả sửa đổi mà bạn muốn thực hiện trong ít danh sách riêng nhất có thể, và đồng thời ngăn chúng chặn hệ thống, bạn nên đặt các điểm kết quả cho một hoặc nhiều thao tác. Điểm kết quả là một đối tượng ContentProviderOperation có giá trị isYieldAllowed() được đặt thành true. Khi các Trình cung cấp Danh bạ gặp phải một điểm kết quả, nó tạm dừng công việc để cho phép các tiến trình khác chạy và đóng giao tác hiện tại. Khi trình cung cấp bắt đầu lại, nó tiếp tục với thao tác tiếp theo trong ArrayList và bắt đầu một giao tác mới.

Điểm kết quả dẫn đến có nhiều hơn một giao tác trên mỗi lệnh gọi tới applyBatch(). Vì điều này, bạn nên đặt một điểm kết quả cho thao tác cuối cùng đối với một tập hợp các hàng có liên quan. Ví dụ, bạn nên đặt một điểm kết quả cho thao tác cuối cùng trong một tập hợp mà thêm các hàng liên lạc thô và hàng dữ liệu liên kết của chúng, hoặc thao tác cuối cùng đối với một tập hợp các hàng liên quan tới một liên lạc riêng lẻ.

Điểm kết quả cũng là một đơn vị thao tác nguyên tử. Tất cả truy cập giữa hai điểm kết quả sẽ hoặc thành công hoặc thất bại như một đơn vị riêng lẻ. Nếu bạn không đặt bất kỳ điểm kết quả nào, thao tác nguyên tử nhỏ nhất chính là toàn bộ loạt thao tác. Nếu sử dụng điểm kết quả, bạn ngăn cản các thao tác làm giảm hiệu suất của hệ thống, đồng thời đảm bảo rằng một tập con của thao tác là tập nguyên tử.

Tham chiếu lại sửa đổi

Khi bạn đang chèn một hàng liên lạc thô mới và các hàng dữ liệu liên kết của nó như một tập hợp các đối tượng ContentProviderOperation, bạn phải liên kết các hàng dữ liệu với hàng liên lạc thô bằng cách chèn giá trị android.provider.BaseColumns#_ID của liên lạc thô làm giá trị RAW_CONTACT_ID. Tuy nhiên, giá trị này không có sẵn khi bạn đang tạo ContentProviderOperation cho hàng dữ liệu, vì bạn chưa áp dụng ContentProviderOperation cho hàng liên lạc thô. Để khắc phục điều này, lớp ContentProviderOperation.Builder có phương pháp withValueBackReference(). Phương pháp này cho phép bạn chèn hoặc sửa đổi một cột bằng kết quả của một thao tác trước đó.

Phương pháp withValueBackReference() có hai tham đối:

key
Khóa của một cặp khóa-giá trị. Giá trị của tham đối này nên là tên của một cột trong bảng mà bạn đang sửa đổi.
previousResult
Chỉ mục dựa trên 0 của một giá trị trong mảng đối tượng ContentProviderResult từ applyBatch(). Khi thao tác hàng loạt được áp dụng, kết quả của mỗi thao tác được lưu giữ trong một mảng kết quả trung gian. Giá trị previousResult là chỉ mục của một trong những kết quả này, nó được truy xuất và lưu giữ với giá trị key . Điều này cho phép bạn chèn một bản ghi liên lạc thô mới và nhận lại giá trị android.provider.BaseColumns#_ID của nó, rồi thực hiện một "tham chiếu ngược" về giá trị đó khi bạn thêm một hàng ContactsContract.Data.

Toàn bộ mảng kết quả được tạo khi bạn lần đầu gọi applyBatch(), với kích cỡ bằng với kích cỡ của ArrayList của các đối tượng ContentProviderOperation mà bạn cung cấp. Tuy nhiên, tất cả các phần tử trong mảng kết quả được đặt thành null, và nếu bạn cố gắng thực hiện tham chiếu ngược tới một kết quả cho một thao tác chưa được áp dụng, withValueBackReference() sẽ đưa ra một lỗi Exception.

Các đoạn mã HTML sau minh họa cách chèn một liên lạc thô mới và dữ liệu hàng loạt. Chúng bao gồm mã thiết lập một điểm kết quả và sử dụng một tham chiếu lại. Đoạn mã HTML là một phiên bản mở rộng của phương pháp createContacEntry(), nó là một phần của lớp ContactAdder trong ứng dụng mẫu Contact Manager.

Đoạn mã HTML đầu tiên truy xuất dữ liệu liên lạc từ UI. Tại điểm này, người dùng đã chọn tài khoản mà liên lạc thô mới nên được thêm cho tài khoản đó.

// Creates a contact entry from the current UI values, using the currently-selected account.
protected void createContactEntry() {
    /*
     * Gets values from the UI
     */
    String name = mContactNameEditText.getText().toString();
    String phone = mContactPhoneEditText.getText().toString();
    String email = mContactEmailEditText.getText().toString();

    int phoneType = mContactPhoneTypes.get(
            mContactPhoneTypeSpinner.getSelectedItemPosition());

    int emailType = mContactEmailTypes.get(
            mContactEmailTypeSpinner.getSelectedItemPosition());

Đoạn mã HTML tiếp theo tạo một thao tác để chèn hàng liên lạc thô vào bảng ContactsContract.RawContacts:

    /*
     * Prepares the batch operation for inserting a new raw contact and its data. Even if
     * the Contacts Provider does not have any data for this person, you can't add a Contact,
     * only a raw contact. The Contacts Provider will then add a Contact automatically.
     */

     // Creates a new array of ContentProviderOperation objects.
    ArrayList<ContentProviderOperation> ops =
            new ArrayList<ContentProviderOperation>();

    /*
     * Creates a new raw contact with its account type (server type) and account name
     * (user's account). Remember that the display name is not stored in this row, but in a
     * StructuredName data row. No other data is required.
     */
    ContentProviderOperation.Builder op =
            ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())
            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());

    // Builds the operation and adds it to the array of operations
    ops.add(op.build());

Tiếp theo, mã tạo các hàng dữ liệu cho hàng tên hiển thị, điện thoại và e-mail.

Từng đối tượng bộ dựng thao tác sẽ sử dụng withValueBackReference() để nhận RAW_CONTACT_ID. Tham chiếu đó sẽ trỏ ngược về đối tượng ContentProviderResult từ thao tác đầu tiên, là thao tác thêm hàng liên lạc thô và trả về giá trị android.provider.BaseColumns#_ID mới của nó. Kết quả là, mỗi hàng dữ liệu được tự động liên kết bởi RAW_CONTACT_ID của nó với hàng ContactsContract.RawContacts mới mà nó thuộc về.

Đối tượng ContentProviderOperation.Builder thêm hàng e-mail sẽ được gắn cờ bằng withYieldAllowed(), mà điều này đặt một điểm kết quả:

    // Creates the display name for the new raw contact, as a StructuredName data row.
    op =
            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            /*
             * withValueBackReference sets the value of the first argument to the value of
             * the ContentProviderResult indexed by the second argument. In this particular
             * call, the raw contact ID column of the StructuredName data row is set to the
             * value of the result returned by the first operation, which is the one that
             * actually adds the raw contact row.
             */
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)

            // Sets the data row's MIME type to StructuredName
            .withValue(ContactsContract.Data.MIMETYPE,
                    ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

            // Sets the data row's display name to the name in the UI.
            .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);

    // Builds the operation and adds it to the array of operations
    ops.add(op.build());

    // Inserts the specified phone number and type as a Phone data row
    op =
            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            /*
             * Sets the value of the raw contact id column to the new raw contact ID returned
             * by the first operation in the batch.
             */
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)

            // Sets the data row's MIME type to Phone
            .withValue(ContactsContract.Data.MIMETYPE,
                    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)

            // Sets the phone number and type
            .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
            .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType);

    // Builds the operation and adds it to the array of operations
    ops.add(op.build());

    // Inserts the specified email and type as a Phone data row
    op =
            ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            /*
             * Sets the value of the raw contact id column to the new raw contact ID returned
             * by the first operation in the batch.
             */
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)

            // Sets the data row's MIME type to Email
            .withValue(ContactsContract.Data.MIMETYPE,
                    ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)

            // Sets the email address and type
            .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email)
            .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType);

    /*
     * Demonstrates a yield point. At the end of this insert, the batch operation's thread
     * will yield priority to other threads. Use after every set of operations that affect a
     * single contact, to avoid degrading performance.
     */
    op.withYieldAllowed(true);

    // Builds the operation and adds it to the array of operations
    ops.add(op.build());

Đoạn mã HTML cuối cùng hiển thị lệnh gọi tới applyBatch() mà chèn liên lạc thô mới và các hàng dữ liệu.

    // Ask the Contacts Provider to create a new contact
    Log.d(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +
            mSelectedAccount.getType() + ")");
    Log.d(TAG,"Creating contact: " + name);

    /*
     * Applies the array of ContentProviderOperation objects in batch. The results are
     * discarded.
     */
    try {

            getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
    } catch (Exception e) {

            // Display a warning
            Context ctx = getApplicationContext();

            CharSequence txt = getString(R.string.contactCreationFailure);
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(ctx, txt, duration);
            toast.show();

            // Log exception
            Log.e(TAG, "Exception encountered while inserting contact: " + e);
    }
}

Thao tác hàng loạt cũng cho phép bạn triển khai kiểm soát đồng thời lạc quan, một phương pháp áp dụng các giao tác sửa đổi mà không phải khóa kho lưu giữ liên quan. Để sử dụng phương pháp này, bạn áp dụng giao tác đó rồi kiểm tra các sửa đổi khác mà có thể đã được thực hiện tại cùng thời điểm. Nếu bạn thấy đã diễn ra một sửa đổi không nhất quán, hãy quay lui giao tác của bạn và thử lại.

Kiểm soát đồng thời lạc quan rất hữu ích đối với thiết bị di động, khi đó mỗi lúc chỉ có một người dùng và việc truy cập đồng thời vào một kho lưu giữ dữ liệu hiếm khi xảy ra. Vì không sử dụng khóa nên không bị lãng phí thời gian cho việc thiết đặt khóa hay chờ các giao tác khác nhả khóa của mình.

Để sử dụng kiểm soát đồng thời lạc quan trong khi đang cập nhật một hàng ContactsContract.RawContacts đơn, hãy làm theo các bước sau:

  1. Truy xuất cột VERSION của liên lạc thô cùng với dữ liệu khác mà bạn truy xuất.
  2. Tạo một đối tượng ContentProviderOperation.Builder phù hợp để thi hành một ràng buộc, bằng cách sử dụng phương pháp newAssertQuery(Uri). Đối với URI nội dung, sử dụng RawContacts.CONTENT_URI với android.provider.BaseColumns#_ID của liên lạc thô được nối với nó.
  3. Đối với đối tượng ContentProviderOperation.Builder, hãy gọi withValue() để so sánh cột VERSION với số phiên bản bạn vừa truy xuất.
  4. Đối với cùng ContentProviderOperation.Builder, hãy gọi withExpectedCount() để đảm bảo rằng chỉ một hàng được kiểm tra bằng xác nhận này.
  5. Gọi build() để tạo đối tượng ContentProviderOperation, rồi thêm đối tượng này làm đối tượng đầu tiên trong ArrayList mà bạn chuyển cho applyBatch().
  6. Áp dụng giao tác hàng loạt.

Nếu hàng liên lạc thô được cập nhật bởi một thao tác khác giữa thời điểm bạn đọc hàng và thời điểm bạn cố gắng sửa đổi nó, "xác nhận" ContentProviderOperation sẽ thất bại, và toàn bộ loạt thao tác sẽ được rút khỏi. Sau đó, bạn có thể chọn thử lại loạt hoặc thực hiện một hành động khác.

Đoạn mã HTML sau minh họa cách tạo một "xác nhận" ContentProviderOperation sau khi truy vấn một liên lạc thô đơn bằng cách sử dụng một CursorLoader:

/*
 * The application uses CursorLoader to query the raw contacts table. The system calls this method
 * when the load is finished.
 */
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

    // Gets the raw contact's _ID and VERSION values
    mRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
    mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION));
}

...

// Sets up a Uri for the assert operation
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactID);

// Creates a builder for the assert operation
ContentProviderOperation.Builder assertOp = ContentProviderOperation.netAssertQuery(rawContactUri);

// Adds the assertions to the assert operation: checks the version and count of rows tested
assertOp.withValue(SyncColumns.VERSION, mVersion);
assertOp.withExpectedCount(1);

// Creates an ArrayList to hold the ContentProviderOperation objects
ArrayList ops = new ArrayList<ContentProviderOperationg>;

ops.add(assertOp.build());

// You would add the rest of your batch operations to "ops" here

...

// Applies the batch. If the assert fails, an Exception is thrown
try
    {
        ContentProviderResult[] results =
                getContentResolver().applyBatch(AUTHORITY, ops);

    } catch (OperationApplicationException e) {

        // Actions you want to take if the assert operation fails go here
    }

Truy xuất và sửa đổi bằng ý định

Việc gửi một ý định tới ứng dụng danh bạ của thiết bị cho phép bạn truy cập Trình cung cấp Danh bạ một cách gián tiếp. Ý định sẽ khởi động UI ứng dụng danh bạ của thiết bị, trong đó người dùng có thể thực hiện công việc liên quan tới danh bạ. Với kiểu truy cập này, người dùng có thể:

  • Chọn một liên lạc từ danh sách và trả nó về ứng dụng của bạn để làm việc tiếp.
  • Chỉnh sửa dữ liệu của một liên lạc hiện có.
  • Chèn một liên lạc thô mới cho bất kỳ tài khoản nào của họ.
  • Xóa một liên lạc hoặc dữ liệu danh bạ.

Nếu người dùng đang chèn hoặc cập nhật dữ liệu, bạn có thể thu thập dữ liệu trước và gửi nó như một phần của ý định.

Khi bạn sử dụng ý định để truy cập Trình cung cấp Danh bạ thông qua ứng dụng danh bạ của thiết bị, bạn không phải ghi UI hay mã của chính mình để truy nhập trình cung cấp. Bạn cũng không phải yêu cầu quyền đọc hoặc ghi đến trình cung cấp. Ứng dụng danh bạ của thiết bị có thể cấp quyền đọc đối với một liên lạc cho bạn, và vì bạn đang thực hiện sửa đổi đối với trình cung cấp thông qua một ứng dụng khác, bạn không cần phải có quyền ghi.

Tiến trình chung để gửi một ý định nhằm truy cập một trình cung cấp được mô tả chi tiết trong hướng dẫn Nội dung Cơ bản về Trình cung cấp Nội dung trong phần "Truy cập dữ liệu thông qua ý định." Hành động, kiểu MIME, và các giá trị dữ liệu bạn sử dụng cho các tác vụ có sẵn được tóm tắt trong Bảng 4, trong khi các giá trị phụ thêm mà bạn có thể sử dụng với putExtra() được liệt kê trong tài liệu tham khảo cho ContactsContract.Intents.Insert:

Bảng 4. Ý định của Trình cung cấp Danh bạ.

Tác vụ Hành động Dữ liệu Kiểu MIME Lưu ý
Chọn một liên lạc từ danh sách ACTION_PICK Một trong:
  • Contacts.CONTENT_URI, mà hiển thị một danh sách các liên lạc.
  • Phone.CONTENT_URI, mà hiển thị một danh sách các số điện thoại cho một liên lạc thô.
  • StructuredPostal.CONTENT_URI, mà hiển thị một danh sách các địa chỉ bưu điện cho một liên lạc thô.
  • Email.CONTENT_URI, mà hiển thị một danh sách các địa chỉ e-mail cho một liên lạc thô.
Không sử dụng Hiển thị một danh sách các liên lạc thô hoặc danh sách dữ liệu từ một liên lạc thô, tùy vào kiểu URI nội dung mà bạn cung cấp.

Gọi startActivityForResult(), nó trả về URI nội dung của hàng được chọn. Hình thức của URI là URI nội dung của bảng với LOOKUP_ID của hàng được nối với nó. Ứng dụng danh bạ của thiết bị cấp quyền đọc và ghi cho URI nội dung này trong suốt thời gian hoạt động của bạn. Xem hướng dẫn Nội dung Cơ bản về Trình cung cấp Nội dung để biết thêm chi tiết.

Chèn một liên lạc thô mới Insert.ACTION Không áp dụng RawContacts.CONTENT_TYPE, kiểu MIME cho một tập hợp liên các lạc thô. Hiển thị màn hình Thêm Liên lạc của ứng dụng danh bạ của thiết bị. Các giá trị phụ thêm mà bạn thêm vào ý định sẽ được hiển thị. Nếu được gửi bằng startActivityForResult(), URI nội dung của liên lạc thô mới thêm sẽ được chuyển lại cho phương pháp gọi lại onActivityResult() của hoạt động của bạn trong tham đối Intent, trong trường "dữ liệu". Để nhận giá trị, hãy gọi getData().
Chỉnh sửa một liên lạc ACTION_EDIT CONTENT_LOOKUP_URI đối với liên lạc. Hoạt động của trình chỉnh sửa sẽ cho phép người dùng chỉnh sửa bất kỳ dữ liệu nào được liên kết với liên lạc này. Contacts.CONTENT_ITEM_TYPE, một liên lạc đơn. Hiển thị màn hình Chỉnh sửa Liên lạc trong ứng dụng danh bạ. Các giá trị phụ thêm mà bạn thêm vào ý định sẽ được hiển thị. Khi người dùng nhấp vào Xong để lưu các chỉnh sửa, hoạt động của bạn quay lại tiền cảnh.
Hiển thị một trình chọn mà cũng có thể thêm dữ liệu. ACTION_INSERT_OR_EDIT Không áp dụng CONTENT_ITEM_TYPE Ý định này luôn hiển thị màn hình bộ chọn của ứng dụng danh bạ. Người dùng có thể hoặc chọn một liên lạc để chỉnh sửa, hoặc thêm một liên lạc mới. Hoặc màn hình chỉnh sửa hoặc màn hình thêm sẽ xuất hiện, tùy vào lựa chọn của người dùng, và dữ liệu phụ thêm mà bạn chuyển trong ý định sẽ được hiển thị. Nếu ứng dụng của bạn hiển thị dữ liệu chẳng hạn như e-mail hoặc số điện thoại, hãy sử dụng ý định này để cho phép người dùng thêm dữ liệu vào một liên lạc hiện tại. liên lạc,

Lưu ý: Không cần gửi một giá trị tên trong phần phụ thêm của ý định, vì người dùng luôn chọn một tên hiện có hoặc thêm một tên mới. Thêm nữa, nếu bạn gửi một tên, và người dùng chọn thực hiện chỉnh sửa, ứng dụng danh bạ sẽ hiển thị tên mà bạn gửi, ghi đè giá trị trước. Nếu người dùng không để ý thấy điều này và lưu chỉnh sửa, giá trị cũ sẽ bị mất.

Ứng dụng danh bạ của thiết bị không cho phép bạn xóa một liên lạc thô hay bất kỳ dữ liệu nào bằng một ý định. Thay vào đó, để xóa một liên lạc thô, hãy sử dụng ContentResolver.delete() hoặc ContentProviderOperation.newDelete().

Đoạn mã HTML sau minh họa cách xây dựng và gửi một ý định để chèn một liên lạc thô mới và dữ liệu:

// Gets values from the UI
String name = mContactNameEditText.getText().toString();
String phone = mContactPhoneEditText.getText().toString();
String email = mContactEmailEditText.getText().toString();

String company = mCompanyName.getText().toString();
String jobtitle = mJobTitle.getText().toString();

// Creates a new intent for sending to the device's contacts application
Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION);

// Sets the MIME type to the one expected by the insertion activity
insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

// Sets the new contact name
insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name);

// Sets the new company and job title
insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company);
insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle);

/*
 * Demonstrates adding data rows as an array list associated with the DATA key
 */

// Defines an array list to contain the ContentValues objects for each row
ArrayList<ContentValues> contactData = new ArrayList<ContentValues>();


/*
 * Defines the raw contact row
 */

// Sets up the row as a ContentValues object
ContentValues rawContactRow = new ContentValues();

// Adds the account type and name to the row
rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType());
rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());

// Adds the row to the array
contactData.add(rawContactRow);

/*
 * Sets up the phone number data row
 */

// Sets up the row as a ContentValues object
ContentValues phoneRow = new ContentValues();

// Specifies the MIME type for this data row (all data rows must be marked by their type)
phoneRow.put(
        ContactsContract.Data.MIMETYPE,
        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
);

// Adds the phone number and its type to the row
phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);

// Adds the row to the array
contactData.add(phoneRow);

/*
 * Sets up the email data row
 */

// Sets up the row as a ContentValues object
ContentValues emailRow = new ContentValues();

// Specifies the MIME type for this data row (all data rows must be marked by their type)
emailRow.put(
        ContactsContract.Data.MIMETYPE,
        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
);

// Adds the email address and its type to the row
emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email);

// Adds the row to the array
contactData.add(emailRow);

/*
 * Adds the array to the intent's extras. It must be a parcelable object in order to
 * travel between processes. The device's contacts app expects its key to be
 * Intents.Insert.DATA
 */
insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData);

// Send out the intent to start the device's contacts app in its add contact activity.
startActivity(insertIntent);

Toàn vẹn dữ liệu

Vì kho lưu giữ danh bạ chứa dữ liệu quan trọng và nhạy cảm mà người dùng cho là đúng và cập nhật, Trình cung cấp Danh bạ có các quy tắc về toàn vẹn dữ liệu được định nghĩa rõ ràng. Bạn có trách nhiệm tuân theo những quy tắc này khi sửa đổi dữ liệu danh bạ. Các quy tắc quan trọng được liệt kê ở đây:

Luôn thêm một hàng ContactsContract.CommonDataKinds.StructuredName cho mỗi hàng ContactsContract.RawContacts mà bạn thêm.
Hàng ContactsContract.RawContacts không có một hàng ContactsContract.CommonDataKinds.StructuredName trong bảng ContactsContract.Data có thể gây ra sự cố trong khi tổng hợp.
Luôn liên kết các hàng ContactsContract.Data mới với hàng ContactsContract.RawContacts mẹ của chúng.
Mỗi hàng ContactsContract.Data mà không được liên kết với một ContactsContract.RawContacts sẽ không hiển thị trong ứng dụng danh bạ của thiết bị, và nó có thể gây ra sự cố với trình điều hợp đồng bộ.
Chỉ thay đổi dữ liệu đối với những liên lạc thô mà bạn sở hữu.
Nhớ rằng Trình cung cấp Danh bạ luôn quản lý dữ liệu từ vài loại tài khoản/dịch vụ trực tuyến khác nhau. Bạn cần đảm bảo rằng ứng dụng của bạn chỉ sửa đổi hoặc xóa dữ liệu đối với các hàng thuộc về bạn, và rằng nó chỉ chèn dữ liệu có loại và tên tài khoản mà bạn kiểm soát.
Luôn sử dụng các hằng số được định nghĩa trong ContactsContract và các lớp con của nó đối với thẩm quyền, URI nội dung, đường dẫn URI, tên cột, kiểu MIME, và các giá trị TYPE.
Sử dụng những hằng số này sẽ giúp bạn tránh gặp lỗi. Bạn cũng sẽ được thông báo bằng cảnh báo từ trình biên dịch nếu bất kỳ hằng số nào không được chấp nhận.

Hàng dữ liệu tùy chỉnh

Bằng cách tạo và sử dụng các kiểu MIME tùy chỉnh của chính mình, bạn có thể chèn, chỉnh sửa, xóa và truy xuất các hàng dữ liệu của chính mình trong bảng ContactsContract.Data. Các hàng của bạn bị giới hạn bằng cách sử dụng cột được định nghĩa trong ContactsContract.DataColumns, mặc dù bạn có thể ánh xạ tên cột theo kiểu của chính mình với tên cột mặc định. Trong ứng dụng danh bạ của thiết bị, dữ liệu cho các hàng của bạn được hiển thị nhưng không thể chỉnh sửa hay xóa được, và người dùng không thể thêm dữ liệu bổ sung. Để cho phép người dùng sửa đổi các hàng dữ liệu tùy chỉnh của mình, bạn phải cung cấp một hoạt động trình chỉnh sửa trong ứng dụng của chính mình.

Để hiển thị dữ liệu tùy chỉnh của mình, hãy cung cấp một tệp contacts.xml chứa một phần tử <ContactsAccountType> và một hoặc nhiều phần tử con <ContactsDataKind> của nó. Điều này được mô tả chi tiết hơn trong phần <ContactsDataKind> element.

Để tìm hiểu thêm về các kiểu MIME tùy chỉnh, hãy đọc hướng dẫn Tạo một Trình cung cấp Nội dung.

Trình điều hợp Đồng bộ Trình cung cấp Danh bạ

Trình cung cấp Danh bạ được thiết kế riêng để xử lý đồng bộ hoá dữ liệu danh bạ giữa một thiết bị và một dịch vụ trực tuyến. Điều này cho phép người dùng tải dữ liệu hiện có xuống một thiết bị mới và tải dữ liệu hiện có lên một tài khoản mới. Đồng bộ hoá cũng đảm bảo rằng người dùng có sẵn dữ liệu mới nhất, không phụ thuộc vào nguồn của các bổ sung và thay đổi. Một ưu điểm khác của đồng bộ hoá đó là nó khiến dữ liệu danh bạ có sẵn ngay cả khi thiết bị không được kết nối với mạng.

Mặc dù bạn có thể triển khai đồng bộ hoá theo nhiều cách, hệ thống Android cung cấp một khuôn khổ đồng bộ hóa bổ trợ có khả năng tự động hóa những tác vụ sau:

  • Kiểm tra sự sẵn sàng của mạng.
  • Lập lịch biểu và thực hiện đồng bộ hoá dựa trên tùy chọn của người dùng.
  • Khởi động lại những đồng bộ hoá đã dừng.

Để sử dụng khuôn khổ này, bạn phải cung cấp một phần bổ trợ trình điều hợp đồng bộ. Mỗi trình điều hợp đồng bộ là duy nhất đối với một dịch vụ và trình cung cấp nội dung, nhưng có thể xử lý nhiều tên tài khoản cho cùng dịch vụ. Khuôn khổ cũng cho phép nhiều trình điều hợp đồng bộ cho cùng dịch vụ và trình cung cấp.

Các lớp và tệp trình điều hợp đồng bộ

Bạn triển khai một trình điều hợp đồng bộ làm lớp con của AbstractThreadedSyncAdapter và cài đặt nó như một phần của một ứng dụng Android. Hệ thống biết về trình điều hợp đồng bộ từ các phần tử trong bản kê khai ứng dụng của nó, và từ một tệp XML đặc biệt được chỉ đến trong bản kê khai. Tệp XML sẽ định nghĩa loại tài khoản cho dịch vụ trực tuyến và thẩm quyền cho trình cung cấp nội dung, cùng nhau chúng xác định duy nhất một trình điều hợp. Trình điều hợp đồng bộ không được kích hoạt cho tới khi người dùng thêm một tài khoản cho loại tài khoản của trình điều hợp đồng bộ và kích hoạt đồng bộ hoá cho trình cung cấp nội dung mà trình điều hợp đồng bộ sẽ đồng bộ cùng. Tại thời điểm đó, hệ thống bắt đầu quản lý trình điều hợp, gọi nó nếu cần thiết để đồng bộ hoá giữa trình cung cấp nội dung và máy chủ.

Lưu ý: Việc sử dụng một loại tài khoản để tham gia nhận biết trình điều hợp đồng bộ sẽ cho phép hệ thống phát hiện và nhóm cùng nhau những trình điều hợp đồng bộ truy cập các dịch vụ khác nhau từ cùng tổ chức. Ví dụ, các trình điều hợp đồng bộ cho dịch vụ trực tuyến của Google đều có cùng loại tài khoản com.google. Khi người dùng thêm một tài khoản Google vào thiết bị của mình, tất cả trình điều hợp đồng bộ được cài đặt cho dịch vụ Google được liệt kê cùng nhau; mỗi trình điều hợp đồng bộ được liệt kê sẽ đồng bộ với một trình cung cấp nội dung khác nhau trên thiết bị.

Vì hầu hết dịch vụ đều yêu cầu người dùng xác minh danh tính của họ trước khi truy cập dữ liệu, hệ thống Android cung cấp một khuôn khổ xác thực tương tự như và thường được sử dụng cùng với khuôn khổ của trình điều hợp đồng bộ. Khuôn khổ xác thực sử dụng các trình xác thực bổ trợ là lớp con của AbstractAccountAuthenticator. Một trình xác thực sẽ xác minh danh tính của người dùng theo các bước sau:

  1. Thu thập tên, mật khẩu hoặc thông tin tương tự của người dùng ( thông tin xác thực của người dùng).
  2. Gửi thông tin xác thực tới dịch vụ
  3. Kiểm tra trả lời của dịch vụ.

Nếu dịch vụ chấp nhận thông tin xác thực, trình xác thực có thể lưu giữ thông tin xác thực đó để sử dụng sau. Vì khuôn khổ trình xác thực bổ trợ, AccountManager có thể cung cấp quyền truy cập bất kỳ token xác thực nào mà một trình xác thực hỗ trợ và chọn hiện ra, chẳng hạn như token xác thực OAuth2.

Mặc dù không yêu cầu xác thực, phần lớn dịch vụ danh bạ đều sử dụng nó. Tuy nhiên, bạn không phải sử dụng khuôn khổ xác thực của Android để thực hiện xác thực.

Triển khai trình điều hợp đồng bộ

Để triển khai một trình điều hợp đồng bộ cho Trình cung cấp Danh bạ, bạn bắt đầu bằng cách tạo một ứng dụng Android chứa:

Một thành phần Service để hồi đáp lại các yêu cầu từ hệ thống nhằm gắn kết với trình điều hợp đồng bộ.
Khi hệ thống muốn chạy đồng bộ hoá, nó gọi phương pháp onBind() của dịch vụ và nhận một IBinder cho trình điều hợp đồng bộ. Điều này cho phép hệ thống thực hiện lệnh gọi liên tiến trình tới các phương pháp của trình điều hợp.

Trong ứng dụng mẫu Trình điều hợp Đồng bộ Mẫu, tên lớp của dịch vụ này là com.example.android.samplesync.syncadapter.SyncService.

Trình điều hợp đồng bộ thực tế, được triển khai như một lớp con cụ thể của AbstractThreadedSyncAdapter.
Lớp này thực hiện công việc tải xuống dữ liệu từ máy chủ, tải lên dữ liệu từ thiết bị, và xử lý xung đột. Công việc chính của trình điều hợp được thực hiện trong phương pháp onPerformSync(). Lớp này phải được khởi tạo như một đối tượng duy nhất (singleton).

Trong ứng dụng mẫu Trình điều hợp Đồng bộ Mẫu, trình điều hợp đồng bộ được định nghĩa trong lớp com.example.android.samplesync.syncadapter.SyncAdapter.

Một lớp con của Application.
Lớp này đóng vai trò như một nhà máy cho đối tượng duy nhất của trình điều hợp đồng bộ. Sử dụng phương pháp onCreate() để khởi tạo trình điều hợp đồng bộ, và cung cấp một phương pháp "bộ nhận" tĩnh để trả đối tượng duy nhất về phương pháp onBind() của dịch vụ của trình điều hợp đồng bộ.
Tùy chọn: Một thành phần Service để hồi đáp lại các yêu cầu từ hệ thống về xác thực người dùng.
AccountManager khởi động dịch vụ này để bắt đầu tiến trình xác thực. Phương pháp onCreate() của dịch vụ này sẽ khởi tạo một đối tượng trình xác thực. Khi hệ thống muốn xác thực một tài khoản người dùng cho trình điều hợp đồng bộ của ứng dụng, nó sẽ gọi phương pháp onBind() của dịch vụ để nhận một IBinder cho trình xác thực. Điều này cho phép hệ thống thực hiện lệnh gọi liên tiến trình tới các phương pháp của trình xác thực.

Trong ứng dụng mẫu Trình điều hợp Đồng bộ Mẫu, tên lớp của dịch vụ này là com.example.android.samplesync.authenticator.AuthenticationService.

Tùy chọn: Một lớp con cụ thể của AbstractAccountAuthenticator để xử lý các yêu cầu về xác thực.
Lớp này cung cấp các phương pháp mà AccountManager gọi ra để xác thực các thông tin xác thực của người dùng với máy chủ. Các chi tiết của tiến trình xác thực rất khác nhau dựa trên công nghệ máy chủ đang sử dụng. Bạn nên tham khảo tài liệu cho phần mềm máy chủ của mình để tìm hiểu thêm về xác thực.

Trong ứng dụng mẫu Trình điều hợp Đồng bộ Mẫu, trình xác thực được định nghĩa trong lớp com.example.android.samplesync.authenticator.Authenticator.

Các tệp XML để định nghĩa trình điều hợp đồng bộ và trình xác thực cho hệ thống.
Các thành phần dịch vụ trình điều hợp đồng bộ và trình xác thực đã nêu được định nghĩa trong các phần tử <service> ở bản kê khai của ứng dụng. Những phần tử này chứa các phần tử con <meta-data> mà cung cấp dữ liệu cụ thể cho hệ thống:
  • Phần tử <meta-data> cho dịch vụ trình điều hợp đồng bộ sẽ trỏ về tệp XML res/xml/syncadapter.xml. Đến lượt mình, tệp này quy định một URI cho dịch vụ web mà sẽ được đồng bộ hóa với Trình cung cấp Danh bạ, và một loại tài khoản cho dịch vụ web.
  • Tùy chọn: Phần tử <meta-data> cho trình xác thực sẽ trỏ về tệp XML res/xml/authenticator.xml. Đến lượt mình, tệp này quy định loại tài khoản mà trình xác thực này hỗ trợ, cũng như các tài nguyên UI mà xuất hiện trong tiến trình xác thực. Loại tài khoản được quy định trong phần tử này phải giống như loại tài khoản được quy định cho trình điều hợp đồng bộ.

Dữ liệu từ Luồng Xã hội

Các bảng android.provider.ContactsContract.StreamItemsandroid.provider.ContactsContract.StreamItemPhotos quản lý dữ liệu đến từ các mạng xã hội. Bạn có thể ghi một trình điều hợp đồng bộ mà thêm dữ liệu luồng từ mạng của chính mình vào những bảng này, hoặc bạn có thể đọc dữ liệu luồng từ những bảng này và hiển thị nó trong ứng dụng của chính mình, hoặc cả hai. Với những tính năng này, các dịch vụ và ứng dụng mạng xã hội của bạn có thể được tích hợp vào trải nghiệm mạng xã hội của Android.

Văn bản từ luồng xã hội

Các mục dòng dữ liệu luôn được liên kết với một liên lạc thô. android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID liên kết với giá trị _ID của liên lạc thô mới. Loại tài khoản và tên tài khoản của liên lạc thô cũng được lưu giữ trong hàng mục dòng.

Lưu giữ dữ liệu từ luồng của bạn vào những cột sau:

android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE
Bắt buộc. Loại tài khoản của người dùng đối với liên lạc thô được liên kết với mục dòng này. Nhớ đặt giá trị này khi bạn chèn một mục dòng.
android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME
Bắt buộc. Tên tài khoản của người dùng đối với liên lạc thô được liên kết với mục dòng này. Nhớ đặt giá trị này khi bạn chèn một mục dòng.
Cột mã định danh
Bắt buộc. Bạn phải chèn các cột mã định danh sau khi chèn một mục dòng:
  • android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID: Giá trị android.provider.BaseColumns#_ID của liên lạc mà mục dòng này được liên kết với.
  • android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY: Giá trị android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY của liên lạc mà mục dòng này được liên kết với.
  • android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID: Giá trị android.provider.BaseColumns#_ID của liên lạc thô mà mục dòng này được liên kết với.
android.provider.ContactsContract.StreamItemsColumns#COMMENTS
Tùy chọn. Lưu giữ thông tin tóm tắt mà bạn có thể hiển thị ở phần đầu của một mục dòng.
android.provider.ContactsContract.StreamItemsColumns#TEXT
Văn bản của mục dòng, hoặc là nội dung đã được đăng bởi nguồn của mục đó, hoặc là mô tả về một số hành động đã khởi tạo mục dòng. Cột này có thể chứa bất kỳ hình ảnh tài nguyên định dạng và được nhúng nào mà có thể được kết xuất bởi fromHtml(). Trình cung cấp có thể cắt bớt hoặc cắt ngắn bằng dấu ba chấm các nội dung dài, nhưng sẽ cố gắng tránh làm hỏng các tag.
android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP
Xâu văn bản chứa thời gian mà mục dòng được chèn hoặc cập nhật, có dạng mili giây trôi qua kể từ giờ epoch. Những ứng dụng chèn hoặc cập nhật mục dòng sẽ chịu trách nhiệm duy trì cột này; nó không được tự động duy trì bởi Trình cung cấp Danh bạ.

Để hiển thị thông tin nhận dạng cho các mục dòng của bạn, hãy sử dụng android.provider.ContactsContract.StreamItemsColumns#RES_ICON, android.provider.ContactsContract.StreamItemsColumns#RES_LABEL, và android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE để liên kết với các tài nguyên trong ứng dụng của mình.

Bảng android.provider.ContactsContract.StreamItems chứa các cột android.provider.ContactsContract.StreamItemsColumns#SYNC1 thông qua android.provider.ContactsContract.StreamItemsColumns#SYNC4 dành riêng để sử dụng trình điều hợp đồng bộ.

Ảnh từ luồng xã hội

Bảng android.provider.ContactsContract.StreamItemPhotos lưu giữ ảnh được liên kết với một mục dòng. Cột android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID của bảng liên kết với các giá trị trong android.provider.BaseColumns#_ID của bảng android.provider.ContactsContract.StreamItems. Các tham chiếu ảnh được lưu giữ trong bảng ở những cột này:

Cột android.provider.ContactsContract.StreamItemPhotos#PHOTO (một BLOB).
Biểu diễn dạng nhị phân của ảnh, được trình cung cấp đổi kích cỡ để lưu giữ và hiển thị. Cột này có sẵn để tương thích ngược với các phiên bản trước của Trình cung cấp Danh bạ mà đã sử dụng nó để lưu giữ ảnh. Tuy nhiên, trong phiên bản hiện tại bạn không nên sử dụng cột này để lưu giữ ảnh. Thay vào đó, hãy sử dụng hoặc android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID hoặc android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI (cả hai đều được mô tả trong các điểm sau) để lưu giữ ảnh trong một tệp. Lúc này, cột này chứa một hình thu nhỏ của ảnh sẵn sàng để đọc.
android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID
Một mã định danh dạng số của ảnh cho một liên lạc thô. Nối giá trị này với hằng số DisplayPhoto.CONTENT_URI để nhận một URI nội dung trỏ về một tệp ảnh đơn, rồi gọi openAssetFileDescriptor() để nhận một điều khiển (handle) cho tệp ảnh.
android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI
Một URI nội dung trỏ trực tiếp tới tệp ảnh cho ảnh được đại diện bởi hàng này. Gọi openAssetFileDescriptor() bằng URI này để nhận một điều khiển (handle) cho tệp ảnh.

Sử dụng các bảng luồng xã hội

Những bảng này hoạt động giống như các bảng chính khác trong Trình cung cấp Danh bạ, ngoại trừ:

  • Những bảng này yêu cầu quyền truy cập bổ sung. Để đọc từ chúng, ứng dụng của bạn phải có quyền android.Manifest.permission#READ_SOCIAL_STREAM. Để sửa đổi chúng, ứng dụng của bạn phải có quyền android.Manifest.permission#WRITE_SOCIAL_STREAM.
  • Đối với bảng android.provider.ContactsContract.StreamItems, số hàng được lưu giữ cho mỗi liên lạc thô sẽ bị giới hạn. Sau khi đạt đến giới hạn này, Trình cung cấp Danh bạ sẽ tạo khoảng trống cho các hàng mục dòng mới bằng cách tự động xóa những hàng có android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP lâu nhất. Để nhận giới hạn, hãy phát hành một truy vấn tới URI nội dung android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI. Bạn có thể để tất cả các tham đối khác ngoài URI nội dung được đặt về null. Truy vấn trả về một Con chạy chứa một hàng đơn, với cột đơn android.provider.ContactsContract.StreamItems#MAX_ITEMS.

Lớp android.provider.ContactsContract.StreamItems.StreamItemPhotos định nghĩa một bảng con android.provider.ContactsContract.StreamItemPhotos chứa các hàng ảnh cho một mục dòng đơn.

Tương tác từ luồng xã hội

Dữ liệu từ luồng xã hội được quản lý bởi Trình cung cấp Danh bạ, kết hợp với ứng dụng danh bạ của thiết bị, cung cấp một cách hiệu quả để kết nối hệ thống mạng xã hội của bạn với các liên lạc hiện tại. Có sẵn những tính năng sau:

  • Bằng cách đồng bộ dịch vụ mạng xã hội của bạn với Trình cung cấp Danh bạ bằng một trình điều hợp đồng bộ, bạn có thể truy xuất hoạt động gần đây đối với danh bạ của một người dùng và lưu giữ nó trong các bảng android.provider.ContactsContract.StreamItemsandroid.provider.ContactsContract.StreamItemPhotos để sử dụng sau.
  • Bên cạnh việc đồng bộ hoá thường xuyên, bạn có thể kích khởi trình điều hợp đồng bộ của mình để truy xuất dữ liệu bổ sung khi người dùng chọn một liên lạc để xem. Điều này cho phép trình điều hợp đồng bộ của bạn truy xuất ảnh độ phân giải cao và các mục dòng gần đây nhất cho liên lạc đó.
  • Bằng cách đăng ký một thông báo với ứng dụng danh bạ của thiết bị và Trình cung cấp Danh bạ, bạn có thể nhận một ý định khi một liên lạc được xem, và tại thời điểm đó, cập nhật trạng thái của liên lạc đó từ dịch vụ của bạn. Phương pháp này có thể nhanh hơn và sử dụng ít băng thông hơn việc thực hiện đồng bộ đầy đủ với một trình điều hợp đồng bộ.
  • Người dùng có thể thêm một liên lạc vào dịch vụ mạng xã hội của mình trong khi đang xem liên lạc đó trong ứng dụng danh bạ của thiết bị. Bạn kích hoạt điều này bằng tính năng "mời liên lạc", theo đó cho phép kết hợp một hoạt động để thêm một liên lạc hiện có vào mạng của bạn, và một tệp XML để cung cấp cho ứng dụng danh bạ của thiết bị và Trình cung cấp Danh bạ thông tin chi tiết về ứng dụng của bạn.

Đồng bộ hóa thường xuyên các mục dòng với Trình cung cấp Danh bạ giống như các trường hợp đồng bộ hoá khác. Để tìm hiểu thêm về đồng bộ hoá, hãy xem phần Trình điều hợp Đồng bộ Trình cung cấp Danh bạ. Việc đăng ký thông tin và mời liên lạc được đề cập trong hai phần tiếp theo.

Đăng ký để xử lý các lượt xem mạng xã hội

Để đăng ký để trình điều hợp đồng bộ của bạn nhận thông báo khi người dùng xem một liên lạc do trình điều hợp đồng bộ của bạn quản lý:

  1. Tạo một tệp có tên contacts.xml trong thư mục res/xml/ của dự án của bạn. Nếu đã có tệp này, bạn có thể bỏ qua bước này.
  2. Trong tệp này, hãy thêm phần tử <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. Nếu phần tử này đã tồn tại, bạn có thể bỏ qua bước này.
  3. Để đăng ký một dịch vụ được thông báo khi người dùng mở trang chi tiết của một liên lạc trong ứng dụng danh bạ của thiết bị, hãy thêm thuộc tính viewContactNotifyService="serviceclass" vào phần tử, trong đó serviceclass là tên lớp được đáp ứng đầy đủ của dịch vụ mà sẽ nhận ý định từ ứng dụng danh bạ của thiết bị. Đối với dịch vụ trình thông báo, hãy sử dụng một lớp mở rộng IntentService, để cho phép dịch vụ nhận các ý định. Dữ liệu trong ý định đến chứa URI nội dung của liên lạc thô mà người dùng đã nhấp vào. Từ dịch vụ trình thông báo, bạn có thể gắn kết với rồi gọi trình điều hợp đồng bộ của bạn để cập nhật dữ liệu cho liên lạc thô.

Để đăng ký một hoạt động sẽ được gọi khi người dùng nhấp vào một mục dòng hay ảnh hoặc cả hai:

  1. Tạo một tệp có tên contacts.xml trong thư mục res/xml/ của dự án của bạn. Nếu đã có tệp này, bạn có thể bỏ qua bước này.
  2. Trong tệp này, hãy thêm phần tử <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. Nếu phần tử này đã tồn tại, bạn có thể bỏ qua bước này.
  3. Để đăng ký một trong các hoạt động của bạn sẽ xử lý khi người dùng nhấp vào một mục dòng trong ứng dụng danh bạ của thiết bị, hãy thêm thuộc tính viewStreamItemActivity="activityclass" vào phần tử đó, trong đó activityclass là tên lớp được xác định đầy đủ của hoạt động mà sẽ nhận ý định từ ứng dụng danh bạ của thiết bị.
  4. Để đăng ký một trong các hoạt động của bạn sẽ xử lý khi người dùng nhấp vào một ảnh luồng trong ứng dụng danh bạ của thiết bị, hãy thêm thuộc tính viewStreamItemPhotoActivity="activityclass" vào phần tử đó, trong đó activityclass là tên lớp được xác định đầy đủ của hoạt động mà sẽ nhận ý định từ ứng dụng danh bạ của thiết bị.

Phần tử <ContactsAccountType> được mô tả chi tiết hơn trong mục phần tử <ContactsAccountType>.

Ý định đến chứa URI nội dung của mục hoặc ảnh mà người dùng đã nhấp vào. Để có các hoạt động riêng cho các mục văn bản và ảnh, hãy sử dụng cả hai thuộc tính trong cùng tệp.

Tương tác với dịch vụ mạng xã hội của bạn

Người dùng không phải rời ứng dụng danh bạ của thiết bị để mời một liên lạc tới trang mạng xã hội của bạn. Thay vào đó, bạn có thể thiết đặt để ứng dụng danh bạ của thiết bị gửi một ý định để mời liên lạc đó tới một trong các hoạt động của mình. Để thiết đặt điều này:

  1. Tạo một tệp có tên contacts.xml trong thư mục res/xml/ của dự án của bạn. Nếu đã có tệp này, bạn có thể bỏ qua bước này.
  2. Trong tệp này, hãy thêm phần tử <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. Nếu phần tử này đã tồn tại, bạn có thể bỏ qua bước này.
  3. Thêm các thuộc tính sau:
    • inviteContactActivity="activityclass"
    • inviteContactActionLabel="@string/invite_action_label"
    Giá trị activityclass là tên lớp được xác định đầy đủ của hoạt động mà sẽ nhận được ý định. Giá trị invite_action_label là một xâu văn bản được hiển thị trong menu Thêm Kết nối trong ứng dụng danh bạ của thiết bị.

Lưu ý: ContactsSource là một tên tag không được chấp nhận đối với ContactsAccountType.

Tham chiếu contacts.xml

Tệp contacts.xml chứa các phần tử XML có chức năng kiểm soát tương tác giữa trình điều hợp đồng bộ và ứng dụng của bạn với ứng dụng danh bạ và Trình cung cấp Danh bạ. Những phần tử này được mô tả trong các mục sau.

Thành phần <ContactsAccountType>

Phần tử <ContactsAccountType> kiểm soát tương tác giữa ứng dụng của bạn với ứng dụng danh bạ. Nó có những cú pháp sau:

<ContactsAccountType
        xmlns:android="http://schemas.android.com/apk/res/android"
        inviteContactActivity="activity_name"
        inviteContactActionLabel="invite_command_text"
        viewContactNotifyService="view_notify_service"
        viewGroupActivity="group_view_activity"
        viewGroupActionLabel="group_action_text"
        viewStreamItemActivity="viewstream_activity_name"
        viewStreamItemPhotoActivity="viewphotostream_activity_name">

chứa trong:

res/xml/contacts.xml

có thể chứa:

<ContactsDataKind>

Mô tả:

Khai báo các thành phần Android và nhãn UI mà cho phép người dùng mời một trong các liên lạc của mình đến một mạng xã hội, thông báo người dùng khi một trong các luồng mạng xã hội của họ được cập nhật, v.v.

Để ý rằng tiền tố thuộc tính android: không nhất thiết áp dụng cho các thuộc tính của <ContactsAccountType>.

Thuộc tính:

inviteContactActivity
Tên lớp được xác định đầy đủ của hoạt động trong ứng dụng của bạn mà bạn muốn kích hoạt khi người dùng chọn Thêm kết nối từ ứng dụng danh bạ của thiết bị.
inviteContactActionLabel
Một xâu văn bản được hiển thị cho hoạt động được quy định trong inviteContactActivity, trong menu Thêm kết nối. Ví dụ, bạn có thể sử dụng xâu "Follow in my network". Bạn có thể sử dụng mã định danh tài nguyên xâu cho nhãn này.
viewContactNotifyService
Tên lớp được xác định đầy đủ của một dịch vụ trong ứng dụng của bạn mà sẽ nhận được thông báo khi người dùng xem một liên lạc. Thông báo này được gửi từ ứng dụng danh bạ của thiết bị; nó cho phép ứng dụng của bạn tạm hoãn các thao tác dùng nhiều dữ liệu tới khi cần. Ví dụ, ứng dụng của bạn có thể hồi đáp lại thông báo này bằng cách đọc và hiển thị ảnh độ phân giải cao của danh bạ và các mục dòng mạng xã hội gần đây nhất. Tính năng này được mô tả chi tiết hơn trong phần Tương tác với luồng xã hội. Bạn có thể thấy một ví dụ về dịch vụ thông báo trong tệp NotifierService.java trong ứng dụng mẫu SampleSyncAdapter .
viewGroupActivity
Tên lớp được xác định đầy đủ của một hoạt động trong ứng dụng của bạn mà có thể hiển thị thông tin nhóm. Khi người dùng nhấp vào nhãn nhóm trong ứng dụng danh bạ của thiết bị, UI cho hoạt động này sẽ được hiển thị.
viewGroupActionLabel
Nhãn mà ứng dụng danh bạ hiển thị cho một điều khiển UI có cho phép người dùng xem các nhóm trong ứng dụng của bạn.

Ví dụ, nếu bạn cài đặt ứng dụng Google+ trên thiết bị của mình và bạn đồng bộ Google+ với ứng dụng danh bạ, bạn sẽ thấy các vòng tròn Google+ được liệt kê thành các nhóm trong tab Nhóm của ứng dụng danh bạ của bạn. Nếu bạn nhấp vào một vòng tròn Google+, bạn sẽ thấy những người trong vòng tròn đó được liệt kê thành một "nhóm". Phía bên trên của hiển thị, bạn sẽ thấy một biểu tượng Google+; nếu bạn nhấp vào đó, điều khiển sẽ chuyển sang ứng dụng Google+. Ứng dụng danh bạ làm điều này bằng viewGroupActivity, bằng cách sử dụng biểu tượng Google+ làm giá trị của viewGroupActionLabel.

Một mã định danh tài nguyên xâu được cho phép cho thuộc tính này.

viewStreamItemActivity
Tên lớp được xác định đầy đủ của một hoạt động trong ứng dụng của bạn mà ứng dụng danh bạ của thiết bị khởi chạy khi người dùng nhấp vào một mục dòng đối với một liên lạc thô.
viewStreamItemPhotoActivity
Tên lớp được xác định đầy đủ của một hoạt động trong ứng dụng của bạn mà ứng dụng danh bạ của thiết bị khởi chạy khi người dùng nhấp vào một ảnh trong mục dòng đối với một liên lạc thô.

Phần tử <ContactsDataKind>

Phần tử <ContactsDataKind> kiểm soát việc hiển thị các hàng dữ liệu tùy chỉnh của ứng dụng của bạn trong UI của ứng dụng danh bạ. Nó có những cú pháp sau:

<ContactsDataKind
        android:mimeType="MIMEtype"
        android:icon="icon_resources"
        android:summaryColumn="column_name"
        android:detailColumn="column_name">

chứa trong:

<ContactsAccountType>

Mô tả:

Sử dụng phần tử này để ứng dụng danh bạ hiển thị các nội dung trong một hàng dữ liệu tùy chỉnh như một phần chi tiết của một liên lạc thô. Mỗi phần tử con <ContactsDataKind> của <ContactsAccountType> đại diện cho một kiểu hàng dữ liệu tùy chỉnh mà trình điều hợp đồng bộ của bạn thêm vào bảng ContactsContract.Data. Thêm một phần tử <ContactsDataKind> cho mỗi kiểu MIME tùy chỉnh mà bạn sử dụng. Bạn không phải thêm phần tử nếu có một hàng dữ liệu tùy chỉnh mà bạn không muốn hiển thị dữ liệu.

Thuộc tính:

android:mimeType
Kiểu MIME tùy chỉnh mà bạn đã định nghĩa cho một trong các kiểu hàng dữ liệu tùy chỉnh của bạn trong bảng ContactsContract.Data. Ví dụ, giá trị vnd.android.cursor.item/vnd.example.locationstatus có thể là một kiểu MIME tùy chỉnh cho một hàng dữ liệu có chức năng ghi lại vị trí được biết đến cuối cùng của một liên lạc.
android:icon
Một tài nguyên có thể vẽ của Android mà ứng dụng danh bạ hiển thị bên cạnh dữ liệu của bạn. Sử dụng nó để thể hiện với người dùng rằng dữ liệu xuất phát từ dịch vụ của bạn.
android:summaryColumn
Tên cột của giá trị thứ nhất trong hai giá trị được truy xuất từ hàng dữ liệu. Giá trị được hiển thị là dòng thứ nhất của mục nhập cho hàng dữ liệu này. Dòng thứ nhất có mục đích sử dụng làm bản tóm tắt dữ liệu, nhưng điều đó là tùy chọn. Xem thêm android:detailColumn.
android:detailColumn
Tên cột của giá trị thứ hai trong hai giá trị được truy xuất từ hàng dữ liệu. Giá trị được hiển thị là dòng thứ hai của mục nhập cho hàng dữ liệu này. Xem thêm android:summaryColumn.

Các Tính năng Bổ sung của Trình cung cấp Danh bạ

Bên cạnh các tính năng chính được mô tả trong các phần trước, Trình cung cấp Danh bạ còn cung cấp những tính năng hữu ích sau khi làm việc với dữ liệu danh bạ:

  • Nhóm liên lạc
  • Tính năng ảnh

Nhóm liên lạc

Trình cung cấp Danh bạ có thể tùy chọn đánh nhãn các bộ sưu tập liên lạc có liên quan bằng dữ liệu nhóm. Nếu máy chủ liên kết với một tài khoản người dùng muốn duy trì nhóm, trình điều hợp đồng bộ cho loại tài khoản của tài khoản đó sẽ chuyển dữ liệu nhóm giữa Trình cung cấp Danh bạ và máy chủ. Khi người dùng thêm một liên lạc mới vào máy chủ, trình điều hợp đồng bộ phải thêm nhóm mới vào bảng ContactsContract.Groups. Nhóm hoặc các nhóm mà một liên lạc thô thuộc về được lưu giữ trong bảng ContactsContract.Data, bằng cách sử dụng kiểu MIME ContactsContract.CommonDataKinds.GroupMembership.

Nếu bạn đang thiết kế một trình điều hợp đồng bộ mà sẽ thêm dữ liệu liên lạc thô từ máy chủ tới Trình cung cấp Danh bạ, và bạn không sử dụng các nhóm, khi đó bạn cần báo cho Trình cung cấp làm các dữ liệu của bạn thấy được. Trong đoạn mã được thực hiện khi một người dùng thêm một tài khoản vào thiết bị, hãy cập nhật hàng ContactsContract.Settings mà Trình cung cấp Danh bạ thêm cho tài khoản. Trong hàng này, đặt giá trị của cột Settings.UNGROUPED_VISIBLE thành 1. Khi bạn làm vậy, Trình cung cấp Danh bạ sẽ luôn làm cho dữ liệu danh bạ của bạn thấy được, ngay cả khi bạn không sử dụng nhóm.

Ảnh liên lạc

Bảng ContactsContract.Data lưu giữ ảnh thành hàng với kiểu MIME Photo.CONTENT_ITEM_TYPE. Cột CONTACT_ID của hàng được liên kết với cột android.provider.BaseColumns#_ID của liên lạc thô mà nó thuộc về. Lớp ContactsContract.Contacts.Photo định nghĩa một bảng con của ContactsContract.Contacts chứa thông tin ảnh về ảnh chính của một liên lạc, đây là ảnh chính của liên lạc thô chính của liên lạc. Tương tự, lớp ContactsContract.RawContacts.DisplayPhoto định nghĩa một bảng con của ContactsContract.RawContacts chứa thông tin ảnh đối với ảnh chính của một liên lạc thô.

Tài liệu tham khảo cho ContactsContract.Contacts.PhotoContactsContract.RawContacts.DisplayPhoto có các ví dụ về việc truy xuất thông tin ảnh. Không có lớp thuận tiện cho việc truy xuất hình thu nhỏ chính đối với một liên lạc thô, nhưng bạn có thể gửi một truy vấn tới bảng ContactsContract.Data, chọn android.provider.BaseColumns#_ID của liên lạc thô, Photo.CONTENT_ITEM_TYPE, và cột IS_PRIMARY để tìm hàng ảnh chính của liên lạc thô.

Dữ liệu từ luồng xã hội đối với một người cũng có thể bao gồm ảnh. Những ảnh này được lưu giữ trong bảng android.provider.ContactsContract.StreamItemPhotos, được mô tả chi tiết hơn trong phần Ảnh từ luồng xã hội.