您的位置:首页 > 移动开发 > Android开发

Android开发入门之访问通讯录中的联系人和添加联系人

2013-07-09 16:32 405 查看
首先在向Android联系人中添加数据



联系人的数据放在



将contacts2.db导出到桌面上,打开



contact2.db有很多表,最重要的有3张表raw_contacts(存放联系人ID)、data、mimetypes

raw_contacts:



data:



mimetypes:



新建一个名为contacts 的项目,添加测试环境,新建一个测试类ContactsTest,放在cn.leigo.test包下。

现在我们看看源码是如何定义联系人的ContentProvider的,https://android.googlesource.com/platform/packages/providers/ContactsProvider.git/+/android-2.3.3_r1/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.providers.contacts"
android:sharedUserId="android.uid.shared">

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.cp" />
<uses-permission android:name="android.permission.SUBSCRIBED_FEEDS_READ" />
<uses-permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE" />

<application android:process="android.process.acore"
android:label="@string/app_label"
android:icon="@drawable/app_icon">

<provider android:name="ContactsProvider2"
android:authorities="contacts;com.android.contacts"
android:label="@string/provider_label"
android:multiprocess="false"
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>

<provider android:name="CallLogProvider"
android:authorities="call_log"
android:syncable="false" android:multiprocess="false"
android:readPermission="android.permission.READ_CONTACTS"
android:writePermission="android.permission.WRITE_CONTACTS">
</provider>

<!-- TODO: create permissions for social data -->
<provider android:name="SocialProvider"
android:authorities="com.android.social"
android:syncable="false"
android:multiprocess="false"
android:readPermission="android.permission.READ_CONTACTS"
android:writePermission="android.permission.WRITE_CONTACTS" />

<!-- Handles database upgrades after OTAs, then disables itself -->
<receiver android:name="ContactsUpgradeReceiver">
<!-- This broadcast is sent after the core system has finished
booting, before the home app is launched or BOOT_COMPLETED
is sent. -->
<intent-filter>
<action android:name="android.intent.action.PRE_BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>

来到https://android.googlesource.com/platform/packages/providers/ContactsProvider.git/+/android-2.3.3_r1/src/com/android/providers/contacts/ContactsProvider2.java,
这个类有6000多行,我们不可能全部看完,可以根据

sUriMatcher

查找或者直接找静态代码块

static {
// Contacts URI matching table
final UriMatcher matcher = sUriMatcher;
matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions",
AGGREGATION_SUGGESTIONS);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*",
AGGREGATION_SUGGESTIONS);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID);
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, "raw_contacts", RAW_CONTACTS);
matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID);
matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA);
matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID);

matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES);

matcher.addURI(ContactsContract.AUTHORITY, "data", DATA);
matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER);
matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS);
matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID);
matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP);
matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER);
matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER);
matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS);
matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID);

matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS);
matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID);
matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY);

matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE);
matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#",
SYNCSTATE_ID);

matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP);
matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions",
AGGREGATION_EXCEPTIONS);
matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*",
AGGREGATION_EXCEPTION_ID);

matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS);

matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES);
matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID);

matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY,
SEARCH_SUGGESTIONS);
matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*",
SEARCH_SUGGESTIONS);
matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*",
SEARCH_SHORTCUT);

matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts",
LIVE_FOLDERS_CONTACTS);
matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*",
LIVE_FOLDERS_CONTACTS_GROUP_NAME);
matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones",
LIVE_FOLDERS_CONTACTS_WITH_PHONES);
matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites",
LIVE_FOLDERS_CONTACTS_FAVORITES);

matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS);
}

目前为止,我们只关心3个路径
        matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA);

测试类:
package cn.leigo.test;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.text.TextUtils;
import android.util.Log;

public class ContactsTest extends AndroidTestCase {
private static final String TAG = "ContactsTest";

/**
* 获取联系人
*
* @throws Exception
*/
public void testContacts() throws Exception {
Uri uri = Uri.parse("content://com.android.contacts/contacts");
ContentResolver resolver = getContext().getContentResolver();
Cursor c = resolver
.query(uri, new String[] { "_id" }, null, null, null);
while (c.moveToNext()) {
int contactid = c.getInt(0);
StringBuilder sb = new StringBuilder("contactid=")
.append(contactid);
uri = Uri.parse("content://com.android.contacts/contacts/"
+ contactid + "/data");
Cursor cursor = resolver.query(uri, new String[] { "mimetype",
"data1", "data2" }, null, null, null);
while (cursor.moveToNext()) {
String data1 = cursor.getString(cursor.getColumnIndex("data1"));
String mimetypeId = cursor.getString(cursor
.getColumnIndex("mimetype"));
if (TextUtils
.equals(mimetypeId, "vnd.android.cursor.item/name")) {
// 姓名
sb.append(",name=" + data1);
} else if (TextUtils.equals(mimetypeId,
"vnd.android.cursor.item/email_v2")) {
// email
sb.append(",email=" + data1);
} else if (TextUtils.equals(mimetypeId,
"vnd.android.cursor.item/phone_v2")) {
// 电话
sb.append(",phone=" + data1);
}
}
Log.i(TAG, sb.toString());
}
}

}
注意的是,android内部提供了关联查询,所以查询的时候可以直接查询"mimetype",而不是先查询"mimetype_id"然后根据"mimetype_id"查询"mimetype"。
最后添加上权限

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

这里我把读写权限都加上去了。



/**
* 根据号码获取联系人的姓名
*/
public void testDisplayNameByNumber() throws Exception {
String number = "15100000000";
Uri uri = Uri
.parse("content://com.android.contacts/data/phones/filter/"
+ number);
ContentResolver resolver = getContext().getContentResolver();
Cursor c = resolver.query(uri, new String[] { "display_name" }, null,
null, null);
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndex("display_name"));
Log.i(TAG, name);
}
c.close();
}



/**
* 向通讯录添加联系人
*
* @throws Exception
*/
public void testAddContact() throws Exception {
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
// content://com.android.contacts/raw_contacts/2
long contactid = ContentUris.parseId(resolver.insert(uri, values));

// 添加姓名
uri = Uri.parse("content://com.android.contacts/data");
values.put("raw_contact_id", contactid);
values.put("mimetype", "vnd.android.cursor.item/name");
values.put("data2", "张三");
resolver.insert(uri, values);

// 添加电话
values.clear();
values.put("raw_contact_id", contactid);
values.put("mimetype", "vnd.android.cursor.item/phone_v2");
values.put("data2", "2");
values.put("data1", "18900000000");
resolver.insert(uri, values);

// 添加Email
values.clear();
values.put("raw_contact_id", contactid);
values.put("mimetype", "vnd.android.cursor.item/email_v2");
values.put("data2", "2");
values.put("data1", "zhangsan@csdn.net");
resolver.insert(uri, values);
}


这种方式虽然能够添加成功,但是有个问题就是若某个数据没插入成功,那么其他数据依然会插入进去,没涉及到事务的操作。

下面提供另一种插入方法:

public void testAddContact2() throws Exception {
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
ContentResolver resolver = getContext().getContentResolver();
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri)
.withValue("account_name", null).build();
operations.add(op1);

uri = Uri.parse("content://com.android.contacts/data");
ContentProviderOperation op2 = ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/name")
.withValue("data2", "李四").build();
operations.add(op2);

ContentProviderOperation op3 = ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/phone_v2")
.withValue("data2", "2").withValue("data1", "13500000000")
.build();
operations.add(op3);

ContentProviderOperation op4 = ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/email_v2")
.withValue("data2", "2").withValue("data1", "lisi@csdn.net")
.build();
operations.add(op4);

resolver.applyBatch("com.android.contacts", operations);
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐