am 8b12144d: Merge change I170c8251 into eclair-mr2

Merge commit '8b12144dad94bc0807e20590d72b4aadc56189d4' into eclair-mr2-plus-aosp

* commit '8b12144dad94bc0807e20590d72b4aadc56189d4':
  Add tests and fix vCard code.
This commit is contained in:
Daisuke Miyakawa
2009-10-14 16:46:09 -07:00
committed by Android Git Automerger
9 changed files with 1749 additions and 505 deletions

View File

@@ -56,7 +56,7 @@ package android.pim.vcard;
public static final String PROPERTY_X_PHONETIC_MIDDLE_NAME = "X-PHONETIC-MIDDLE-NAME";
public static final String PROPERTY_X_PHONETIC_LAST_NAME = "X-PHONETIC-LAST-NAME";
// Properties both the current (as of 2009-08-17) ContactsStruct and de-fact vCard extensions
// Properties both ContactsStruct in Eclair and de-fact vCard extensions
// shown in http://en.wikipedia.org/wiki/VCard support are defined here.
public static final String PROPERTY_X_AIM = "X-AIM";
public static final String PROPERTY_X_MSN = "X-MSN";
@@ -65,15 +65,12 @@ package android.pim.vcard;
public static final String PROPERTY_X_JABBER = "X-JABBER";
public static final String PROPERTY_X_GOOGLE_TALK = "X-GOOGLE-TALK";
public static final String PROPERTY_X_SKYPE_USERNAME = "X-SKYPE-USERNAME";
// Properties only ContactsStruct has. We alse use this.
public static final String PROPERTY_X_QQ = "X-QQ";
public static final String PROPERTY_X_NETMEETING = "X-NETMEETING";
// Phone number for Skype, available as usual phone.
public static final String PROPERTY_X_SKYPE_PSTNNUMBER = "X-SKYPE-PSTNNUMBER";
// Some device emits this "X-" attribute, which is specifically invalid but should be
// always properly accepted, and emitted in some special case (for that device/application).
public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
// Android specific properties
// Use only in vCard paser code.
public static final String PROPERTY_X_NICKNAME = "X-NICKNAME";
// Properties for DoCoMo vCard.
public static final String PROPERTY_X_CLASS = "X-CLASS";
@@ -81,6 +78,11 @@ package android.pim.vcard;
public static final String PROPERTY_X_NO = "X-NO";
public static final String PROPERTY_X_DCM_HMN_MODE = "X-DCM-HMN-MODE";
// For some historical reason, we often use the term "ATTR"/"attribute" especially toward
// what is called "param" in both vCard specs, while vCard, while vCard importer side uses
// "param".
//
// TODO: Confusing. Fix it.
public static final String ATTR_TYPE = "TYPE";
// How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0
@@ -102,13 +104,19 @@ package android.pim.vcard;
public static final String ATTR_TYPE_VOICE = "VOICE";
public static final String ATTR_TYPE_INTERNET = "INTERNET";
// Abbreviation of "preferable"? We interpret this value as "primary" property.
// Abbreviation of "prefered" according to vCard 2.1 specification.
// We interpret this value as "primary" property during import/export.
//
// Note: Both vCard specs does anything about the requirement about this attribute,
// but there may be some vCard importer which will get confused with more than
// one "PREF"s in one property name, while Android accepts them.
public static final String ATTR_TYPE_PREF = "PREF";
// Phone types valid in vCard and known to ContactsContract, but not so common.
public static final String ATTR_TYPE_CAR = "CAR";
public static final String ATTR_TYPE_ISDN = "ISDN";
public static final String ATTR_TYPE_PAGER = "PAGER";
public static final String ATTR_TYPE_TLX = "TLX"; // Telex
// Phone types existing in vCard 2.1 but not known to ContactsContract.
// TODO: should make parser make these TYPE_CUSTOM.
@@ -118,16 +126,16 @@ package android.pim.vcard;
public static final String ATTR_TYPE_VIDEO = "VIDEO";
// Attribute for Phones, which are not formally valid in vCard (at least 2.1).
// These types are encoded to "X-" attributes when composing vCard for now.
// Parser passes these even if "X-" is added to the attribute.
public static final String ATTR_PHONE_EXTRA_TYPE_OTHER = "OTHER";
// These types are basically encoded to "X-" attributes when composing vCard.
// Parser passes these when "X-" is added to the attribute or not.
public static final String ATTR_PHONE_EXTRA_TYPE_CALLBACK = "CALLBACK";
// TODO: may be "TYPE=COMPANY,PREF", not "COMPANY-MAIN".
public static final String ATTR_PHONE_EXTRA_TYPE_COMPANY_MAIN = "COMPANY-MAIN";
public static final String ATTR_PHONE_EXTRA_TYPE_RADIO = "RADIO";
public static final String ATTR_PHONE_EXTRA_TYPE_TELEX = "TELEX";
public static final String ATTR_PHONE_EXTRA_TYPE_TTY_TDD = "TTY-TDD";
public static final String ATTR_PHONE_EXTRA_TYPE_ASSISTANT = "ASSISTANT";
// vCard composer translates this type to "WORK" + "PREF". Just for parsing.
public static final String ATTR_PHONE_EXTRA_TYPE_COMPANY_MAIN = "COMPANY-MAIN";
// vCard composer translates this type to "VOICE" Just for parsing.
public static final String ATTR_PHONE_EXTRA_TYPE_OTHER = "OTHER";
// Attribute for addresses.
public static final String ATTR_ADR_TYPE_PARCEL = "PARCEL";
@@ -142,6 +150,14 @@ package android.pim.vcard;
// vCard 3.0.
public static final String ATTR_TYPE_X_IRMC_N = "X-IRMC-N";
public interface ImportOnly {
public static final String PROPERTY_X_NICKNAME = "X-NICKNAME";
// Some device emits this "X-" attribute for expressing Google Talk,
// which is specifically invalid but should be always properly accepted, and emitted
// in some special case (for that device/application).
public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
}
private Constants() {
}
}

View File

@@ -68,7 +68,8 @@ public class ContactStruct {
sImMap.put(Constants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER);
sImMap.put(Constants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE);
sImMap.put(Constants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK);
sImMap.put(Constants.PROPERTY_X_GOOGLE_TALK_WITH_SPACE, Im.PROTOCOL_GOOGLE_TALK);
sImMap.put(Constants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE,
Im.PROTOCOL_GOOGLE_TALK);
}
static public class PhoneData {
@@ -292,16 +293,18 @@ public class ContactStruct {
}
static public class ImData {
public final int protocol;
public final String customProtocol;
public final int type;
public final String data;
public final String label;
public final boolean isPrimary;
// TODO: ContactsConstant#PROTOCOL, ContactsConstant#CUSTOM_PROTOCOL should be used?
public ImData(int type, String data, String label, boolean isPrimary) {
public ImData(int protocol, String customProtocol, int type,
String data, boolean isPrimary) {
this.protocol = protocol;
this.customProtocol = customProtocol;
this.type = type;
this.data = data;
this.label = label;
this.isPrimary = isPrimary;
}
@@ -311,14 +314,18 @@ public class ContactStruct {
return false;
}
ImData imData = (ImData)obj;
return (type == imData.type && data.equals(imData.data) &&
label.equals(imData.label) && isPrimary == imData.isPrimary);
return (type == imData.type && protocol == imData.protocol
&& (customProtocol != null ? customProtocol.equals(imData.customProtocol) :
(imData.customProtocol == null))
&& (data != null ? data.equals(imData.data) : (imData.data == null))
&& isPrimary == imData.isPrimary);
}
@Override
public String toString() {
return String.format("type: %d, data: %s, label: %s, isPrimary: %s",
type, data, label, isPrimary);
return String.format(
"type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s",
type, protocol, customProtocol, data, isPrimary);
}
}
@@ -440,7 +447,7 @@ public class ContactStruct {
private final Account mAccount;
public ContactStruct() {
this(VCardConfig.VCARD_TYPE_V21_GENERIC);
this(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
}
public ContactStruct(int vcardType) {
@@ -619,11 +626,12 @@ public class ContactStruct {
addNewOrganization(DEFAULT_ORGANIZATION_TYPE, null, null, title, false);
}
private void addIm(int type, String data, String label, boolean isPrimary) {
private void addIm(int protocol, String customProtocol, int type,
String propValue, boolean isPrimary) {
if (mImList == null) {
mImList = new ArrayList<ImData>();
}
mImList.add(new ImData(type, data, label, isPrimary));
mImList.add(new ImData(protocol, customProtocol, type, propValue, isPrimary));
}
private void addNote(final String note) {
@@ -720,7 +728,7 @@ public class ContactStruct {
} else if (propName.equals(Constants.PROPERTY_NICKNAME)) {
mPhoneticFullName = propValue;
} else if (propName.equals(Constants.PROPERTY_NICKNAME) ||
propName.equals(Constants.PROPERTY_X_NICKNAME)) {
propName.equals(Constants.ImportOnly.PROPERTY_X_NICKNAME)) {
addNickName(propValue);
} else if (propName.equals(Constants.PROPERTY_SOUND)) {
Collection<String> typeCollection = paramMap.get(Constants.ATTR_TYPE);
@@ -891,25 +899,28 @@ public class ContactStruct {
isPrimary = false;
}
addPhone(type, propValue, label, isPrimary);
} else if (sImMap.containsKey(propName)){
int type = sImMap.get(propName);
} else if (sImMap.containsKey(propName)) {
final int protocol = sImMap.get(propName);
boolean isPrimary = false;
int type = -1;
final Collection<String> typeCollection = paramMap.get(Constants.ATTR_TYPE);
if (typeCollection != null) {
for (String typeString : typeCollection) {
if (typeString.equals(Constants.ATTR_TYPE_PREF)) {
isPrimary = true;
} else if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_HOME)) {
type = Phone.TYPE_HOME;
} else if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_WORK)) {
type = Phone.TYPE_WORK;
} else if (type < 0) {
if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_HOME)) {
type = Im.TYPE_HOME;
} else if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_WORK)) {
type = Im.TYPE_WORK;
}
}
}
}
if (type < 0) {
type = Phone.TYPE_HOME;
}
addIm(type, propValue, null, isPrimary);
addIm(protocol, null, type, propValue, isPrimary);
} else if (propName.equals(Constants.PROPERTY_NOTE)) {
addNote(propValue);
} else if (propName.equals(Constants.PROPERTY_URL)) {
@@ -1158,10 +1169,10 @@ public class ContactStruct {
builder.withValueBackReference(Im.RAW_CONTACT_ID, 0);
builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
builder.withValue(Im.TYPE, imData.type);
if (imData.type == Im.TYPE_CUSTOM) {
builder.withValue(Im.LABEL, imData.label);
builder.withValue(Im.PROTOCOL, imData.protocol);
if (imData.protocol == Im.PROTOCOL_CUSTOM) {
builder.withValue(Im.CUSTOM_PROTOCOL, imData.customProtocol);
}
builder.withValue(Im.DATA, imData.data);
if (imData.isPrimary) {
builder.withValue(Data.IS_PRIMARY, 1);
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,14 +15,20 @@
*/
package android.pim.vcard;
import android.util.Log;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* The class representing VCard related configurations. Useful static methods are not in this class
* but in VCardUtils.
*/
public class VCardConfig {
private static final String LOG_TAG = "vcard.VCardConfig";
// TODO: may be better to make the instance of this available and stop using static methods and
// one integer.
@@ -95,18 +101,63 @@ public class VCardConfig {
private static final int FLAG_DOCOMO = 0x20000000;
/**
* The flag indicating the vCard composer use Quoted-Printable toward even "primary" types.
* In this context, "primary" types means "N", "FN", etc. which are usually "not" encoded
* into Quoted-Printable format in external exporters.
* This flag is useful when some target importer does not accept "primary" property values
* without Quoted-Printable encoding.
*
* @hide Temporaly made public. We don't strictly define "primary", so we may change the
* behavior around this flag in the future. Do not use this flag without any reason.
* <P>
* The flag indicating the vCard composer does "NOT" use Quoted-Printable toward "primary"
* properties even though it is required by vCard 2.1 (QP is prohibited in vCard 3.0).
* </P>
* <P>
* We actually cannot define what is the "primary" property. Note that this is NOT defined
* in vCard specification either. Also be aware that it is NOT related to "primary" notion
* used in {@link android.provider.ContactsContract}.
* This notion is just for vCard composition in Android.
* </P>
* <P>
* We added this Android-specific notion since some (incomplete) vCard exporters for vCard 2.1
* do NOT use Quoted-Printable encoding toward some properties like "N", "FN", etc. even when
* their values contain non-ascii or/and CR/LF, while they use the encoding in the other
* properties like "ADR", "ORG", etc.
* <P>
* We are afraid of the case where some vCard importer also forget handling QP presuming QP is
* not used in such fields.
* </P>
* <P>
* This flag is useful when some target importer you are going to focus on does not accept
* such "primary" property values with Quoted-Printable encoding.
* </P>
* <P>
* Again, we should not use this flag at all for complying vCard 2.1 spec.
* </P>
* <P>
* We will change the behavior around this flag in the future, after understanding the other
* real vCard cases around this problem. Please use this flag with extreme caution even when
* needed.
* </P>
* <P>
* In vCard 3.0, Quoted-Printable is explicitly "prohibitted", so we don't need to care this
* kind of problem (hopefully).
* </P>
*/
public static final int FLAG_USE_QP_TO_PRIMARY_PROPERTIES = 0x10000000;
public static final int FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES = 0x10000000;
/**
* <P>
* The flag indicating that phonetic name related fields must be converted to
* appropriate form. Note that "appropriate" is not defined in any vCard specification.
* This is Android-specific.
* </P>
* <P>
* One typical (and currently sole) example where we need this flag is the time when
* we need to emit Japanese phonetic names into vCard entries. The property values
* should be encoded into half-width katakana when the target importer is Japanese mobile
* phones', which are probably not able to parse full-width hiragana/katakana for
* historical reasons, while the vCard importers embedded to softwares for PC should be
* able to parse them as we expect.
* </P>
*/
public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x0800000;
/**
* <P>
* The flag indicating the vCard composer "for 2.1" emits "TYPE=" string every time
* possible. The default behavior does not emit it and is valid, while adding "TYPE="
* is also valid. In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in
@@ -119,87 +170,118 @@ public class VCardConfig {
*
* e.g. int vcardType = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);
*/
public static final int FLAG_APPEND_TYPE_PARAM = 0x08000000;
public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000;
//// The followings are VCard types available from importer/exporter. ////
/**
* <P>
* General vCard format with the version 2.1. Uses UTF-8 for the charset.
* When composing a vCard entry, the US convension will be used.
*
* When composing a vCard entry, the US convension will be used toward formatting
* some values
* </P>
* <P>
* e.g. The order of the display name would be "Prefix Given Middle Family Suffix",
* while in Japan, it should be "Prefix Family Middle Given Suffix".
* while it should be "Prefix Family Middle Given Suffix" in Japan.
* </P>
*/
public static final int VCARD_TYPE_V21_GENERIC =
public static final int VCARD_TYPE_V21_GENERIC_UTF8 =
(FLAG_V21 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static String VCARD_TYPE_V21_GENERIC_STR = "v21_generic";
/* package */ static String VCARD_TYPE_V21_GENERIC_UTF8_STR = "v21_generic";
/**
* <P>
* General vCard format with the version 3.0. Uses UTF-8 for the charset.
*
* Note that this type is not fully implemented, so probably some bugs remain both in
* parsing and composing.
*
* TODO: implement this type correctly.
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V30_GENERIC =
public static final int VCARD_TYPE_V30_GENERIC_UTF8 =
(FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V30_GENERIC_STR = "v30_generic";
/* package */ static final String VCARD_TYPE_V30_GENERIC_UTF8_STR = "v30_generic";
/**
* General vCard format with the version 2.1 with some Europe convension. Uses Utf-8.
* <P>
* General vCard format for the vCard 2.1 with some Europe convension. Uses Utf-8.
* Currently, only name order is considered ("Prefix Middle Given Family Suffix")
* </P>
*/
public static final int VCARD_TYPE_V21_EUROPE =
public static final int VCARD_TYPE_V21_EUROPE_UTF8 =
(FLAG_V21 | NAME_ORDER_EUROPE | FLAG_CHARSET_UTF8 |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V21_EUROPE_STR = "v21_europe";
/* package */ static final String VCARD_TYPE_V21_EUROPE_UTF8_STR = "v21_europe";
/**
* <P>
* General vCard format with the version 3.0 with some Europe convension. Uses UTF-8
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V30_EUROPE =
public static final int VCARD_TYPE_V30_EUROPE_UTF8 =
(FLAG_V30 | NAME_ORDER_EUROPE | FLAG_CHARSET_UTF8 |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V30_EUROPE_STR = "v30_europe";
/**
* vCard 2.1 format for miscellaneous Japanese devices. Shift_Jis is used for
* parsing/composing the vCard data.
*/
public static final int VCARD_TYPE_V21_JAPANESE =
(FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V21_JAPANESE_STR = "v21_japanese";
/**
* vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset.
* <P>
* The vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset.
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V21_JAPANESE_UTF8 =
(FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_UTF8 |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V21_JAPANESE_UTF8_STR = "v21_japanese_utf8";
/**
* <P>
* vCard 2.1 format for miscellaneous Japanese devices. Shift_Jis is used for
* parsing/composing the vCard data.
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V21_JAPANESE_SJIS =
(FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V21_JAPANESE_SJIS_STR = "v21_japanese_sjis";
/**
* <P>
* vCard format for miscellaneous Japanese devices, using Shift_Jis for
* parsing/composing the vCard data.
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V30_JAPANESE =
public static final int VCARD_TYPE_V30_JAPANESE_SJIS =
(FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
/* package */ static final String VCARD_TYPE_V30_JAPANESE_STR = "v30_japanese";
/* package */ static final String VCARD_TYPE_V30_JAPANESE_SJIS_STR = "v30_japanese_sjis";
/**
* vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset.
* <P>
* The vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset.
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V30_JAPANESE_UTF8 =
(FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_CHARSET_UTF8 |
@@ -208,38 +290,72 @@ public class VCardConfig {
/* package */ static final String VCARD_TYPE_V30_JAPANESE_UTF8_STR = "v30_japanese_utf8";
/**
* VCard format used in DoCoMo, which is one of Japanese mobile phone careers.
* Base version is vCard 2.1, but the data has several DoCoMo-specific convensions.
* No Android-specific property nor defact property is included.
* <P>
* The vCard 2.1 based format which (partially) considers the convention in Japanese
* mobile phones, where phonetic names are translated to half-width katakana if
* possible, etc.
* </P>
* <P>
* Not ready yet. Use with caution when you use this.
* </P>
*/
public static final int VCARD_TYPE_V21_JAPANESE_MOBILE =
(FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
FLAG_CONVERT_PHONETIC_NAME_STRINGS |
FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES);
public static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile";
/**
* <P>
* VCard format used in DoCoMo, which is one of Japanese mobile phone careers.
* </p>
* <P>
* Base version is vCard 2.1, but the data has several DoCoMo-specific convensions.
* No Android-specific property nor defact property is included. The "Primary" properties
* are NOT encoded to Quoted-Printable.
* </P>
*/
public static final int VCARD_TYPE_DOCOMO =
(FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS | FLAG_DOCOMO);
(VCARD_TYPE_V21_JAPANESE_MOBILE | FLAG_DOCOMO);
private static final String VCARD_TYPE_DOCOMO_STR = "docomo";
public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC;
public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC_UTF8;
private static final Map<String, Integer> VCARD_TYPES_MAP;
private static final Map<String, Integer> sVCardTypeMap;
private static final Set<Integer> sJapaneseMobileTypeSet;
static {
VCARD_TYPES_MAP = new HashMap<String, Integer>();
VCARD_TYPES_MAP.put(VCARD_TYPE_V21_GENERIC_STR, VCARD_TYPE_V21_GENERIC);
VCARD_TYPES_MAP.put(VCARD_TYPE_V30_GENERIC_STR, VCARD_TYPE_V30_GENERIC);
VCARD_TYPES_MAP.put(VCARD_TYPE_V21_EUROPE_STR, VCARD_TYPE_V21_EUROPE);
VCARD_TYPES_MAP.put(VCARD_TYPE_V30_EUROPE_STR, VCARD_TYPE_V30_EUROPE);
VCARD_TYPES_MAP.put(VCARD_TYPE_V21_JAPANESE_STR, VCARD_TYPE_V21_JAPANESE);
VCARD_TYPES_MAP.put(VCARD_TYPE_V21_JAPANESE_UTF8_STR, VCARD_TYPE_V21_JAPANESE_UTF8);
VCARD_TYPES_MAP.put(VCARD_TYPE_V30_JAPANESE_STR, VCARD_TYPE_V30_JAPANESE);
VCARD_TYPES_MAP.put(VCARD_TYPE_V30_JAPANESE_UTF8_STR, VCARD_TYPE_V30_JAPANESE_UTF8);
VCARD_TYPES_MAP.put(VCARD_TYPE_DOCOMO_STR, VCARD_TYPE_DOCOMO);
sVCardTypeMap = new HashMap<String, Integer>();
sVCardTypeMap.put(VCARD_TYPE_V21_GENERIC_UTF8_STR, VCARD_TYPE_V21_GENERIC_UTF8);
sVCardTypeMap.put(VCARD_TYPE_V30_GENERIC_UTF8_STR, VCARD_TYPE_V30_GENERIC_UTF8);
sVCardTypeMap.put(VCARD_TYPE_V21_EUROPE_UTF8_STR, VCARD_TYPE_V21_EUROPE_UTF8);
sVCardTypeMap.put(VCARD_TYPE_V30_EUROPE_STR, VCARD_TYPE_V30_EUROPE_UTF8);
sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_SJIS_STR, VCARD_TYPE_V21_JAPANESE_SJIS);
sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_UTF8_STR, VCARD_TYPE_V21_JAPANESE_UTF8);
sVCardTypeMap.put(VCARD_TYPE_V30_JAPANESE_SJIS_STR, VCARD_TYPE_V30_JAPANESE_SJIS);
sVCardTypeMap.put(VCARD_TYPE_V30_JAPANESE_UTF8_STR, VCARD_TYPE_V30_JAPANESE_UTF8);
sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_MOBILE_STR, VCARD_TYPE_V21_JAPANESE_MOBILE);
sVCardTypeMap.put(VCARD_TYPE_DOCOMO_STR, VCARD_TYPE_DOCOMO);
sJapaneseMobileTypeSet = new HashSet<Integer>();
sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_SJIS);
sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_UTF8);
sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_SJIS);
sJapaneseMobileTypeSet.add(VCARD_TYPE_V30_JAPANESE_SJIS);
sJapaneseMobileTypeSet.add(VCARD_TYPE_V30_JAPANESE_UTF8);
sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_MOBILE);
sJapaneseMobileTypeSet.add(VCARD_TYPE_DOCOMO);
}
public static int getVCardTypeFromString(String vcardTypeString) {
String loweredKey = vcardTypeString.toLowerCase();
if (VCARD_TYPES_MAP.containsKey(loweredKey)) {
return VCARD_TYPES_MAP.get(loweredKey);
if (sVCardTypeMap.containsKey(loweredKey)) {
return sVCardTypeMap.get(loweredKey);
} else {
// XXX: should return the value indicating the input is invalid?
Log.e(LOG_TAG, "Unknown vCard type String: \"" + vcardTypeString + "\"");
return VCARD_TYPE_DEFAULT;
}
}
@@ -252,22 +368,6 @@ public class VCardConfig {
return !isV30(vcardType);
}
public static boolean isDoCoMo(int vcardType) {
return ((vcardType & FLAG_DOCOMO) != 0);
}
/**
* @return true if the device is Japanese and some Japanese convension is
* applied to creating "formatted" something like FORMATTED_ADDRESS.
*/
public static boolean isJapaneseDevice(int vcardType) {
return ((vcardType == VCARD_TYPE_V21_JAPANESE) ||
(vcardType == VCARD_TYPE_V21_JAPANESE_UTF8) ||
(vcardType == VCARD_TYPE_V30_JAPANESE) ||
(vcardType == VCARD_TYPE_V30_JAPANESE_UTF8) ||
(vcardType == VCARD_TYPE_DOCOMO));
}
public static boolean usesUtf8(int vcardType) {
return ((vcardType & FLAG_CHARSET_UTF8) != 0);
}
@@ -276,17 +376,6 @@ public class VCardConfig {
return ((vcardType & FLAG_CHARSET_SHIFT_JIS) != 0);
}
/**
* @return true when Japanese phonetic string must be converted to a string
* containing only half-width katakana. This method exists since Japanese mobile
* phones usually use only half-width katakana for expressing phonetic names and
* some devices are not ready for parsing other phonetic strings like hiragana and
* full-width katakana.
*/
public static boolean needsToConvertPhoneticString(int vcardType) {
return (vcardType == VCARD_TYPE_DOCOMO);
}
public static int getNameOrderType(int vcardType) {
return vcardType & NAME_ORDER_MASK;
}
@@ -299,24 +388,37 @@ public class VCardConfig {
return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0);
}
public static boolean onlyOneNoteFieldIsAvailable(int vcardType) {
return vcardType == VCARD_TYPE_DOCOMO;
}
public static boolean showPerformanceLog() {
return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0;
}
/**
* @hide
*/
public static boolean usesQPToPrimaryProperties(int vcardType) {
return (usesQuotedPrintable(vcardType) &&
((vcardType & FLAG_USE_QP_TO_PRIMARY_PROPERTIES) != 0));
public static boolean refrainsQPToPrimaryProperties(int vcardType) {
return (!usesQuotedPrintable(vcardType) ||
((vcardType & FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES) != 0));
}
public static boolean appendTypeParamName(int vcardType) {
return (vcardType & FLAG_APPEND_TYPE_PARAM) != 0;
return (isV30(vcardType) || ((vcardType & FLAG_APPEND_TYPE_PARAM) != 0));
}
/**
* @return true if the device is Japanese and some Japanese convension is
* applied to creating "formatted" something like FORMATTED_ADDRESS.
*/
public static boolean isJapaneseDevice(int vcardType) {
return sJapaneseMobileTypeSet.contains(vcardType);
}
public static boolean needsToConvertPhoneticString(int vcardType) {
return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0);
}
public static boolean onlyOneNoteFieldIsAvailable(int vcardType) {
return vcardType == VCARD_TYPE_DOCOMO;
}
public static boolean isDoCoMo(int vcardType) {
return ((vcardType & FLAG_DOCOMO) != 0);
}
private VCardConfig() {

View File

@@ -69,7 +69,7 @@ public class VCardDataBuilder implements VCardBuilder {
private List<EntryHandler> mEntryHandlers = new ArrayList<EntryHandler>();
public VCardDataBuilder() {
this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC, null);
this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8, null);
}
/**

View File

@@ -18,6 +18,7 @@ package android.pim.vcard;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.text.TextUtils;
@@ -44,38 +45,49 @@ public class VCardUtils {
private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS;
private static final Set<String> sPhoneTypesSetUnknownToContacts;
private static final Map<String, Integer> sKnownPhoneTypesMap_StoI;
private static final Map<String, Integer> sKnownPhoneTypeMap_StoI;
private static final Map<Integer, String> sKnownImPropNameMap_ItoS;
static {
sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>();
sKnownPhoneTypesMap_StoI = new HashMap<String, Integer>();
sKnownPhoneTypeMap_StoI = new HashMap<String, Integer>();
sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_CAR, Constants.ATTR_TYPE_CAR);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_CAR, Phone.TYPE_CAR);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_CAR, Phone.TYPE_CAR);
sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_PAGER, Constants.ATTR_TYPE_PAGER);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PAGER, Phone.TYPE_PAGER);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_PAGER, Phone.TYPE_PAGER);
sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_ISDN, Constants.ATTR_TYPE_ISDN);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_ISDN, Phone.TYPE_ISDN);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_ISDN, Phone.TYPE_ISDN);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_HOME, Phone.TYPE_HOME);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_WORK, Phone.TYPE_WORK);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_CELL, Phone.TYPE_MOBILE);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_HOME, Phone.TYPE_HOME);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_WORK, Phone.TYPE_WORK);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_CELL, Phone.TYPE_MOBILE);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_CALLBACK, Phone.TYPE_CALLBACK);
sKnownPhoneTypesMap_StoI.put(
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_CALLBACK, Phone.TYPE_CALLBACK);
sKnownPhoneTypeMap_StoI.put(
Constants.ATTR_PHONE_EXTRA_TYPE_COMPANY_MAIN, Phone.TYPE_COMPANY_MAIN);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_TELEX, Phone.TYPE_TELEX);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_TTY_TDD, Phone.TYPE_TTY_TDD);
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_ASSISTANT,
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_TTY_TDD, Phone.TYPE_TTY_TDD);
sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_ASSISTANT,
Phone.TYPE_ASSISTANT);
sPhoneTypesSetUnknownToContacts = new HashSet<String>();
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_MODEM);
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_MSG);
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_BBS);
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_VIDEO);
sKnownImPropNameMap_ItoS = new HashMap<Integer, String>();
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, Constants.PROPERTY_X_AIM);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_MSN, Constants.PROPERTY_X_MSN);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_YAHOO, Constants.PROPERTY_X_YAHOO);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_SKYPE, Constants.PROPERTY_X_SKYPE_USERNAME);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_GOOGLE_TALK, Constants.PROPERTY_X_GOOGLE_TALK);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_ICQ, Constants.PROPERTY_X_ICQ);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, Constants.PROPERTY_X_QQ);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, Constants.PROPERTY_X_NETMEETING);
}
public static String getPhoneAttributeString(Integer type) {
@@ -103,7 +115,7 @@ public class VCardUtils {
if (typeString.startsWith("X-") && type < 0) {
typeString = typeString.substring(2);
}
Integer tmp = sKnownPhoneTypesMap_StoI.get(typeString);
Integer tmp = sKnownPhoneTypeMap_StoI.get(typeString);
if (tmp != null) {
type = tmp;
} else if (type < 0) {
@@ -136,7 +148,11 @@ public class VCardUtils {
return type;
}
}
public static String getPropertyNameForIm(int protocol) {
return sKnownImPropNameMap_ItoS.get(protocol);
}
public static boolean isValidPhoneAttribute(String phoneAttribute, int vcardType) {
// TODO: check the following.
// - it may violate vCard spec
@@ -206,12 +222,12 @@ public class VCardUtils {
builder.withValue(Data.IS_PRIMARY, 1);
}
}
/**
* Returns String[] containing address information based on vCard spec
* (PO Box, Extended Address, Street, Locality, Region, Postal Code, Country Name).
* All String objects are non-null ("" is used when the relevant data is empty).
*
*
* Note that the data structure of ContactsContract is different from that defined in vCard.
* So some conversion may be performed in this method. See also
* {{@link #insertStructuredPostalDataUsingContactsStruct(int,
@@ -219,13 +235,20 @@ public class VCardUtils {
* android.pim.vcard.ContactStruct.PostalData)}
*/
public static String[] getVCardPostalElements(ContentValues contentValues) {
// adr-value = 0*6(text-value ";") text-value
// ; PO Box, Extended Address, Street, Locality, Region, Postal
// ; Code, Country Name
String[] dataArray = new String[7];
dataArray[0] = contentValues.getAsString(StructuredPostal.POBOX);
if (dataArray[0] == null) {
dataArray[0] = "";
}
// Extended addr. There's no relevant data in ContactsContract.
dataArray[1] = "";
// We keep all the data in StructuredPostal, presuming NEIGHBORHOOD is
// similar to "Extended Address".
dataArray[1] = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD);
if (dataArray[1] == null) {
dataArray[1] = "";
}
dataArray[2] = contentValues.getAsString(StructuredPostal.STREET);
if (dataArray[2] == null) {
dataArray[2] = "";