14199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/* 24199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project 34199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 44199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not 54199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * use this file except in compliance with the License. You may obtain a copy of 64199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * the License at 74199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 84199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 94199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * License for the specific language governing permissions and limitations under 144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * the License. 154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapackage com.android.vcard; 174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentResolver; 194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues; 204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.Context; 214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.Entity; 224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.Entity.NamedContentValues; 23422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.content.EntityIterator; 244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.database.Cursor; 254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.database.sqlite.SQLiteException; 264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.net.Uri; 274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email; 284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event; 294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Im; 304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Nickname; 314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Note; 324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Organization; 334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone; 344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo; 354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Relation; 36422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Website; 40422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.Contacts; 41422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.Data; 42422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.RawContacts; 43422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.RawContactsEntity; 445f0f9e9f2d3e8b73beaf49d542e10fdec6fa199bMartijn Coenenimport android.provider.ContactsContract; 454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.text.TextUtils; 464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log; 474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.lang.reflect.InvocationTargetException; 494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.lang.reflect.Method; 504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList; 514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap; 524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List; 534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map; 544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/** 564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class for composing vCard from Contacts information. 584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Usually, this class should be used like this. 614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <pre class="prettyprint">VCardComposer composer = null; 634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * try { 644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer = new VCardComposer(context); 654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer.addHandler( 664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer.new HandlerForOutputStream(outputStream)); 674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (!composer.init()) { 684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * // Do something handling the situation. 694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return; 704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * while (!composer.isAfterLast()) { 724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (mCanceled) { 734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * // Assume a user may cancel this operation during the export. 744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return; 754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (!composer.createOneEntry()) { 774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * // Do something handling the error situation. 784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return; 794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } finally { 824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (composer != null) { 834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer.terminate(); 844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * }</pre> 864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Users have to manually take care of memory efficiency. Even one vCard may contain 884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * image of non-trivial size for mobile devices. 894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VCardBuilder} is used to build each vCard. 924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardComposer { 954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String LOG_TAG = "VCardComposer"; 967e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private static final boolean DEBUG = false; 974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO = 994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Failed to get database information"; 1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_NO_ENTRY = 1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "There's no exportable in the database"; 1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_NOT_INITIALIZED = 1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The vCard composer object is not correctly initialized"; 1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** Should be visible only from developers... (no need to translate, hopefully) */ 1084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_UNSUPPORTED_URI = 1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The Uri vCard composer received is not supported by the composer."; 1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String NO_ERROR = "No error"; 1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Strictly speaking, "Shift_JIS" is the most appropriate, but we use upper version here, 1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // since usual vCard devices for Japanese devices already use it. 1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String SHIFT_JIS = "SHIFT_JIS"; 1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String UTF_8 = "UTF-8"; 1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final Map<Integer, String> sImMap; 1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa static { 1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap = new HashMap<Integer, String>(); 1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM); 1234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN); 1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO); 1254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ); 1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER); 1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME); 1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We don't add Google talk here since it has to be handled separately. 1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final int mVCardType; 1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final ContentResolver mContentResolver; 1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsDoCoMo; 13556174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa /** 13656174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa * Used only when {@link #mIsDoCoMo} is true. Set to true when the first vCard for DoCoMo 13756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa * vCard is emitted. 13856174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa */ 13956174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa private boolean mFirstVCardEmittedInDoCoMoCase; 14056174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa 1414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private Cursor mCursor; 1427e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean mCursorSuppliedFromOutside; 1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private int mIdColumn; 144677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa private Uri mContentUriForRawContactsEntity; 1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final String mCharset; 1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1487e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean mInitDone; 1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String mErrorReason = NO_ERROR; 1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 151a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa /** 152a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * Set to false when one of {@link #init()} variants is called, and set to true when 153a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * {@link #terminate()} is called. Initially set to true. 154a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa */ 155a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa private boolean mTerminateCalled = true; 15691ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa 157753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai private RawContactEntitlesInfoCallback mRawContactEntitlesInfoCallback; 158753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai 1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String[] sContactsProjection = new String[] { 1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Contacts._ID, 1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa }; 1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context) { 1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, VCardConfig.VCARD_TYPE_DEFAULT, null, true); 1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The variant which sets charset to null and sets careHandlerErrors to true. 1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context, int vcardType) { 1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, null, true); 1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context, int vcardType, String charset) { 1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, charset, true); 1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The variant which sets charset to null. 1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(final Context context, final int vcardType, 1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean careHandlerErrors) { 1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, null, careHandlerErrors); 1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1877e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Constructs for supporting call log entry vCard composing. 1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param context Context to be used during the composition. 1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param vcardType The type of vCard, typically available via {@link VCardConfig}. 1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param charset The charset to be used. Use null when you don't need the charset. 1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param careHandlerErrors If true, This object returns false everytime 1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(final Context context, final int vcardType, String charset, 1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean careHandlerErrors) { 1967e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa this(context, context.getContentResolver(), vcardType, charset, careHandlerErrors); 1977e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 1987e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 1997e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa /** 2007e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Just for testing for now. 2017e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * @param resolver {@link ContentResolver} which used by this object. 2027e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * @hide 2037e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa */ 2047e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa public VCardComposer(final Context context, ContentResolver resolver, 2057e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa final int vcardType, String charset, final boolean careHandlerErrors) { 20656174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // Not used right now 20756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // mContext = context; 2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardType = vcardType; 2097e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mContentResolver = resolver; 2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = (TextUtils.isEmpty(charset) ? VCardConfig.DEFAULT_EXPORT_CHARSET : charset); 2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetParam = !( 215be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa VCardConfig.isVersion30(vcardType) && UTF_8.equalsIgnoreCase(charset)); 2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo || shouldAppendCharsetParam) { 2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (SHIFT_JIS.equalsIgnoreCase(charset)) { 2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 221422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa /* Log.w(LOG_TAG, 2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The charset \"" + charset + "\" is used while " 223422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa + SHIFT_JIS + " is needed to be used."); */ 2244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 2254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = SHIFT_JIS; 2264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 2324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = UTF_8; 2334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\""); 2394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 2427e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Initializes this object using default {@link Contacts#CONTENT_URI}. 2437e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * 2447e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * You can call this method or a variant of this method just once. In other words, you cannot 2457e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * reuse this object. 2467e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * 2474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return Returns true when initialization is successful and all the other 2484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * methods are available. Returns false otherwise. 2494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 2504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init() { 2514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return init(null, null); 2524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 254a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa /** 255a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * Special variant of init(), which accepts a Uri for obtaining {@link RawContactsEntity} from 256a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * {@link ContentResolver} with {@link Contacts#_ID}. 257a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * <code> 258a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * String selection = Data.CONTACT_ID + "=?"; 259a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * String[] selectionArgs = new String[] {contactId}; 260a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * Cursor cursor = mContentResolver.query( 261a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * contentUriForRawContactsEntity, null, selection, selectionArgs, null) 262a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * </code> 2637e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * 2647e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * You can call this method or a variant of this method just once. In other words, you cannot 2657e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * reuse this object. 266677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 267677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @deprecated Use {@link #init(Uri, String[], String, String[], String, Uri)} if you really 268677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * need to change the default Uri. 269a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa */ 270677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa @Deprecated 271a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa public boolean initWithRawContactsEntityUri(Uri contentUriForRawContactsEntity) { 272677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return init(Contacts.CONTENT_URI, sContactsProjection, null, null, null, 273677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa contentUriForRawContactsEntity); 274a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa } 275a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa 2767e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa /** 2777e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Initializes this object using default {@link Contacts#CONTENT_URI} and given selection 2787e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * arguments. 2797e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa */ 2804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init(final String selection, final String[] selectionArgs) { 281677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return init(Contacts.CONTENT_URI, sContactsProjection, selection, selectionArgs, 282677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa null, null); 2834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 2864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note that this is unstable interface, may be deleted in the future. 2874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 2884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init(final Uri contentUri, final String selection, 2894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] selectionArgs, final String sortOrder) { 290677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return init(contentUri, sContactsProjection, selection, selectionArgs, sortOrder, null); 2917e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 2927e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 293677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa /** 294846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param contentUri Uri for obtaining the list of contactId. Used with 295846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 296846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param selection selection used with 297846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 298846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param selectionArgs selectionArgs used with 299846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 300846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param sortOrder sortOrder used with 301846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 302846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param contentUriForRawContactsEntity Uri for obtaining entries relevant to each 303846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * contactId. 304846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * Note that this is an unstable interface, may be deleted in the future. 305846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen */ 306846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen public boolean init(final Uri contentUri, final String selection, 307846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen final String[] selectionArgs, final String sortOrder, 308846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen final Uri contentUriForRawContactsEntity) { 309846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen return init(contentUri, sContactsProjection, selection, selectionArgs, sortOrder, 310846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen contentUriForRawContactsEntity); 311846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen } 312846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen 313846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen /** 314677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * A variant of init(). Currently just for testing. Use other variants for init(). 315677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 316677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * First we'll create {@link Cursor} for the list of contactId. 317677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 318677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * <code> 319677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * Cursor cursorForId = mContentResolver.query( 320677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * contentUri, projection, selection, selectionArgs, sortOrder); 321677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * </code> 322677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 323677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * After that, we'll obtain data for each contactId in the list. 324677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 325677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * <code> 326677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * Cursor cursorForContent = mContentResolver.query( 327677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * contentUriForRawContactsEntity, null, 328677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * Data.CONTACT_ID + "=?", new String[] {contactId}, null) 329677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * </code> 330677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 331677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link #createOneEntry()} or its variants let the caller obtain each entry from 332677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * <code>cursorForContent</code> above. 333677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 334677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param contentUri Uri for obtaining the list of contactId. Used with 335677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 336677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param projection projection used with 337677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 338677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param selection selection used with 339677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 340677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param selectionArgs selectionArgs used with 341677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 342677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param sortOrder sortOrder used with 343677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 344677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param contentUriForRawContactsEntity Uri for obtaining entries relevant to each 345677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * contactId. 346677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @return true when successful 347677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 348677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @hide 349677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa */ 350677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa public boolean init(final Uri contentUri, final String[] projection, 351677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final String selection, final String[] selectionArgs, 352677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final String sortOrder, Uri contentUriForRawContactsEntity) { 3535f0f9e9f2d3e8b73beaf49d542e10fdec6fa199bMartijn Coenen if (!ContactsContract.AUTHORITY.equals(contentUri.getAuthority())) { 3547e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (DEBUG) Log.d(LOG_TAG, "Unexpected contentUri: " + contentUri); 3557e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mErrorReason = FAILURE_REASON_UNSUPPORTED_URI; 3567e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3577e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3585f0f9e9f2d3e8b73beaf49d542e10fdec6fa199bMartijn Coenen 359677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa if (!initInterFirstPart(contentUriForRawContactsEntity)) { 3607e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3617e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3627e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!initInterCursorCreationPart(contentUri, projection, selection, selectionArgs, 3637e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa sortOrder)) { 3647e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3657e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3667e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!initInterMainPart()) { 3677e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3687e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3697e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return initInterLastPart(); 3707e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3717e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 3727e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa /** 3737e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Just for testing for now. Do not use. 3747e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * @hide 3757e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa */ 3767e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa public boolean init(Cursor cursor) { 377753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai return initWithCallback(cursor, null); 378753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai } 379753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai 380753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai /** 381753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * @param cursor Cursor that used to get contact id 382753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * @param rawContactEntitlesInfoCallback Callback that return RawContactEntitlesInfo 383753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * Note that this is an unstable interface, may be deleted in the future. 384753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * 385753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * @return true when successful 386753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai */ 387753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai public boolean initWithCallback(Cursor cursor, 388753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai RawContactEntitlesInfoCallback rawContactEntitlesInfoCallback) { 389677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa if (!initInterFirstPart(null)) { 3907e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3917e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3927e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mCursorSuppliedFromOutside = true; 3937e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mCursor = cursor; 394753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai mRawContactEntitlesInfoCallback = rawContactEntitlesInfoCallback; 3957e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!initInterMainPart()) { 3967e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3977e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3987e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return initInterLastPart(); 3997e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4007e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 401677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa private boolean initInterFirstPart(Uri contentUriForRawContactsEntity) { 402677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa mContentUriForRawContactsEntity = 403677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa (contentUriForRawContactsEntity != null ? contentUriForRawContactsEntity : 404677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa RawContactsEntity.CONTENT_URI); 4057e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (mInitDone) { 4067e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa Log.e(LOG_TAG, "init() is already called"); 4074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4097e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return true; 4107e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4117e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 4127e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean initInterCursorCreationPart( 4137e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa final Uri contentUri, final String[] projection, 4147e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa final String selection, final String[] selectionArgs, final String sortOrder) { 4157e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mCursorSuppliedFromOutside = false; 4164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = mContentResolver.query( 4174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentUri, projection, selection, selectionArgs, sortOrder); 4184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 4197e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa Log.e(LOG_TAG, String.format("Cursor became null unexpectedly")); 4204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO; 4214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4237e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return true; 4247e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4267e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean initInterMainPart() { 4277e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) { 4287e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (DEBUG) { 4297e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa Log.d(LOG_TAG, 4307e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa String.format("mCursor has an error (getCount: %d): ", mCursor.getCount())); 4314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4327e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa closeCursorIfAppropriate(); 4334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 435753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai mIdColumn = mCursor.getColumnIndex(Data.CONTACT_ID); 436753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai if (mIdColumn < 0) { 437753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai mIdColumn = mCursor.getColumnIndex(Contacts._ID); 438753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai } 439677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return mIdColumn >= 0; 4407e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4427e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean initInterLastPart() { 4437e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mInitDone = true; 444a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa mTerminateCalled = false; 4454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 4464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4488ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa /** 449677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @return a vCard string. 450677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa */ 4518ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa public String createOneEntry() { 4528ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa return createOneEntry(null); 453677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa } 454677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa 455677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa /** 456677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @hide 457677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa */ 4588ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa public String createOneEntry(Method getEntityIteratorMethod) { 45956174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa if (mIsDoCoMo && !mFirstVCardEmittedInDoCoMoCase) { 46056174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa mFirstVCardEmittedInDoCoMoCase = true; 46156174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // Previously we needed to emit empty data for this specific case, but actually 46256174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // this doesn't work now, as resolver doesn't return any data with "-1" contactId. 46356174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // TODO: re-introduce or remove this logic. Needs to modify unit test when we 46456174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // re-introduce the logic. 46556174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // return createOneEntryInternal("-1", getEntityIteratorMethod); 46656174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa } 46756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa 468753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai final String vcard = createOneEntryInternal(mCursor.getLong(mIdColumn), 469677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa getEntityIteratorMethod); 470677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa if (!mCursor.moveToNext()) { 471677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa Log.e(LOG_TAG, "Cursor#moveToNext() returned false"); 472677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa } 473677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return vcard; 474677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa } 475677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa 476753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai /** 477753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * Class that store rawContactEntitlesUri and contactId 478753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai */ 479753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai public static class RawContactEntitlesInfo { 480753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai public final Uri rawContactEntitlesUri; 481753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai public final long contactId; 482753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai public RawContactEntitlesInfo(Uri rawContactEntitlesUri, long contactId) { 483753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai this.rawContactEntitlesUri = rawContactEntitlesUri; 484753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai this.contactId = contactId; 485753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai } 486753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai } 487753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai 488753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai /** 489753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * Listener for getting raw contact entitles info 490753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai */ 491753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai public interface RawContactEntitlesInfoCallback { 492753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai /** 493753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * Callback to get RawContactEntitlesInfo from contact id 494753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * 495753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * @param contactId Contact id that you want to process. 496753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai * @return RawContactEntitlesInfo that ready to process. 497753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai */ 498753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai RawContactEntitlesInfo getRawContactEntitlesInfo(long contactId); 499753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai } 500753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai 501753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai private String createOneEntryInternal(long contactId, 502677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final Method getEntityIteratorMethod) { 5034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Map<String, List<ContentValues>> contentValuesListMap = 5044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa new HashMap<String, List<ContentValues>>(); 5054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // The resolver may return the entity iterator with no data. It is possible. 5064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // e.g. If all the data in the contact of the given contact id are not exportable ones, 5074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // they are hidden from the view of this method, though contact id itself exists. 5084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa EntityIterator entityIterator = null; 5094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 510753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai Uri uri = mContentUriForRawContactsEntity; 511753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai if (mRawContactEntitlesInfoCallback != null) { 512753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai RawContactEntitlesInfo rawContactEntitlesInfo = 513753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai mRawContactEntitlesInfoCallback.getRawContactEntitlesInfo(contactId); 514753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai uri = rawContactEntitlesInfo.rawContactEntitlesUri; 515753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai contactId = rawContactEntitlesInfo.contactId; 516753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai } 5174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String selection = Data.CONTACT_ID + "=?"; 518753058fffd5cead5e6ebe7e81a9810cc4ca9ceeaRicky Wai final String[] selectionArgs = new String[] {String.valueOf(contactId)}; 5194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (getEntityIteratorMethod != null) { 5204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Please note that this branch is executed by unit tests only 5214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 5224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null, 5234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mContentResolver, uri, selection, selectionArgs, null); 5244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IllegalArgumentException e) { 5254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "IllegalArgumentException has been thrown: " + 5264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IllegalAccessException e) { 5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "IllegalAccessException has been thrown: " + 5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (InvocationTargetException e) { 53156174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa Log.e(LOG_TAG, "InvocationTargetException has been thrown: ", e); 53256174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa throw new RuntimeException("InvocationTargetException has been thrown"); 5334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator = RawContacts.newEntityIterator(mContentResolver.query( 5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa uri, null, selection, selectionArgs, null)); 5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (entityIterator == null) { 5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "EntityIterator is null"); 5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!entityIterator.hasNext()) { 5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "Data does not exist. contactId: " + contactId); 5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa while (entityIterator.hasNext()) { 5504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Entity entity = entityIterator.next(); 5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (NamedContentValues namedContentValues : entity.getSubValues()) { 5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues contentValues = namedContentValues.values; 5534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String key = contentValues.getAsString(Data.MIMETYPE); 5544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (key != null) { 5554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa List<ContentValues> contentValuesList = 5564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesListMap.get(key); 5574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null) { 5584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesList = new ArrayList<ContentValues>(); 5594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesListMap.put(key, contentValuesList); 5604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesList.add(contentValues); 5624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } finally { 5664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (entityIterator != null) { 5674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator.close(); 5684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return buildVCard(contentValuesListMap); 5724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5745fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa private VCardPhoneNumberTranslationCallback mPhoneTranslationCallback; 5755fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa /** 5765fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * <p> 5775fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * Set a callback for phone number formatting. It will be called every time when this object 5785fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * receives a phone number for printing. 5795fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * </p> 5805fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * <p> 5815fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * When this is set {@link VCardConfig#FLAG_REFRAIN_PHONE_NUMBER_FORMATTING} will be ignored 5825fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * and the callback should be responsible for everything about phone number formatting. 5835fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * </p> 5845fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * <p> 5855fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * Caution: This interface will change. Please don't use without any strong reason. 5865fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * </p> 5875fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa */ 5885fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa public void setPhoneNumberTranslationCallback(VCardPhoneNumberTranslationCallback callback) { 5895fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa mPhoneTranslationCallback = callback; 5905fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa } 5915fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa 5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Builds and returns vCard using given map, whose key is CONTENT_ITEM_TYPE defined in 5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {ContactsContract}. Developers can override this method to customize the output. 5954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 5964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String buildVCard(final Map<String, List<ContentValues>> contentValuesListMap) { 5974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesListMap == null) { 5984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "The given map is null. Ignore and return empty String"); 5994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset); 6024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) 6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) 6045fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE), 6055fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa mPhoneTranslationCallback) 6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) 6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) 6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) 6098c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)); 6108c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa if ((mVCardType & VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT) == 0) { 6118c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa builder.appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)); 6128c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa } 6138c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa builder.appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) 6144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) 6154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) 616422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa .appendSipAddresses(contentValuesListMap.get(SipAddress.CONTENT_ITEM_TYPE)) 6174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); 6184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return builder.toString(); 6194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void terminate() { 6237e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa closeCursorIfAppropriate(); 6247e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mTerminateCalled = true; 6257e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 6267e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 6277e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private void closeCursorIfAppropriate() { 6287e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!mCursorSuppliedFromOutside && mCursor != null) { 6294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 6304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor.close(); 6314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (SQLiteException e) { 6324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage()); 6334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = null; 6354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @Override 63991ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa protected void finalize() throws Throwable { 64091ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa try { 641a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa if (!mTerminateCalled) { 642a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa Log.e(LOG_TAG, "finalized() is called before terminate() being called"); 643a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa } 64491ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa } finally { 64591ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa super.finalize(); 6464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return returns the number of available entities. The return value is undefined 6514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * when this object is not ready yet (typically when {{@link #init()} is not called 6524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * or when {@link #terminate()} is already called). 6534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public int getCount() { 6554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 6564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "This object is not ready yet."); 6574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return 0; 6584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCursor.getCount(); 6604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return true when there's no entity to be built. The return value is undefined 6644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * when this object is not ready yet. 6654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean isAfterLast() { 6674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 6684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "This object is not ready yet."); 6694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 6704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCursor.isAfterLast(); 6724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return Returns the error reason. 6764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String getErrorReason() { 6784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mErrorReason; 6794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa} 681