Android-讀取/新增/作業系統聯絡人資料
想要訪問Android作業系統的ContentProvider就需要明白以下原理:
在Android作業系統裡面的 /packsges/目錄:
apps: 很多的系統應用,例如:聯絡人,瀏覽器,音樂播放器,設定,相機 ......
............
providers:系統對外暴露的ContentProvider:
這樣就明白了,Android作業系統裡面的應用(apps),是訪問系統對外暴露的ContentProvider(providers)
先在模擬器,新增聯絡人:
既然說Android作業系統裡面的應用(apps),是訪問系統對外暴露的ContentProvider(providers):
/data/data/com.android.contacts(放置在apps目錄裡面)
/data/data/com.android.providers.contacts(放置在providers目錄裡面)
contacts(聯絡人應用) 是呼叫 providers.contacts(內容提供者裡面的資料),如圖:
(為什麼apps目錄的contacts應用 能夠訪問provider
閱讀 com.android.providers.contacts 資料庫與表
Android作業系統的檔案系統目錄/data/data/com.android.contacts,是訪問/data/data/com.android.providers.contacts(內容提供者應用)
所以需要閱讀/data/data/com.android.providers.contacts(內容提供者應用)的資料庫:
開啟 contacts2.db
開啟後:表非常多,檢視非常多,等等, 但是隻需要關注三張核心的表
1.raw_contacts(聯絡人唯一標識表:裡面有 _id 的欄位,是標識了一個聯絡人的唯一標識)
2.data(通過 raw_contacts 表裡面的_id,查詢 raw_contacts_id,就能得到查詢結果)
得到查詢結果後:data1欄位: 聯絡人資料,data2欄位:資料對應的分類(家庭,住宅....)
得到查詢結果後:mimetype_id欄位,是用來查詢的mimetypes表,資料對應的(姓名,..)
3.mimetypes(通過 data 表裡面的 mimetype_id,查詢對應的值)
raw_contacts表:
data表:
mimetypes表:
閱讀 com.android.providers.contacts AndroidManifest.xml,和ContactsProvider2.java
apps目錄的contacts應用,是訪問provider目錄的provider.contacts應用,所以要閱讀Android作業系統原始碼-->packages/providers/ContactsProvider(內容提供者)
AndroidManifest.xml
1.ContactsProvider2就是聯絡人的內容提供者
2.android:authorities="contacts;com.android.contacts" Android2.2版本之前的授權contacts,後面為了考慮相容性就 ;com.android.contacts,這樣就兩個授權都可以使用了,相當於Web伺服器專案的兩個域名,都可以訪問伺服器
3.android:exported="true" 允許對外輸出
4.設定被訪問的許可權 android:readPermission="android.permission.READ_CONTACTS" 聯絡人內容提供者讀取許可權
android:writePermission="android.permission.WRITE_CONTACTS" 聯絡人內容提供者修改許可權
<provider android:name="ContactsProvider2" android:authorities="contacts;com.android.contacts" android:label="@string/provider_label" android:multiprocess="false" android:exported="true" android:readPermission="android.permission.READ_CONTACTS" android:writePermission="android.permission.WRITE_CONTACTS"> <path-permission android:pathPrefix="/search_suggest_query" android:readPermission="android.permission.GLOBAL_SEARCH" /> <path-permission android:pathPrefix="/search_suggest_shortcut" android:readPermission="android.permission.GLOBAL_SEARCH" /> <path-permission android:pathPattern="/contacts/.*/photo" android:readPermission="android.permission.GLOBAL_SEARCH" /> <grant-uri-permission android:pathPattern=".*" /> </provider>
ContactsProvider2.java
首先要找到的就是Uri,所以搜尋UriMatcher的matcher.addURI
matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", CONTACTS_LOOKUP_DISPLAY_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", CONTACTS_LOOKUP_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", CONTACTS_LOOKUP_ID_ENTITIES); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", CONTACTS_LOOKUP_STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", CONTACTS_LOOKUP_ID_STREAM_ITEMS); matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", CONTACTS_AS_MULTI_VCARD); matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", CONTACTS_STREQUENT_FILTER); matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); matcher.addURI(ContactsContract.AUTHORITY, "contacts/delete_usage", CONTACTS_DELETE_USAGE); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_ID_DATA);
有規律,通常情況下,matcher.addURI(授權, path, code),第二個引數 path 和資料庫表名對應的
我首先要查詢,raw_contacts 表,所以找到查詢這個表的 Uri :matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS);
然後還要查詢,data 表,所要要查詢這個表的 Uri :
注意用這個關聯查詢: matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_ID_DATA);
這個不是關聯查詢: matcher.addURI(ContactsContract.AUTHORITY, "data", DATA);
寫入資料需要, 往raw_contacts表增加一條資料,作為唯一標示 matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS);
寫入資料需要,不需要關聯查詢的Uir,需要寫入到Data表:matcher.addURI(ContactsContract.AUTHORITY, "data", DATA);
讀取 -->> Android作業系統聯絡人內容提供者應用裡面的聯絡人資料:
增加資料到 Android作業系統聯絡人內容提供者應用裡面
package liudeli.cp.client; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class ContactsActivity extends Activity { private final String TAG = ContactsActivity.class.getSimpleName(); private EditText name; private EditText phone; private EditText email; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contacts); name = findViewById(R.id.et_name); phone = findViewById(R.id.et_phone); email = findViewById(R.id.et_email); } /** * 獲取 /data/data/com.android.providers.contacts應用(內容提供者暴露的聯絡人資料) * packages/providers/com.android.providers.contacts應用(內容提供者暴露的聯絡人資料) * @param view */ public void readContacts(View view) { /** * 複製com.android.providers.contacts應用的Uri * matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); * matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_ID_DATA); * * 授權:android:authorities="contacts;com.android.contacts" */ Uri rawContactsURI = Uri.parse("content://com.android.contacts/raw_contacts"); Uri rawContactsByIdDataURI = Uri.parse("content://com.android.contacts/raw_contacts/#/data"); // 拿到內容解決者(ContentResolver) ContentResolver contentResolver = getContentResolver(); /** * 使用內容解決者 讀取 作業系統聯絡人內容提供者應用raw_contacts表 */ Cursor cursor = contentResolver.query(rawContactsURI, new String[]{"_id"}, null, null , null); while (cursor.moveToNext()) { // cursor.getInt(0); int _id = cursor.getInt(cursor.getColumnIndex("_id")); Log.d(TAG, "_id" + _id); /** * 使用內容解決者 讀取 作業系統聯絡人內容提供者應用data表 (根據raw_contacts表的_id 去查詢) */ // 把raw_contacts表的_id 寫到 rawContactsByIdDataURI2裡面去 // 把_id寫到...raw_contacts/#/data 的# // 第一種方式 結果為:content://com.android.contacts/raw_contacts/4#/data // 考慮到 作業系統的聯絡人內容提供者不是ContentUris.parseId(uri),所以用第二種拼接方式 // Uri rawContactsByIdDataURI2 = ContentUris.withAppendedId(rawContactsByIdDataURI, _id); // 第二種方式 是直接拼接 Uri rawContactsByIdDataURI2 = Uri.parse("content://com.android.contacts/raw_contacts/"+_id+"/data"); // Log.d(TAG, "rawContactsByIdDataURI2:" + rawContactsByIdDataURI2.toString()); // 結果 content://com.android.contacts/raw_contacts/4/data Cursor dataCursor = contentResolver.query(rawContactsByIdDataURI2, new String[]{}, null, null, null, null); /** * 注意:⚠️ 由於content://com.android.contacts/raw_contacts/#/data這是表關聯查詢 * 所以查詢出來的欄位,我不知道,這系統去關聯查詢的,所以打印出來看看 */ /*String[] columnNames = dataCursor.getColumnNames(); for (String columnName : columnNames) { Log.d(TAG, "關聯查詢Data表 的所有欄位" + columnName); }*/ /** * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位sort_key * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位photo_uri * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位status_label * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位status_ts * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位status_res_package * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位name_verified * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位display_name * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位last_time_used * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位mimetype * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位phonebook_label_alt * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data6 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位version * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位photo_id * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data3 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位custom_ringtone * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位times_contacted * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位account_type_and_data_set * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位dirty * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data7 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data15 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位raw_contact_is_user_profile * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data_set * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位phonebook_label * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data10 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位res_package * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位account_type * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data11 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位display_name_alt * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位lookup * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位phonetic_name * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位last_time_contacted * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_last_updated_timestamp * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data13 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位in_visible_group * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位chat_capability * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data9 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data_sync1 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位sort_key_alt * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_presence * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data_version * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位phonetic_name_style * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位name_raw_contact_id * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位raw_contact_id * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位send_to_voicemail * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data4 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data12 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_status * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_status_label * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位pinned * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位status_icon * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位status * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data1 * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位phonebook_bucket * 12-15 22:45:46.355 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data_sync2 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_status_res_package * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位in_default_directory * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位_id * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位is_super_primary * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data5 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_id * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data8 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位is_primary * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data_sync4 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位has_phone_number * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位display_name_source * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位photo_file_id * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data_sync3 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data14 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_status_ts * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位phonebook_bucket_alt * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位mode * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位data2 * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位group_sourceid * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位starred * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位photo_thumb_uri * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位times_used * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_status_icon * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位contact_chat_capability * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位account_name * 12-15 22:45:46.356 4432-4432/liudeli.cp.client D/ContactsActivity: 關聯查詢Data表 的所有欄位sourceid */ Cursor dataCursor2 = contentResolver.query(rawContactsByIdDataURI2, new String[]{"data1", "data2", "mimetype"}, null, null, null, null); while (dataCursor2.moveToNext()) { String data1 = dataCursor2.getString(0); String data2 = dataCursor2.getString(1); String mimetype = dataCursor2.getString(2); // Log.d(TAG, "data1" + data1 + " ,data2:" + data2 + " ,mimetype:" + mimetype); StringBuilder sb = new StringBuilder(); /** * mimetypes表: * vnd.android.cursor.item/name * vnd.android.cursor.item/phone_v2 * vnd.android.cursor.item/email_v2 * ... */ if ("vnd.android.cursor.item/name".equals(mimetype)) { // 是姓名 if ("1".equals(data2)) { // data2 == 1 是家庭相關 // Log.i(TAG, "家庭姓名:" + data1); sb.append("家庭姓名:" + data1 + ", "); } else { // Log.i(TAG, "姓名:" + data1); sb.append("姓名:" + data1 + ", "); } } else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) { // 是手機號碼 if ("1".equals(data2)) { // data2 == 1 是家庭相關 // Log.i(TAG, "家庭號碼:" + data1); sb.append("家庭號碼:" + data1 + ", "); } else { // Log.i(TAG, "號碼:" + data1); sb.append("號碼:" + data1 + ", "); } } else if ("vnd.android.cursor.item/email_v2".equals(mimetype)) { // 是郵箱 if ("1".equals(data2)) { // data2 == 1 是家庭相關 // Log.i(TAG, "家庭郵箱" + data1); sb.append("家庭郵箱" + data1 + ", "); } else { // Log.i(TAG, "郵箱" + data1); sb.append("郵箱" + data1 + ", "); } } Log.i(TAG, "聯絡人:" + sb.toString()); } } } /** * 寫入 /data/data/com.android.providers.contacts應用(內容提供者暴露的聯絡人資料) * packages/providers/com.android.providers.contacts應用(內容提供者暴露的聯絡人資料) * @param view */ public void insertContacts(View view) { /** * 複製com.android.providers.contacts應用的Uri * matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); * matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); * * 授權:android:authorities="contacts;com.android.contacts" */ Uri rawContactsURI = Uri.parse("content://com.android.contacts/raw_contacts"); Uri dataUri = Uri.parse("content://com.android.contacts/data"); if (!TextUtils.isEmpty(name.getText()) && !TextUtils.isEmpty(phone.getText()) && !TextUtils.isEmpty(email.getText())) { /** * 思路:先往raw_contacts表增加一條記錄,返回Uri,通過返回的Uri,獲取id * 通過獲取的id,在去增加data表,把id插入到data表的raw_contacts_id欄位中去(建立關聯關係) */ // 先往raw_contacts表增加一條記錄,返回Uri,通過返回的Uri,獲取id // 拿到內容解決者(ContentResolver) ContentResolver contentResolver = getContentResolver(); /** * 使用內容解決者 寫入到 作業系統聯絡人內容提供者應用raw_contacts表 */ ContentValues contentValues = new ContentValues(); Uri rawContactsTaleInsertResult = contentResolver.insert(rawContactsURI, contentValues); // 通過返回的Uri,解析id,獲取id long insertResultID = ContentUris.parseId(rawContactsTaleInsertResult); contentValues.clear(); // 通過獲取的id,在去增加data表,把id插入到data表的raw_contacts_id欄位中去(建立關聯關係) /** * mimetypes表: * vnd.android.cursor.item/name * vnd.android.cursor.item/phone_v2 * vnd.android.cursor.item/email_v2 * ... */ contentValues.put("raw_contact_id", insertResultID); contentValues.put("mimetype", "vnd.android.cursor.item/name"); // 型別區分(例如:姓名,電話,郵箱...) contentValues.put("data1", name.getText().toString()); contentResolver.insert(dataUri, contentValues); contentValues.put("raw_contact_id", insertResultID); contentValues.put("mimetype", "vnd.android.cursor.item/phone_v2"); // 型別區分(例如:姓名,電話,郵箱...) contentValues.put("data1", phone.getText().toString()); contentValues.put("data2", 1); // 型別區分(例如:家用,公司,....) contentResolver.insert(dataUri, contentValues); contentValues.put("raw_contact_id", insertResultID); contentValues.put("mimetype", "vnd.android.cursor.item/phone_v2"); // 型別區分(例如:姓名,電話,郵箱...) contentValues.put("data1", email.getText().toString()); contentValues.put("data2", 1); // 型別區分(例如:家用,公司,....) Uri insertExit = contentResolver.insert(dataUri, contentValues); Toast.makeText(this, "插入聯絡人完成", Toast.LENGTH_LONG).show(); } else { Toast.makeText(this, "請填寫完整資訊", Toast.LENGTH_LONG).show(); } } }
Layout:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="讀取聯絡人" android:onClick="readContacts" /> <Button android:id="@+id/bt_insert" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="寫入聯絡人" android:onClick="insertContacts" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_below="@id/bt_insert" android:layout_margin="20dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 我先放置控制元件 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="請輸入姓名:" /> <!-- 剩下的空間給我來全部全部填充 --> <EditText android:id="@+id/et_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 我先放置控制元件 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="請輸入號碼:" /> <!-- 剩下的空間給我來全部全部填充 --> <EditText android:id="@+id/et_phone" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 我先放置控制元件 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="請輸入郵箱:" /> <!-- 剩下的空間給我來全部全部填充 --> <EditText android:id="@+id/et_email" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> </LinearLayout> </RelativeLayout>
AndroidManifest.xml 許可權:
<!-- 訪問作業系統聯絡人內容提供者應用,需要加入的許可權 android:readPermission="android.permission.READ_CONTACTS" android:writePermission="android.permission.WRITE_CONTACTS" --> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
讀取的Log日誌資訊,在新增聯絡人的時候給雷軍增加了很多號碼,所以日誌就多一些:
12-15 23:37:32.731 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:1 368-787-8767,
12-15 23:37:32.731 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:姓名:馬化騰,
12-15 23:37:32.731 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:
12-15 23:37:32.731 5365-5365/liudeli.cp.client D/ContactsActivity: _id2
12-15 23:37:32.786 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:1 667-878-9877,
12-15 23:37:32.786 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:家庭號碼:536-5465,
12-15 23:37:32.786 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:姓名:馬雲,
12-15 23:37:32.786 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:
12-15 23:37:32.786 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:
12-15 23:37:32.786 5365-5365/liudeli.cp.client D/ContactsActivity: _id3
12-15 23:37:32.793 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:1 378-888-8989,
12-15 23:37:32.793 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:姓名:黃光裕,
12-15 23:37:32.793 5365-5365/liudeli.cp.client D/ContactsActivity: _id4
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:1 869-999-9999,
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:家庭號碼:(646) 456-56,
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:(345) 345-464,
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:(654) 745-7657,
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:號碼:575-756,
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:姓名:雷軍,
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:
12-15 23:37:32.799 5365-5365/liudeli.cp.client I/ContactsActivity: 聯絡人:
效果圖: