am ca103c16: Merge change I6ce46417 into eclair-mr2
Merge commit 'ca103c16d80aba1a9535e2eb4e13283258426395' into eclair-mr2-plus-aosp * commit 'ca103c16d80aba1a9535e2eb4e13283258426395': Clean-up vCard code.
This commit is contained in:
@@ -16,15 +16,46 @@
|
||||
package android.pim.vcard;
|
||||
|
||||
/**
|
||||
* Constants used in both composer and parser.
|
||||
* Constants used in both exporter and importer code.
|
||||
*/
|
||||
/* package */ class Constants {
|
||||
|
||||
public static final String ATTR_TYPE = "TYPE";
|
||||
|
||||
public static final String VERSION_V21 = "2.1";
|
||||
public static final String VERSION_V30 = "3.0";
|
||||
|
||||
// The property names valid both in vCard 2.1 and 3.0.
|
||||
public static final String PROPERTY_BEGIN = "BEGIN";
|
||||
public static final String PROPERTY_VERSION = "VERSION";
|
||||
public static final String PROPERTY_N = "N";
|
||||
public static final String PROPERTY_FN = "FN";
|
||||
public static final String PROPERTY_ADR = "ADR";
|
||||
public static final String PROPERTY_EMAIL = "EMAIL";
|
||||
public static final String PROPERTY_NOTE = "NOTE";
|
||||
public static final String PROPERTY_ORG = "ORG";
|
||||
public static final String PROPERTY_SOUND = "SOUND"; // Not fully supported.
|
||||
public static final String PROPERTY_TEL = "TEL";
|
||||
public static final String PROPERTY_TITLE = "TITLE";
|
||||
public static final String PROPERTY_ROLE = "ROLE";
|
||||
public static final String PROPERTY_PHOTO = "PHOTO";
|
||||
public static final String PROPERTY_LOGO = "LOGO";
|
||||
public static final String PROPERTY_URL = "URL";
|
||||
public static final String PROPERTY_BDAY = "BDAY"; // Birthday
|
||||
public static final String PROPERTY_END = "END";
|
||||
|
||||
// Valid property names not supported (not appropriately handled) by our vCard importer now.
|
||||
public static final String PROPERTY_REV = "REV";
|
||||
public static final String PROPERTY_AGENT = "AGENT";
|
||||
|
||||
// Available in vCard 3.0. Shoud not use when composing vCard 2.1 file.
|
||||
public static final String PROPERTY_NAME = "NAME";
|
||||
public static final String PROPERTY_NICKNAME = "NICKNAME";
|
||||
public static final String PROPERTY_SORT_STRING = "SORT-STRING";
|
||||
|
||||
// De-fact property values expressing phonetic names.
|
||||
public static final String PROPERTY_X_PHONETIC_FIRST_NAME = "X-PHONETIC-FIRST-NAME";
|
||||
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
|
||||
// shown in http://en.wikipedia.org/wiki/VCard support are defined here.
|
||||
public static final String PROPERTY_X_AIM = "X-AIM";
|
||||
@@ -39,7 +70,19 @@ package android.pim.vcard;
|
||||
// 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";
|
||||
public static final String PROPERTY_X_REDUCTION = "X-REDUCTION";
|
||||
public static final String PROPERTY_X_NO = "X-NO";
|
||||
public static final String PROPERTY_X_DCM_HMN_MODE = "X-DCM-HMN-MODE";
|
||||
|
||||
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
|
||||
//
|
||||
// e.g.
|
||||
@@ -59,6 +102,7 @@ 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.
|
||||
public static final String ATTR_TYPE_PREF = "PREF";
|
||||
|
||||
// Phone types valid in vCard and known to ContactsContract, but not so common.
|
||||
@@ -73,17 +117,26 @@ package android.pim.vcard;
|
||||
public static final String ATTR_TYPE_BBS = "BBS";
|
||||
public static final String ATTR_TYPE_VIDEO = "VIDEO";
|
||||
|
||||
// Phone types existing in the current Contacts structure but not valid in vCard (at least 2.1)
|
||||
// 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_TYPE_PHONE_EXTRA_OTHER = "OTHER";
|
||||
public static final String ATTR_TYPE_PHONE_EXTRA_CALLBACK = "CALLBACK";
|
||||
public static final String ATTR_PHONE_EXTRA_TYPE_OTHER = "OTHER";
|
||||
public static final String ATTR_PHONE_EXTRA_TYPE_CALLBACK = "CALLBACK";
|
||||
// TODO: may be "TYPE=COMPANY,PREF", not "COMPANY-MAIN".
|
||||
public static final String ATTR_TYPE_PHONE_EXTRA_COMPANY_MAIN = "COMPANY-MAIN";
|
||||
public static final String ATTR_TYPE_PHONE_EXTRA_RADIO = "RADIO";
|
||||
public static final String ATTR_TYPE_PHONE_EXTRA_TELEX = "TELEX";
|
||||
public static final String ATTR_TYPE_PHONE_EXTRA_TTY_TDD = "TTY-TDD";
|
||||
public static final String ATTR_TYPE_PHONE_EXTRA_ASSISTANT = "ASSISTANT";
|
||||
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";
|
||||
|
||||
// Attribute for addresses.
|
||||
public static final String ATTR_ADR_TYPE_PARCEL = "PARCEL";
|
||||
public static final String ATTR_ADR_TYPE_DOM = "DOM";
|
||||
public static final String ATTR_ADR_TYPE_INTL = "INTL";
|
||||
|
||||
// Attribute types not officially valid but used in some vCard exporter.
|
||||
// Do not use in composer side.
|
||||
public static final String ATTR_EXTRA_TYPE_COMPANY = "COMPANY";
|
||||
|
||||
// DoCoMo specific attribute. Used with "SOUND" property, which is alternate of SORT-STRING in
|
||||
// vCard 3.0.
|
||||
|
||||
@@ -71,9 +71,6 @@ public class ContactStruct {
|
||||
sImMap.put(Constants.PROPERTY_X_GOOGLE_TALK_WITH_SPACE, Im.PROTOCOL_GOOGLE_TALK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide only for testing
|
||||
*/
|
||||
static public class PhoneData {
|
||||
public final int type;
|
||||
public final String data;
|
||||
@@ -251,9 +248,6 @@ public class ContactStruct {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide only for testing.
|
||||
*/
|
||||
static public class OrganizationData {
|
||||
public final int type;
|
||||
// non-final is Intended: we may change the values since this info is separated into
|
||||
@@ -328,9 +322,6 @@ public class ContactStruct {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide only for testing.
|
||||
*/
|
||||
static public class PhotoData {
|
||||
public static final String FORMAT_FLASH = "SWF";
|
||||
public final int type;
|
||||
@@ -372,10 +363,6 @@ public class ContactStruct {
|
||||
private List<String> mPropertyValueList = new ArrayList<String>();
|
||||
private byte[] mPropertyBytes;
|
||||
|
||||
public Property() {
|
||||
clear();
|
||||
}
|
||||
|
||||
public void setPropertyName(final String propertyName) {
|
||||
mPropertyName = propertyName;
|
||||
}
|
||||
@@ -415,6 +402,7 @@ public class ContactStruct {
|
||||
mPropertyName = null;
|
||||
mParameterMap.clear();
|
||||
mPropertyValueList.clear();
|
||||
mPropertyBytes = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,45 +452,6 @@ public class ContactStruct {
|
||||
mAccount = account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide only for testing.
|
||||
*/
|
||||
public ContactStruct(String givenName,
|
||||
String familyName,
|
||||
String middleName,
|
||||
String prefix,
|
||||
String suffix,
|
||||
String phoneticGivenName,
|
||||
String pheneticFamilyName,
|
||||
String phoneticMiddleName,
|
||||
List<String> nicknameList,
|
||||
List<byte[]> photoBytesList,
|
||||
List<String> noteList,
|
||||
List<PhoneData> phoneList,
|
||||
List<EmailData> emailList,
|
||||
List<PostalData> postalList,
|
||||
List<OrganizationData> organizationList,
|
||||
List<ImData> imList,
|
||||
List<PhotoData> photoList,
|
||||
List<String> websiteList) {
|
||||
this(VCardConfig.VCARD_TYPE_DEFAULT);
|
||||
mGivenName = givenName;
|
||||
mFamilyName = familyName;
|
||||
mPrefix = prefix;
|
||||
mSuffix = suffix;
|
||||
mPhoneticGivenName = givenName;
|
||||
mPhoneticFamilyName = familyName;
|
||||
mPhoneticMiddleName = middleName;
|
||||
mNickNameList = nicknameList;
|
||||
mNoteList = noteList;
|
||||
mEmailList = emailList;
|
||||
mPostalList = postalList;
|
||||
mOrganizationList = organizationList;
|
||||
mImList = imList;
|
||||
mPhotoList = photoList;
|
||||
mWebsiteList = websiteList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a phone info to phoneList.
|
||||
* @param data phone number
|
||||
@@ -717,7 +666,7 @@ public class ContactStruct {
|
||||
mFamilyName = elems.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Some Japanese mobile phones use this field for phonetic name,
|
||||
* since vCard 2.1 does not have "SORT-STRING" type.
|
||||
@@ -758,21 +707,22 @@ public class ContactStruct {
|
||||
}
|
||||
final String propValue = listToString(propValueList).trim();
|
||||
|
||||
if (propName.equals("VERSION")) {
|
||||
if (propName.equals(Constants.PROPERTY_VERSION)) {
|
||||
// vCard version. Ignore this.
|
||||
} else if (propName.equals("FN")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_FN)) {
|
||||
mFullName = propValue;
|
||||
} else if (propName.equals("NAME") && mFullName == null) {
|
||||
} else if (propName.equals(Constants.PROPERTY_NAME) && mFullName == null) {
|
||||
// Only in vCard 3.0. Use this if FN, which must exist in vCard 3.0 but may not
|
||||
// actually exist in the real vCard data, does not exist.
|
||||
mFullName = propValue;
|
||||
} else if (propName.equals("N")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_N)) {
|
||||
handleNProperty(propValueList);
|
||||
} else if (propName.equals("SORT-STRING")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_NICKNAME)) {
|
||||
mPhoneticFullName = propValue;
|
||||
} else if (propName.equals("NICKNAME") || propName.equals("X-NICKNAME")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_NICKNAME) ||
|
||||
propName.equals(Constants.PROPERTY_X_NICKNAME)) {
|
||||
addNickName(propValue);
|
||||
} else if (propName.equals("SOUND")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_SOUND)) {
|
||||
Collection<String> typeCollection = paramMap.get(Constants.ATTR_TYPE);
|
||||
if (typeCollection != null && typeCollection.contains(Constants.ATTR_TYPE_X_IRMC_N)) {
|
||||
// As of 2009-10-08, Parser side does not split a property value into separated
|
||||
@@ -786,7 +736,7 @@ public class ContactStruct {
|
||||
} else {
|
||||
// Ignore this field since Android cannot understand what it is.
|
||||
}
|
||||
} else if (propName.equals("ADR")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_ADR)) {
|
||||
boolean valuesAreAllEmpty = true;
|
||||
for (String value : propValueList) {
|
||||
if (value.length() > 0) {
|
||||
@@ -811,15 +761,15 @@ public class ContactStruct {
|
||||
type = StructuredPostal.TYPE_HOME;
|
||||
label = "";
|
||||
} else if (typeString.equals(Constants.ATTR_TYPE_WORK) ||
|
||||
typeString.equalsIgnoreCase("COMPANY")) {
|
||||
typeString.equalsIgnoreCase(Constants.ATTR_EXTRA_TYPE_COMPANY)) {
|
||||
// "COMPANY" seems emitted by Windows Mobile, which is not
|
||||
// specifically supported by vCard 2.1. We assume this is same
|
||||
// as "WORK".
|
||||
type = StructuredPostal.TYPE_WORK;
|
||||
label = "";
|
||||
} else if (typeString.equals("PARCEL") ||
|
||||
typeString.equals("DOM") ||
|
||||
typeString.equals("INTL")) {
|
||||
} else if (typeString.equals(Constants.ATTR_ADR_TYPE_PARCEL) ||
|
||||
typeString.equals(Constants.ATTR_ADR_TYPE_DOM) ||
|
||||
typeString.equals(Constants.ATTR_ADR_TYPE_INTL)) {
|
||||
// We do not have any appropriate way to store this information.
|
||||
} else {
|
||||
if (typeString.startsWith("X-") && type < 0) {
|
||||
@@ -838,7 +788,7 @@ public class ContactStruct {
|
||||
}
|
||||
|
||||
addPostal(type, propValueList, label, isPrimary);
|
||||
} else if (propName.equals("EMAIL")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_EMAIL)) {
|
||||
int type = -1;
|
||||
String label = null;
|
||||
boolean isPrimary = false;
|
||||
@@ -870,7 +820,7 @@ public class ContactStruct {
|
||||
type = Email.TYPE_OTHER;
|
||||
}
|
||||
addEmail(type, propValue, label, isPrimary);
|
||||
} else if (propName.equals("ORG")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_ORG)) {
|
||||
// vCard specification does not specify other types.
|
||||
final int type = Organization.TYPE_WORK;
|
||||
boolean isPrimary = false;
|
||||
@@ -883,12 +833,13 @@ public class ContactStruct {
|
||||
}
|
||||
}
|
||||
handleOrgValue(type, propValueList, isPrimary);
|
||||
} else if (propName.equals("TITLE")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_TITLE)) {
|
||||
handleTitleValue(propValue);
|
||||
} else if (propName.equals("ROLE")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_ROLE)) {
|
||||
// This conflicts with TITLE. Ignore for now...
|
||||
// handleTitleValue(propValue);
|
||||
} else if (propName.equals("PHOTO") || propName.equals("LOGO")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_PHOTO) ||
|
||||
propName.equals(Constants.PROPERTY_LOGO)) {
|
||||
Collection<String> paramMapValue = paramMap.get("VALUE");
|
||||
if (paramMapValue != null && paramMapValue.contains("URL")) {
|
||||
// Currently we do not have appropriate example for testing this case.
|
||||
@@ -907,7 +858,7 @@ public class ContactStruct {
|
||||
}
|
||||
addPhotoBytes(formatName, propBytes, isPrimary);
|
||||
}
|
||||
} else if (propName.equals("TEL")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_TEL)) {
|
||||
final Collection<String> typeCollection = paramMap.get(Constants.ATTR_TYPE);
|
||||
final Object typeObject = VCardUtils.getPhoneTypeFromStrings(typeCollection);
|
||||
final int type;
|
||||
@@ -959,20 +910,20 @@ public class ContactStruct {
|
||||
type = Phone.TYPE_HOME;
|
||||
}
|
||||
addIm(type, propValue, null, isPrimary);
|
||||
} else if (propName.equals("NOTE")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_NOTE)) {
|
||||
addNote(propValue);
|
||||
} else if (propName.equals("URL")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_URL)) {
|
||||
if (mWebsiteList == null) {
|
||||
mWebsiteList = new ArrayList<String>(1);
|
||||
}
|
||||
mWebsiteList.add(propValue);
|
||||
} else if (propName.equals("X-PHONETIC-FIRST-NAME")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
|
||||
mPhoneticGivenName = propValue;
|
||||
} else if (propName.equals("X-PHONETIC-MIDDLE-NAME")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
|
||||
mPhoneticMiddleName = propValue;
|
||||
} else if (propName.equals("X-PHONETIC-LAST-NAME")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_X_PHONETIC_LAST_NAME)) {
|
||||
mPhoneticFamilyName = propValue;
|
||||
} else if (propName.equals("BDAY")) {
|
||||
} else if (propName.equals(Constants.PROPERTY_BDAY)) {
|
||||
mBirthday = propValue;
|
||||
/*} else if (propName.equals("REV")) {
|
||||
// Revision of this VCard entry. I think we can ignore this.
|
||||
|
||||
@@ -72,14 +72,30 @@ import java.util.Set;
|
||||
* Usually, this class should be used like this.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="prettyprint"> VCardComposer composer = null; try { composer = new
|
||||
* VCardComposer(context); composer.addHandler(composer.new
|
||||
* HandlerForOutputStream(outputStream)); if (!composer.init()) { // Do
|
||||
* something handling the situation. return; } while (!composer.isAfterLast()) {
|
||||
* if (mCanceled) { // Assume a user may cancel this operation during the
|
||||
* export. return; } if (!composer.createOneEntry()) { // Do something handling
|
||||
* the error situation. return; } } } finally { if (composer != null) {
|
||||
* composer.terminate(); } } </pre>
|
||||
* <pre class="prettyprint">VCardComposer composer = null;
|
||||
* try {
|
||||
* composer = new VCardComposer(context);
|
||||
* composer.addHandler(
|
||||
* composer.new HandlerForOutputStream(outputStream));
|
||||
* if (!composer.init()) {
|
||||
* // Do something handling the situation.
|
||||
* return;
|
||||
* }
|
||||
* while (!composer.isAfterLast()) {
|
||||
* if (mCanceled) {
|
||||
* // Assume a user may cancel this operation during the export.
|
||||
* return;
|
||||
* }
|
||||
* if (!composer.createOneEntry()) {
|
||||
* // Do something handling the error situation.
|
||||
* return;
|
||||
* }
|
||||
* }
|
||||
* } finally {
|
||||
* if (composer != null) {
|
||||
* composer.terminate();
|
||||
* }
|
||||
* } </pre>
|
||||
*/
|
||||
public class VCardComposer {
|
||||
private static final String LOG_TAG = "vcard.VCardComposer";
|
||||
@@ -97,26 +113,57 @@ public class VCardComposer {
|
||||
|
||||
public static final String NO_ERROR = "No error";
|
||||
|
||||
public static final String VCARD_TYPE_STRING_DOCOMO = "docomo";
|
||||
|
||||
// Property for call log entry
|
||||
private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";
|
||||
private static final String VCARD_PROPERTY_CALLTYPE_INCOMING = "INCOMING";
|
||||
private static final String VCARD_PROPERTY_CALLTYPE_OUTGOING = "OUTGOING";
|
||||
private static final String VCARD_PROPERTY_CALLTYPE_MISSED = "MISSED";
|
||||
|
||||
private static final String VCARD_DATA_VCARD = "VCARD";
|
||||
private static final String VCARD_DATA_PUBLIC = "PUBLIC";
|
||||
|
||||
private static final String VCARD_ATTR_SEPARATOR = ";";
|
||||
private static final String VCARD_COL_SEPARATOR = "\r\n";
|
||||
private static final String VCARD_DATA_SEPARATOR = ":";
|
||||
private static final String VCARD_ITEM_SEPARATOR = ";";
|
||||
private static final String VCARD_WS = " ";
|
||||
private static final String VCARD_ATTR_EQUAL = "=";
|
||||
|
||||
private static final String VCARD_ATTR_ENCODING_QP = "ENCODING=QUOTED-PRINTABLE";
|
||||
|
||||
private static final String VCARD_ATTR_ENCODING_BASE64_V21 = "ENCODING=BASE64";
|
||||
private static final String VCARD_ATTR_ENCODING_BASE64_V30 = "ENCODING=b";
|
||||
|
||||
private static final String SHIFT_JIS = "SHIFT_JIS";
|
||||
|
||||
private static final Uri sDataRequestUri;
|
||||
private static final Map<Integer, String> sImMap;
|
||||
|
||||
static {
|
||||
Uri.Builder builder = RawContacts.CONTENT_URI.buildUpon();
|
||||
builder.appendQueryParameter(Data.FOR_EXPORT_ONLY, "1");
|
||||
sDataRequestUri = builder.build();
|
||||
sImMap = new HashMap<Integer, String>();
|
||||
sImMap.put(Im.PROTOCOL_AIM, Constants.PROPERTY_X_AIM);
|
||||
sImMap.put(Im.PROTOCOL_MSN, Constants.PROPERTY_X_MSN);
|
||||
sImMap.put(Im.PROTOCOL_YAHOO, Constants.PROPERTY_X_YAHOO);
|
||||
sImMap.put(Im.PROTOCOL_ICQ, Constants.PROPERTY_X_ICQ);
|
||||
sImMap.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER);
|
||||
sImMap.put(Im.PROTOCOL_SKYPE, Constants.PROPERTY_X_SKYPE_USERNAME);
|
||||
// Google talk is a special case.
|
||||
}
|
||||
|
||||
public static interface OneEntryHandler {
|
||||
public boolean onInit(Context context);
|
||||
|
||||
public boolean onEntryCreated(String vcard);
|
||||
|
||||
public void onTerminate();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An useful example handler, which emits VCard String to outputstream one
|
||||
* by one.
|
||||
* An useful example handler, which emits VCard String to outputstream one by one.
|
||||
* </p>
|
||||
* <p>
|
||||
* The input OutputStream object is closed() on {{@link #onTerminate()}.
|
||||
@@ -211,65 +258,6 @@ public class VCardComposer {
|
||||
}
|
||||
}
|
||||
|
||||
public static final String VCARD_TYPE_STRING_DOCOMO = "docomo";
|
||||
|
||||
private static final String VCARD_PROPERTY_ADR = "ADR";
|
||||
private static final String VCARD_PROPERTY_BEGIN = "BEGIN";
|
||||
private static final String VCARD_PROPERTY_EMAIL = "EMAIL";
|
||||
private static final String VCARD_PROPERTY_END = "END";
|
||||
private static final String VCARD_PROPERTY_NAME = "N";
|
||||
private static final String VCARD_PROPERTY_FULL_NAME = "FN";
|
||||
private static final String VCARD_PROPERTY_NOTE = "NOTE";
|
||||
private static final String VCARD_PROPERTY_ORG = "ORG";
|
||||
private static final String VCARD_PROPERTY_SOUND = "SOUND";
|
||||
private static final String VCARD_PROPERTY_SORT_STRING = "SORT-STRING";
|
||||
private static final String VCARD_PROPERTY_NICKNAME = "NICKNAME";
|
||||
private static final String VCARD_PROPERTY_TEL = "TEL";
|
||||
private static final String VCARD_PROPERTY_TITLE = "TITLE";
|
||||
private static final String VCARD_PROPERTY_PHOTO = "PHOTO";
|
||||
private static final String VCARD_PROPERTY_VERSION = "VERSION";
|
||||
private static final String VCARD_PROPERTY_URL = "URL";
|
||||
private static final String VCARD_PROPERTY_BIRTHDAY = "BDAY";
|
||||
|
||||
private static final String VCARD_PROPERTY_X_PHONETIC_FIRST_NAME = "X-PHONETIC-FIRST-NAME";
|
||||
private static final String VCARD_PROPERTY_X_PHONETIC_MIDDLE_NAME = "X-PHONETIC-MIDDLE-NAME";
|
||||
private static final String VCARD_PROPERTY_X_PHONETIC_LAST_NAME = "X-PHONETIC-LAST-NAME";
|
||||
|
||||
// Android specific properties
|
||||
// TODO: ues extra MIME-TYPE instead of adding this kind of inflexible fields
|
||||
private static final String VCARD_PROPERTY_X_NICKNAME = "X-NICKNAME";
|
||||
|
||||
// Property for call log entry
|
||||
private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";
|
||||
private static final String VCARD_PROPERTY_CALLTYPE_INCOMING = "INCOMING";
|
||||
private static final String VCARD_PROPERTY_CALLTYPE_OUTGOING = "OUTGOING";
|
||||
private static final String VCARD_PROPERTY_CALLTYPE_MISSED = "MISSED";
|
||||
|
||||
// Properties for DoCoMo vCard.
|
||||
private static final String VCARD_PROPERTY_X_CLASS = "X-CLASS";
|
||||
private static final String VCARD_PROPERTY_X_REDUCTION = "X-REDUCTION";
|
||||
private static final String VCARD_PROPERTY_X_NO = "X-NO";
|
||||
private static final String VCARD_PROPERTY_X_DCM_HMN_MODE = "X-DCM-HMN-MODE";
|
||||
|
||||
private static final String VCARD_DATA_VCARD = "VCARD";
|
||||
private static final String VCARD_DATA_PUBLIC = "PUBLIC";
|
||||
|
||||
private static final String VCARD_ATTR_SEPARATOR = ";";
|
||||
private static final String VCARD_COL_SEPARATOR = "\r\n";
|
||||
private static final String VCARD_DATA_SEPARATOR = ":";
|
||||
private static final String VCARD_ITEM_SEPARATOR = ";";
|
||||
private static final String VCARD_WS = " ";
|
||||
private static final String VCARD_ATTR_EQUAL = "=";
|
||||
|
||||
// Type strings are now in VCardConstants.java.
|
||||
|
||||
private static final String VCARD_ATTR_ENCODING_QP = "ENCODING=QUOTED-PRINTABLE";
|
||||
|
||||
private static final String VCARD_ATTR_ENCODING_BASE64_V21 = "ENCODING=BASE64";
|
||||
private static final String VCARD_ATTR_ENCODING_BASE64_V30 = "ENCODING=b";
|
||||
|
||||
private static final String SHIFT_JIS = "SHIFT_JIS";
|
||||
|
||||
private final Context mContext;
|
||||
private final int mVCardType;
|
||||
private final boolean mCareHandlerErrors;
|
||||
@@ -298,19 +286,6 @@ public class VCardComposer {
|
||||
|
||||
private String mErrorReason = NO_ERROR;
|
||||
|
||||
private static final Map<Integer, String> sImMap;
|
||||
|
||||
static {
|
||||
sImMap = new HashMap<Integer, String>();
|
||||
sImMap.put(Im.PROTOCOL_AIM, Constants.PROPERTY_X_AIM);
|
||||
sImMap.put(Im.PROTOCOL_MSN, Constants.PROPERTY_X_MSN);
|
||||
sImMap.put(Im.PROTOCOL_YAHOO, Constants.PROPERTY_X_YAHOO);
|
||||
sImMap.put(Im.PROTOCOL_ICQ, Constants.PROPERTY_X_ICQ);
|
||||
sImMap.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER);
|
||||
sImMap.put(Im.PROTOCOL_SKYPE, Constants.PROPERTY_X_SKYPE_USERNAME);
|
||||
// Google talk is a special case.
|
||||
}
|
||||
|
||||
private boolean mIsCallLogComposer = false;
|
||||
|
||||
private static final String[] sContactsProjection = new String[] {
|
||||
@@ -388,35 +363,6 @@ public class VCardComposer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This static function is to compose vCard for phone own number
|
||||
*/
|
||||
public String composeVCardForPhoneOwnNumber(int phonetype, String phoneName,
|
||||
String phoneNumber, boolean vcardVer21) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD);
|
||||
if (!vcardVer21) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30);
|
||||
} else {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21);
|
||||
}
|
||||
|
||||
boolean needCharset = false;
|
||||
if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
|
||||
needCharset = true;
|
||||
}
|
||||
// TODO: QP should be used? Using mUsesQPToPrimaryProperties should help.
|
||||
appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, phoneName, needCharset, false);
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NAME, phoneName, needCharset, false);
|
||||
|
||||
String label = Integer.toString(phonetype);
|
||||
appendVCardTelephoneLine(builder, phonetype, label, phoneNumber);
|
||||
|
||||
appendVCardLine(builder, VCARD_PROPERTY_END, VCARD_DATA_VCARD);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Must call before {{@link #init()}.
|
||||
*/
|
||||
@@ -534,89 +480,6 @@ public class VCardComposer {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format according to RFC 2445 DATETIME type.
|
||||
* The format is: ("%Y%m%dT%H%M%SZ").
|
||||
*/
|
||||
private final String toRfc2455Format(final long millSecs) {
|
||||
Time startDate = new Time();
|
||||
startDate.set(millSecs);
|
||||
String date = startDate.format2445();
|
||||
return date + FLAG_TIMEZONE_UTC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to append the property line for a call history time stamp field if possible.
|
||||
* Do nothing if the call log type gotton from the database is invalid.
|
||||
*/
|
||||
private void tryAppendCallHistoryTimeStampField(final StringBuilder builder) {
|
||||
// Extension for call history as defined in
|
||||
// in the Specification for Ic Mobile Communcation - ver 1.1,
|
||||
// Oct 2000. This is used to send the details of the call
|
||||
// history - missed, incoming, outgoing along with date and time
|
||||
// to the requesting device (For example, transferring phone book
|
||||
// when connected over bluetooth)
|
||||
//
|
||||
// e.g. "X-IRMC-CALL-DATETIME;MISSED:20050320T100000Z"
|
||||
final int callLogType = mCursor.getInt(CALL_TYPE_COLUMN_INDEX);
|
||||
final String callLogTypeStr;
|
||||
switch (callLogType) {
|
||||
case Calls.INCOMING_TYPE: {
|
||||
callLogTypeStr = VCARD_PROPERTY_CALLTYPE_INCOMING;
|
||||
break;
|
||||
}
|
||||
case Calls.OUTGOING_TYPE: {
|
||||
callLogTypeStr = VCARD_PROPERTY_CALLTYPE_OUTGOING;
|
||||
break;
|
||||
}
|
||||
case Calls.MISSED_TYPE: {
|
||||
callLogTypeStr = VCARD_PROPERTY_CALLTYPE_MISSED;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Log.w(LOG_TAG, "Call log type not correct.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final long dateAsLong = mCursor.getLong(DATE_COLUMN_INDEX);
|
||||
builder.append(VCARD_PROPERTY_X_TIMESTAMP);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
appendTypeAttribute(builder, callLogTypeStr);
|
||||
builder.append(VCARD_DATA_SEPARATOR);
|
||||
builder.append(toRfc2455Format(dateAsLong));
|
||||
builder.append(VCARD_COL_SEPARATOR);
|
||||
}
|
||||
|
||||
private String createOneCallLogEntryInternal() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD);
|
||||
if (mIsV30) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30);
|
||||
} else {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21);
|
||||
}
|
||||
String name = mCursor.getString(CALLER_NAME_COLUMN_INDEX);
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
name = mCursor.getString(NUMBER_COLUMN_INDEX);
|
||||
}
|
||||
final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
|
||||
// TODO: QP should be used? Using mUsesQPToPrimaryProperties should help.
|
||||
appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, name, needCharset, false);
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NAME, name, needCharset, false);
|
||||
|
||||
String number = mCursor.getString(NUMBER_COLUMN_INDEX);
|
||||
int type = mCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
|
||||
String label = mCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
|
||||
if (TextUtils.isEmpty(label)) {
|
||||
label = Integer.toString(type);
|
||||
}
|
||||
appendVCardTelephoneLine(builder, type, label, number);
|
||||
tryAppendCallHistoryTimeStampField(builder);
|
||||
appendVCardLine(builder, VCARD_PROPERTY_END, VCARD_DATA_VCARD);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String createOneEntryInternal(final String contactId) {
|
||||
final Map<String, List<ContentValues>> contentValuesListMap =
|
||||
new HashMap<String, List<ContentValues>>();
|
||||
@@ -663,11 +526,11 @@ public class VCardComposer {
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD);
|
||||
appendVCardLine(builder, Constants.PROPERTY_BEGIN, VCARD_DATA_VCARD);
|
||||
if (mIsV30) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30);
|
||||
appendVCardLine(builder, Constants.PROPERTY_VERSION, Constants.VERSION_V30);
|
||||
} else {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21);
|
||||
appendVCardLine(builder, Constants.PROPERTY_VERSION, Constants.VERSION_V21);
|
||||
}
|
||||
|
||||
appendStructuredNames(builder, contentValuesListMap);
|
||||
@@ -684,13 +547,13 @@ public class VCardComposer {
|
||||
// TODO: GroupMembership
|
||||
|
||||
if (mIsDoCoMo) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_X_CLASS, VCARD_DATA_PUBLIC);
|
||||
appendVCardLine(builder, VCARD_PROPERTY_X_REDUCTION, "");
|
||||
appendVCardLine(builder, VCARD_PROPERTY_X_NO, "");
|
||||
appendVCardLine(builder, VCARD_PROPERTY_X_DCM_HMN_MODE, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC);
|
||||
appendVCardLine(builder, Constants.PROPERTY_X_REDUCTION, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_X_NO, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_X_DCM_HMN_MODE, "");
|
||||
}
|
||||
|
||||
appendVCardLine(builder, VCARD_PROPERTY_END, VCARD_DATA_VCARD);
|
||||
appendVCardLine(builder, Constants.PROPERTY_END, VCARD_DATA_VCARD);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
@@ -748,11 +611,11 @@ public class VCardComposer {
|
||||
if (contentValuesList != null && contentValuesList.size() > 0) {
|
||||
appendStructuredNamesInternal(builder, contentValuesList);
|
||||
} else if (mIsDoCoMo) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_N, "");
|
||||
} else if (mIsV30) {
|
||||
// vCard 3.0 requires "N" and "FN" properties.
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
|
||||
appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_N, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_FN, "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,7 +685,7 @@ public class VCardComposer {
|
||||
}
|
||||
|
||||
// N property. This order is specified by vCard spec and does not depend on countries.
|
||||
builder.append(VCARD_PROPERTY_NAME);
|
||||
builder.append(Constants.PROPERTY_N);
|
||||
if (shouldAppendCharsetAttribute(Arrays.asList(
|
||||
familyName, givenName, middleName, prefix, suffix))) {
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
@@ -858,7 +721,7 @@ public class VCardComposer {
|
||||
escapeCharacters(fullname);
|
||||
|
||||
// FN property
|
||||
builder.append(VCARD_PROPERTY_FULL_NAME);
|
||||
builder.append(Constants.PROPERTY_FN);
|
||||
if (shouldAppendCharsetAttribute(encodedFullname)) {
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(mVCardAttributeCharset);
|
||||
@@ -879,7 +742,7 @@ public class VCardComposer {
|
||||
encodeQuotedPrintable(displayName) :
|
||||
escapeCharacters(displayName);
|
||||
|
||||
builder.append(VCARD_PROPERTY_NAME);
|
||||
builder.append(Constants.PROPERTY_N);
|
||||
if (shouldAppendCharsetAttribute(encodedDisplayName)) {
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(mVCardAttributeCharset);
|
||||
@@ -896,10 +759,10 @@ public class VCardComposer {
|
||||
builder.append(VCARD_ITEM_SEPARATOR);
|
||||
builder.append(VCARD_COL_SEPARATOR);
|
||||
} else if (mIsDoCoMo) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_N, "");
|
||||
} else if (mIsV30) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
|
||||
appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_N, "");
|
||||
appendVCardLine(builder, Constants.PROPERTY_FN, "");
|
||||
}
|
||||
|
||||
String phoneticFamilyName = primaryContentValues
|
||||
@@ -926,7 +789,7 @@ public class VCardComposer {
|
||||
phoneticFamilyName,
|
||||
phoneticMiddleName,
|
||||
phoneticGivenName);
|
||||
builder.append(VCARD_PROPERTY_SORT_STRING);
|
||||
builder.append(Constants.PROPERTY_SORT_STRING);
|
||||
|
||||
// Do not need to care about QP, since vCard 3.0 does not allow it.
|
||||
final String encodedSortString = escapeCharacters(sortString);
|
||||
@@ -944,7 +807,7 @@ public class VCardComposer {
|
||||
// We chose to use DoCoMo's way since it is supported by
|
||||
// a lot of Japanese mobile phones. This is "X-" property, so
|
||||
// any parser hopefully would not get confused with this.
|
||||
builder.append(VCARD_PROPERTY_SOUND);
|
||||
builder.append(Constants.PROPERTY_SOUND);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(Constants.ATTR_TYPE_X_IRMC_N);
|
||||
|
||||
@@ -987,7 +850,7 @@ public class VCardComposer {
|
||||
builder.append(VCARD_COL_SEPARATOR);
|
||||
}
|
||||
} else if (mIsDoCoMo) {
|
||||
builder.append(VCARD_PROPERTY_SOUND);
|
||||
builder.append(Constants.PROPERTY_SOUND);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(Constants.ATTR_TYPE_X_IRMC_N);
|
||||
builder.append(VCARD_DATA_SEPARATOR);
|
||||
@@ -1009,7 +872,7 @@ public class VCardComposer {
|
||||
} else {
|
||||
encodedPhoneticGivenName = escapeCharacters(phoneticGivenName);
|
||||
}
|
||||
builder.append(VCARD_PROPERTY_X_PHONETIC_FIRST_NAME);
|
||||
builder.append(Constants.PROPERTY_X_PHONETIC_FIRST_NAME);
|
||||
if (shouldAppendCharsetAttribute(encodedPhoneticGivenName)) {
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(mVCardAttributeCharset);
|
||||
@@ -1032,7 +895,7 @@ public class VCardComposer {
|
||||
} else {
|
||||
encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName);
|
||||
}
|
||||
builder.append(VCARD_PROPERTY_X_PHONETIC_MIDDLE_NAME);
|
||||
builder.append(Constants.PROPERTY_X_PHONETIC_MIDDLE_NAME);
|
||||
if (shouldAppendCharsetAttribute(encodedPhoneticMiddleName)) {
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(mVCardAttributeCharset);
|
||||
@@ -1055,7 +918,7 @@ public class VCardComposer {
|
||||
} else {
|
||||
encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName);
|
||||
}
|
||||
builder.append(VCARD_PROPERTY_X_PHONETIC_LAST_NAME);
|
||||
builder.append(Constants.PROPERTY_X_PHONETIC_LAST_NAME);
|
||||
if (shouldAppendCharsetAttribute(encodedPhoneticFamilyName)) {
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(mVCardAttributeCharset);
|
||||
@@ -1078,9 +941,9 @@ public class VCardComposer {
|
||||
if (contentValuesList != null) {
|
||||
final String propertyNickname;
|
||||
if (mIsV30) {
|
||||
propertyNickname = VCARD_PROPERTY_NICKNAME;
|
||||
} else if (mUsesAndroidProperty) {
|
||||
propertyNickname = VCARD_PROPERTY_X_NICKNAME;
|
||||
propertyNickname = Constants.PROPERTY_NICKNAME;
|
||||
/*} else if (mUsesAndroidProperty) {
|
||||
propertyNickname = VCARD_PROPERTY_X_NICKNAME;*/
|
||||
} else {
|
||||
// There's no way to add this field.
|
||||
return;
|
||||
@@ -1194,7 +1057,7 @@ public class VCardComposer {
|
||||
appendPostalsForGeneric(builder, contentValuesList);
|
||||
}
|
||||
} else if (mIsDoCoMo) {
|
||||
builder.append(VCARD_PROPERTY_ADR);
|
||||
builder.append(Constants.PROPERTY_ADR);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
builder.append(Constants.ATTR_TYPE_HOME);
|
||||
builder.append(VCARD_DATA_SEPARATOR);
|
||||
@@ -1290,7 +1153,7 @@ public class VCardComposer {
|
||||
website = website.trim();
|
||||
}
|
||||
if (!TextUtils.isEmpty(website)) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_URL, website);
|
||||
appendVCardLine(builder, Constants.PROPERTY_URL, website);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1313,7 +1176,7 @@ public class VCardComposer {
|
||||
birthday = birthday.trim();
|
||||
}
|
||||
if (!TextUtils.isEmpty(birthday)) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_BIRTHDAY, birthday);
|
||||
appendVCardLine(builder, Constants.PROPERTY_BDAY, birthday);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1336,13 +1199,13 @@ public class VCardComposer {
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(company)) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_ORG, company,
|
||||
appendVCardLine(builder, Constants.PROPERTY_ORG, company,
|
||||
!VCardUtils.containsOnlyPrintableAscii(company),
|
||||
(mUsesQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(company)));
|
||||
}
|
||||
if (!TextUtils.isEmpty(title)) {
|
||||
appendVCardLine(builder, VCARD_PROPERTY_TITLE, title,
|
||||
appendVCardLine(builder, Constants.PROPERTY_TITLE, title,
|
||||
!VCardUtils.containsOnlyPrintableAscii(title),
|
||||
(mUsesQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(title)));
|
||||
@@ -1420,7 +1283,7 @@ public class VCardComposer {
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NOTE, noteStr,
|
||||
appendVCardLine(builder, Constants.PROPERTY_NOTE, noteStr,
|
||||
shouldAppendCharsetInfo, reallyUseQuotedPrintable);
|
||||
} else {
|
||||
for (ContentValues contentValues : contentValuesList) {
|
||||
@@ -1431,7 +1294,7 @@ public class VCardComposer {
|
||||
final boolean reallyUseQuotedPrintable =
|
||||
(mUsesQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
|
||||
appendVCardLine(builder, VCARD_PROPERTY_NOTE, noteStr,
|
||||
appendVCardLine(builder, Constants.PROPERTY_NOTE, noteStr,
|
||||
shouldAppendCharsetInfo, reallyUseQuotedPrintable);
|
||||
}
|
||||
}
|
||||
@@ -1517,7 +1380,7 @@ public class VCardComposer {
|
||||
private void appendVCardPhotoLine(final StringBuilder builder,
|
||||
final String encodedData, final String photoType) {
|
||||
StringBuilder tmpBuilder = new StringBuilder();
|
||||
tmpBuilder.append(VCARD_PROPERTY_PHOTO);
|
||||
tmpBuilder.append(Constants.PROPERTY_PHOTO);
|
||||
tmpBuilder.append(VCARD_ATTR_SEPARATOR);
|
||||
if (mIsV30) {
|
||||
tmpBuilder.append(VCARD_ATTR_ENCODING_BASE64_V30);
|
||||
@@ -1550,7 +1413,7 @@ public class VCardComposer {
|
||||
private void appendVCardPostalLine(final StringBuilder builder,
|
||||
final Integer typeAsObject, final String label,
|
||||
final ContentValues contentValues) {
|
||||
builder.append(VCARD_PROPERTY_ADR);
|
||||
builder.append(Constants.PROPERTY_ADR);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
|
||||
// Note: Not sure why we need to emit "empty" line even when actual data does not exist.
|
||||
@@ -1684,7 +1547,7 @@ public class VCardComposer {
|
||||
|
||||
private void appendVCardEmailLine(final StringBuilder builder,
|
||||
final Integer typeAsObject, final String label, final String data) {
|
||||
builder.append(VCARD_PROPERTY_EMAIL);
|
||||
builder.append(Constants.PROPERTY_EMAIL);
|
||||
|
||||
final int typeAsPrimitive;
|
||||
if (typeAsObject == null) {
|
||||
@@ -1743,7 +1606,7 @@ public class VCardComposer {
|
||||
private void appendVCardTelephoneLine(final StringBuilder builder,
|
||||
final Integer typeAsObject, final String label,
|
||||
String encodedData) {
|
||||
builder.append(VCARD_PROPERTY_TEL);
|
||||
builder.append(Constants.PROPERTY_TEL);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
|
||||
final int typeAsPrimitive;
|
||||
@@ -1961,4 +1824,118 @@ public class VCardComposer {
|
||||
|
||||
return tmpBuilder.toString();
|
||||
}
|
||||
|
||||
//// The methods bellow are for call log history ////
|
||||
|
||||
/**
|
||||
* This static function is to compose vCard for phone own number
|
||||
*/
|
||||
public String composeVCardForPhoneOwnNumber(int phonetype, String phoneName,
|
||||
String phoneNumber, boolean vcardVer21) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
appendVCardLine(builder, Constants.PROPERTY_BEGIN, VCARD_DATA_VCARD);
|
||||
if (!vcardVer21) {
|
||||
appendVCardLine(builder, Constants.PROPERTY_VERSION, Constants.VERSION_V30);
|
||||
} else {
|
||||
appendVCardLine(builder, Constants.PROPERTY_VERSION, Constants.VERSION_V21);
|
||||
}
|
||||
|
||||
boolean needCharset = false;
|
||||
if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
|
||||
needCharset = true;
|
||||
}
|
||||
// TODO: QP should be used? Using mUsesQPToPrimaryProperties should help.
|
||||
appendVCardLine(builder, Constants.PROPERTY_FN, phoneName, needCharset, false);
|
||||
appendVCardLine(builder, Constants.PROPERTY_N, phoneName, needCharset, false);
|
||||
|
||||
String label = Integer.toString(phonetype);
|
||||
appendVCardTelephoneLine(builder, phonetype, label, phoneNumber);
|
||||
|
||||
appendVCardLine(builder, Constants.PROPERTY_END, VCARD_DATA_VCARD);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format according to RFC 2445 DATETIME type.
|
||||
* The format is: ("%Y%m%dT%H%M%SZ").
|
||||
*/
|
||||
private final String toRfc2455Format(final long millSecs) {
|
||||
Time startDate = new Time();
|
||||
startDate.set(millSecs);
|
||||
String date = startDate.format2445();
|
||||
return date + FLAG_TIMEZONE_UTC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to append the property line for a call history time stamp field if possible.
|
||||
* Do nothing if the call log type gotton from the database is invalid.
|
||||
*/
|
||||
private void tryAppendCallHistoryTimeStampField(final StringBuilder builder) {
|
||||
// Extension for call history as defined in
|
||||
// in the Specification for Ic Mobile Communcation - ver 1.1,
|
||||
// Oct 2000. This is used to send the details of the call
|
||||
// history - missed, incoming, outgoing along with date and time
|
||||
// to the requesting device (For example, transferring phone book
|
||||
// when connected over bluetooth)
|
||||
//
|
||||
// e.g. "X-IRMC-CALL-DATETIME;MISSED:20050320T100000Z"
|
||||
final int callLogType = mCursor.getInt(CALL_TYPE_COLUMN_INDEX);
|
||||
final String callLogTypeStr;
|
||||
switch (callLogType) {
|
||||
case Calls.INCOMING_TYPE: {
|
||||
callLogTypeStr = VCARD_PROPERTY_CALLTYPE_INCOMING;
|
||||
break;
|
||||
}
|
||||
case Calls.OUTGOING_TYPE: {
|
||||
callLogTypeStr = VCARD_PROPERTY_CALLTYPE_OUTGOING;
|
||||
break;
|
||||
}
|
||||
case Calls.MISSED_TYPE: {
|
||||
callLogTypeStr = VCARD_PROPERTY_CALLTYPE_MISSED;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Log.w(LOG_TAG, "Call log type not correct.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final long dateAsLong = mCursor.getLong(DATE_COLUMN_INDEX);
|
||||
builder.append(VCARD_PROPERTY_X_TIMESTAMP);
|
||||
builder.append(VCARD_ATTR_SEPARATOR);
|
||||
appendTypeAttribute(builder, callLogTypeStr);
|
||||
builder.append(VCARD_DATA_SEPARATOR);
|
||||
builder.append(toRfc2455Format(dateAsLong));
|
||||
builder.append(VCARD_COL_SEPARATOR);
|
||||
}
|
||||
|
||||
private String createOneCallLogEntryInternal() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
appendVCardLine(builder, Constants.PROPERTY_BEGIN, VCARD_DATA_VCARD);
|
||||
if (mIsV30) {
|
||||
appendVCardLine(builder, Constants.PROPERTY_VERSION, Constants.VERSION_V30);
|
||||
} else {
|
||||
appendVCardLine(builder, Constants.PROPERTY_VERSION, Constants.VERSION_V21);
|
||||
}
|
||||
String name = mCursor.getString(CALLER_NAME_COLUMN_INDEX);
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
name = mCursor.getString(NUMBER_COLUMN_INDEX);
|
||||
}
|
||||
final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
|
||||
// TODO: QP should be used? Using mUsesQPToPrimaryProperties should help.
|
||||
appendVCardLine(builder, Constants.PROPERTY_FN, name, needCharset, false);
|
||||
appendVCardLine(builder, Constants.PROPERTY_N, name, needCharset, false);
|
||||
|
||||
String number = mCursor.getString(NUMBER_COLUMN_INDEX);
|
||||
int type = mCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
|
||||
String label = mCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
|
||||
if (TextUtils.isEmpty(label)) {
|
||||
label = Integer.toString(type);
|
||||
}
|
||||
appendVCardTelephoneLine(builder, type, label, number);
|
||||
tryAppendCallHistoryTimeStampField(builder);
|
||||
appendVCardLine(builder, Constants.PROPERTY_END, VCARD_DATA_VCARD);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class VCardParser_V21 extends VCardParser {
|
||||
}
|
||||
|
||||
protected String getVersionString() {
|
||||
return "2.1";
|
||||
return Constants.VERSION_V21;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,9 +43,9 @@ public class VCardUtils {
|
||||
// vCard and current (as of 2009-08-07) Contacts structure.
|
||||
private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS;
|
||||
private static final Set<String> sPhoneTypesSetUnknownToContacts;
|
||||
|
||||
|
||||
private static final Map<String, Integer> sKnownPhoneTypesMap_StoI;
|
||||
|
||||
|
||||
static {
|
||||
sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>();
|
||||
sKnownPhoneTypesMap_StoI = new HashMap<String, Integer>();
|
||||
@@ -61,14 +61,15 @@ public class VCardUtils {
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_WORK, Phone.TYPE_WORK);
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_CELL, Phone.TYPE_MOBILE);
|
||||
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PHONE_EXTRA_OTHER, Phone.TYPE_OTHER);
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PHONE_EXTRA_CALLBACK, Phone.TYPE_CALLBACK);
|
||||
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(
|
||||
Constants.ATTR_TYPE_PHONE_EXTRA_COMPANY_MAIN, Phone.TYPE_COMPANY_MAIN);
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PHONE_EXTRA_RADIO, Phone.TYPE_RADIO);
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PHONE_EXTRA_TELEX, Phone.TYPE_TELEX);
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PHONE_EXTRA_TTY_TDD, Phone.TYPE_TTY_TDD);
|
||||
sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PHONE_EXTRA_ASSISTANT, Phone.TYPE_ASSISTANT);
|
||||
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,
|
||||
Phone.TYPE_ASSISTANT);
|
||||
|
||||
sPhoneTypesSetUnknownToContacts = new HashSet<String>();
|
||||
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_MODEM);
|
||||
@@ -76,11 +77,11 @@ public class VCardUtils {
|
||||
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_BBS);
|
||||
sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_VIDEO);
|
||||
}
|
||||
|
||||
|
||||
public static String getPhoneAttributeString(Integer type) {
|
||||
return sKnownPhoneTypesMap_ItoS.get(type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns Interger when the given types can be parsed as known type. Returns String object
|
||||
* when not, which should be set to label.
|
||||
|
||||
Reference in New Issue
Block a user