解剖Android联系人之二,基于2.1 博客分类: 基础 AndroidOracleQQ编程SQL
程序员文章站
2024-03-01 10:50:52
...
上次把联系人的表都打开看了看,也了解了些东西
现在要开始编程了
要从联系人当中提取哪些信息呢?
ID 看起来没用的数据
显示的名字
名
姓
(中间名可以省咯了,中国人基本用不到)
电话
更多电话(家里,工作,等等)
电子邮件(家里,工作,等等)
即时通信(QQ,MSN,Skype,Gtalk,等等)
通讯地址
昵称
备注
网站
更重要的一个东西就是数据的版本号,就是上次我们看到很高兴的那个字段version
data表中有个version字段,raw_contacts表中有个version字段,contacts表中没有
这样只需要我们构建一张表来记录相关数据,我们就能知道哪些数据是在某个时间点后变化过的
如果牛逼的话,就HACK联系人的数据库,给它加个触发器来更改我们表的数据,当然我们的表得放在联系人的数据库当中,又不能像Oracle样建个DATABASE LINK,但是这基本是不可能的
扯远了
现在我们首要任务是在API中把那些对应的字段找出来,把数据读出来
上次我们在分析表的时候发现对于id有很多引用,比如raw_contacts中的contact_id就引用了contacts中的id,并且data中的raw_contact_id又引用了raw_contacts中的_id,这其实还是个比较重要的信息
我们就可以知道,在所有的数据当中,contacts是最开始的,它是起源,虽然它本身不带有很多数据,但是他的作用不可忽视
所以
ID <----------> ContactsContract.Contacts._ID
看看ContactsContract.Contacts._ID的注释我们也可以理解,The unique ID for a row. INTEGER (long)
显示的名字 <----------> ContactsContract.Contacts.DISPLAY_NAME
名 <----------> ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
姓 <----------> ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
看了下表的数据,data表中有条数据是
9||9|1|0|0|0|海 郭|海|郭||||||||||||||||
第三列对应于mimetype,查下mimetype表之后9对应于vnd.android.cursor.item/name
那么我们只需要根据ID和类型查询出这条数据,然后再取出第九列和第十列的数据就应该OK了,第八列是显示的名字
即DATA2(名)和DATA3(姓)
SDK已经帮我们封装好了就是ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME和ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
那么读出联系人数据的代码就应该可以是如下这个样子的
现在要开始编程了
要从联系人当中提取哪些信息呢?
ID 看起来没用的数据
显示的名字
名
姓
(中间名可以省咯了,中国人基本用不到)
电话
更多电话(家里,工作,等等)
电子邮件(家里,工作,等等)
即时通信(QQ,MSN,Skype,Gtalk,等等)
通讯地址
昵称
备注
网站
更重要的一个东西就是数据的版本号,就是上次我们看到很高兴的那个字段version
data表中有个version字段,raw_contacts表中有个version字段,contacts表中没有
这样只需要我们构建一张表来记录相关数据,我们就能知道哪些数据是在某个时间点后变化过的
如果牛逼的话,就HACK联系人的数据库,给它加个触发器来更改我们表的数据,当然我们的表得放在联系人的数据库当中,又不能像Oracle样建个DATABASE LINK,但是这基本是不可能的
扯远了
现在我们首要任务是在API中把那些对应的字段找出来,把数据读出来
上次我们在分析表的时候发现对于id有很多引用,比如raw_contacts中的contact_id就引用了contacts中的id,并且data中的raw_contact_id又引用了raw_contacts中的_id,这其实还是个比较重要的信息
我们就可以知道,在所有的数据当中,contacts是最开始的,它是起源,虽然它本身不带有很多数据,但是他的作用不可忽视
所以
ID <----------> ContactsContract.Contacts._ID
看看ContactsContract.Contacts._ID的注释我们也可以理解,The unique ID for a row. INTEGER (long)
显示的名字 <----------> ContactsContract.Contacts.DISPLAY_NAME
名 <----------> ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
姓 <----------> ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
看了下表的数据,data表中有条数据是
9||9|1|0|0|0|海 郭|海|郭||||||||||||||||
第三列对应于mimetype,查下mimetype表之后9对应于vnd.android.cursor.item/name
那么我们只需要根据ID和类型查询出这条数据,然后再取出第九列和第十列的数据就应该OK了,第八列是显示的名字
即DATA2(名)和DATA3(姓)
SDK已经帮我们封装好了就是ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME和ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
那么读出联系人数据的代码就应该可以是如下这个样子的
private List showContacts() { Cursor cursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { String contactId = cursor .getString(cursor .getColumnIndex(ContactsContract.Contacts._ID)); String dn = cursor .getString(cursor .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); Log.v("DISPLAY NAME", dn); // ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYP,表示是姓名系 Cursor names = getContentResolver() .query( ContactsContract.Data.CONTENT_URI, null, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?", new String[] { contactId, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE }, null); // + " AND " + ContactsContract.Data.MIMETYPE + " = 9" // 非要这么写才出来,用什么数值,或者StructuredName不放在selectionArgs都出不来,想知道它是如何拼写SQL的? while (names.moveToNext()) { // 名 String gn = names .getString(names .getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)); Log.v("GIVEN NAME", gn); // 姓 String fn = names .getString(names .getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)); Log.v("FAMILY NAME", fn); // 姓名数据版本 String versions = names .getString(names .getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DATA_VERSION)); Log.v("DATA VERSION", versions); } names.close(); // 查询RawContacts,这个里面有版本号version,关键字段 Cursor raws = getContentResolver() .query( ContactsContract.RawContacts.CONTENT_URI, null, ContactsContract.RawContacts.CONTACT_ID + " = ?", new String[] { contactId, }, null); while (raws.moveToNext()) { String rawVersion = raws .getString(raws .getColumnIndex(ContactsContract.RawContacts.VERSION)); Log.v("RAW VERSION", rawVersion); } raws.close(); String hasPhone = cursor .getString(cursor .getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); if ("1".equals(hasPhone)) { Cursor phones = getContentResolver() .query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null); while (phones.moveToNext()) { String phoneNumber = phones .getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); Log.v("phone", phoneNumber); } phones.close(); } Cursor emails = getContentResolver() .query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null); while (emails.moveToNext()) { String emailAddress = emails .getString(emails .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); // 如何获取Email地址 // 为什么ADDRESS这个字段不能用?Unhide in a separate CL Log.v("email", emailAddress); String version = emails .getString(emails .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA_VERSION)); Log.v("email version", version); } emails.close(); } cursor.close(); return null; }