最近要忙于工作了,工作中的事情有点多,也没时间做UI了。不过,等过一点时间充裕。会继续推出新的学UI博客。感谢大家的关注!!!
这篇博客,主要是要介绍android联系人数据操作,讲解一些工作中遇到的一些新情况。分享给大家!
从Android2.2以后,android又经过几个版本的更新,联系人这块的操作已经发生了很大的变化。这次先讲解今天遇到两个数据操作问题:
一、联系人中IM数据怎样更新?
先看IM有哪些数据,看图:
总共类型,大概有10种,包括用户可以自定义类型。
先介绍主要的Im类中的主要的字段:
ContactsContract.Data.MIMETYPE-->ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE("vnd.android.cursor.item/im")
ContactsContract.Data.DATA5-->ContactsContract.CommonDataKinds.Im.PROTOCOL
ContactsContract.Data.DATA6-->ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL
ContactsContract.Data.DATA1-->ContactsContract.CommonDataKinds.Im.DATA (从CommonColumns继承而来)
ContactsContract.Data.DATA2-->ContactsContract.CommonDataKinds.Im.TYPE (从CommonColumns继承而来)
统一的查询Uri: ContactsContract.Data.CONTENT_URI
所有的数据存放,基本上都在ContactsContract .Data类中,如想取数据:
private static final String[] PROJECTION = new String[] {
Data.CONTACT_ID,
Data.DATA1, Data.DATA2,
Data.DATA3, Data.DATA4,
Data.DATA5, Data.DATA6,
Data.DATA7, Data.DATA8,
Data.DATA9, Data.DATA10,
Data.MIMETYPE
};
查询的条件必须加上类型,如:ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
如果是查询IM数据,则需要关心,以下几个字段:
Data.RAW_CONTACT_ID表示联系人的ID
Data.MIMETYPE:表示mime类型,查im则类型为:Im.CONTENT_ITEM_TYPE
Data.DATA1:表示用户填写的数据,如:是QQ类型,则此为QQ号:123456789
Data.DATA2:表示数据类型,个人感觉是源码中对应的此类型:(目前手机中读取出来的值都为3)
public static final int TYPE_HOME = 1;
public static final int TYPE_WORK = 2;
public static final int TYPE_OTHER = 3;
也看图,有图有真相:
添加数据图:
两条基本数据,一条自定义数据。
看看数据库中的结果图:
data2就是type,是不是都是3啊(用手机测试,也是这个值)。
Data.DATA5:在源码中是Im.PROTOCOL:它才表示的是真正的类型,如源码中对应的类型:
public static final int PROTOCOL_CUSTOM = -1;
public static final int PROTOCOL_AIM = 0;
public static final int PROTOCOL_MSN = 1;
public static final int PROTOCOL_YAHOO = 2;
public static final int PROTOCOL_SKYPE = 3;
public static final int PROTOCOL_QQ = 4;
public static final int PROTOCOL_GOOGLE_TALK = 5;
public static final int PROTOCOL_ICQ = 6;
public static final int PROTOCOL_JABBER = 7;
public static final int PROTOCOL_NETMEETING = 8;
而当PROTOCOL的取值为-1时,则要取出Data.DATA6的值。
Data.DATA6 :在源码中是Im.CUSTOM_PROTOCOL字段,它表示是用户自定义的值,
也就是只有data5为-1时,这个取取出来才不是null(上图能很好的证明了)
基本上只要了解这几个字段,就能正确的完成Im数据的操作。
二、怎样更新Website数据?
下面,再介绍一个很是纠结的数据:Website
website在手机中,是可以插入多条数据,但在操作的数据库,是不能区分多条数据(不知道为啥)。
做项目,当然不能凭感觉说话,要找到证据才能说明问题,这时候,当然去看数据库,有图有真相:
这是我编辑的两条数据,也没有类型选择。所以,用类型区分是不可能的。此点已证明。
接下来看数据库中保存的内容,看看最终保存的结果,就知道结果:
从上面的数据,可以看出来保存的数据,也没有字段区分这两条数据。所以,再一次证明,推论正确。
这是website的问题,但下面看一下Website需要操作的字段:
Data.MIMETYPE:表示mime类型,查Website类型为:Website.CONTENT_ITEM_TYPE
Website.TYPE:表示类型,对应的类型如下:(但手机中都对应的是7,感觉基本无用)
website操作结论:要想实现更新,就只能先删除,再重新插入。
这两个类型数据,比较简单,只要知道操作哪些数据了,基本就没什么问题了。
操作的代码不在电脑上,所以,就不上传了。如果大家对此有任何疑问,欢迎一起讨论!!!
后续,还会再研究联系人中的其它字段。欢迎大家关注了,如发现有错误的地方,欢迎指正!!!
修正:
Website数据,它的源码:
/** MIME type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
public static final int TYPE_HOMEPAGE = 1;
public static final int TYPE_BLOG = 2;
public static final int TYPE_PROFILE = 3;
public static final int TYPE_HOME = 4;
public static final int TYPE_WORK = 5;
public static final int TYPE_FTP = 6;
public static final int TYPE_OTHER = 7;
/**
* The website URL string.
* <P>Type: TEXT</P>
*/
public static final String URL = DATA;
这个类中的主要数据只有这些,其实看到它定义了类型,就知道,它应该也可以添加为多条。
在以前的分析中,由于只是在模拟器中分析,发现它不能添加多条,所以,就有一个错误的地方。
现在在moto里程碑二中,是有多条数据的。所以,它的type和label也是有用的。
在此说明一下。
补充:Im说明
文章前面讲述了从源码中的一些字段说明,这里要再提一下的是,对于相同类型的数据,在data表中只能通过_id
来标识,除此之外,想要通过其它字段做更新,是不可行的。
如下图,添加的两条数据:
被红线圈的数据,就是类型一样的数据。除了 id是无法区分的。
后面要纠正上文对Im解释中的一些问题:
public static final class Im implements DataColumnsWithJoins, CommonColumns {
/**
* This utility class cannot be instantiated
*/
private Im() {}
/** MIME type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
public static final int TYPE_HOME = 1;
public static final int TYPE_WORK = 2;
public static final int TYPE_OTHER = 3;
/**
* This column should be populated with one of the defined
* constants, e.g. {@link #PROTOCOL_YAHOO}. If the value of this
* column is {@link #PROTOCOL_CUSTOM}, the {@link #CUSTOM_PROTOCOL}
* should contain the name of the custom protocol.
*/
public static final String PROTOCOL = DATA5;
public static final String CUSTOM_PROTOCOL = DATA6;
/*
* The predefined IM protocol types.
*/
public static final int PROTOCOL_CUSTOM = -1;
public static final int PROTOCOL_AIM = 0;
public static final int PROTOCOL_MSN = 1;
public static final int PROTOCOL_YAHOO = 2;
public static final int PROTOCOL_SKYPE = 3;
public static final int PROTOCOL_QQ = 4;
public static final int PROTOCOL_GOOGLE_TALK = 5;
public static final int PROTOCOL_ICQ = 6;
public static final int PROTOCOL_JABBER = 7;
public static final int PROTOCOL_NETMEETING = 8;
/**
* Return the string resource that best describes the given
* {@link #TYPE}. Will always return a valid resource.
*/
public static final int getTypeLabelResource(int type) {
switch (type) {
case TYPE_HOME: return com.android.internal.R.string.imTypeHome;
case TYPE_WORK: return com.android.internal.R.string.imTypeWork;
case TYPE_OTHER: return com.android.internal.R.string.imTypeOther;
default: return com.android.internal.R.string.imTypeCustom;
}
}
/**
* Return a {@link CharSequence} that best describes the given type,
* possibly substituting the given {@link #LABEL} value
* for {@link #TYPE_CUSTOM}.
*/
public static final CharSequence getTypeLabel(Resources res, int type,
CharSequence label) {
if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
return label;
} else {
final int labelRes = getTypeLabelResource(type);
return res.getText(labelRes);
}
}
/**
* Return the string resource that best describes the given
* {@link #PROTOCOL}. Will always return a valid resource.
*/
public static final int getProtocolLabelResource(int type) {
switch (type) {
case PROTOCOL_AIM: return com.android.internal.R.string.imProtocolAim;
case PROTOCOL_MSN: return com.android.internal.R.string.imProtocolMsn;
case PROTOCOL_YAHOO: return com.android.internal.R.string.imProtocolYahoo;
case PROTOCOL_SKYPE: return com.android.internal.R.string.imProtocolSkype;
case PROTOCOL_QQ: return com.android.internal.R.string.imProtocolQq;
case PROTOCOL_GOOGLE_TALK: return com.android.internal.R.string.imProtocolGoogleTalk;
case PROTOCOL_ICQ: return com.android.internal.R.string.imProtocolIcq;
case PROTOCOL_JABBER: return com.android.internal.R.string.imProtocolJabber;
case PROTOCOL_NETMEETING: return com.android.internal.R.string.imProtocolNetMeeting;
default: return com.android.internal.R.string.imProtocolCustom;
}
}
/**
* Return a {@link CharSequence} that best describes the given
* protocol, possibly substituting the given
* {@link #CUSTOM_PROTOCOL} value for {@link #PROTOCOL_CUSTOM}.
*/
public static final CharSequence getProtocolLabel(Resources res, int type,
CharSequence label) {
if (type == PROTOCOL_CUSTOM && !TextUtils.isEmpty(label)) {
return label;
} else {
final int labelRes = getProtocolLabelResource(type);
return res.getText(labelRes);
}
}
}
这是Im字段的源码。其实它有Type字段,在数据表中是Data.data2表示。
当Type为Custom(为0)的时候,这时就是自定义的数据类型。这个时候
自定义的名称为Label,存在Data.data3字段中。
而这里需要说明的一点是,Im是有一个PROTOCOL字段,用Data.data5存储。
它表示是哪种协议的Im,如QQ、skype等。
如果是自定义类型的,则在CUSTOM_PROTOCOL,也就是Data.data6字段中,存有一份和data3一样的数据。
所以,对im操作,首先要注意:data2的数据类型。若为自定义的,就要取label值。
接着要注意:data5的值,它能判断出来是哪种Im.
这些说明,希望能帮助大家更好的理解数据库表,如有问题,欢迎交流!!!