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 1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String[] sContactsProjection = new String[] { 1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Contacts._ID, 1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa }; 1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context) { 1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, VCardConfig.VCARD_TYPE_DEFAULT, null, true); 1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The variant which sets charset to null and sets careHandlerErrors to true. 1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context, int vcardType) { 1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, null, true); 1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context, int vcardType, String charset) { 1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, charset, true); 1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The variant which sets charset to null. 1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(final Context context, final int vcardType, 1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean careHandlerErrors) { 1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, null, careHandlerErrors); 1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1857e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Constructs for supporting call log entry vCard composing. 1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param context Context to be used during the composition. 1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param vcardType The type of vCard, typically available via {@link VCardConfig}. 1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param charset The charset to be used. Use null when you don't need the charset. 1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param careHandlerErrors If true, This object returns false everytime 1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(final Context context, final int vcardType, String charset, 1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean careHandlerErrors) { 1947e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa this(context, context.getContentResolver(), vcardType, charset, careHandlerErrors); 1957e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 1967e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 1977e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa /** 1987e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Just for testing for now. 1997e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * @param resolver {@link ContentResolver} which used by this object. 2007e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * @hide 2017e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa */ 2027e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa public VCardComposer(final Context context, ContentResolver resolver, 2037e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa final int vcardType, String charset, final boolean careHandlerErrors) { 20456174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // Not used right now 20556174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // mContext = context; 2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardType = vcardType; 2077e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mContentResolver = resolver; 2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = (TextUtils.isEmpty(charset) ? VCardConfig.DEFAULT_EXPORT_CHARSET : charset); 2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetParam = !( 213be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa VCardConfig.isVersion30(vcardType) && UTF_8.equalsIgnoreCase(charset)); 2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo || shouldAppendCharsetParam) { 2169919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa // TODO: clean up once we're sure CharsetUtils are really unnecessary any more. 2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (SHIFT_JIS.equalsIgnoreCase(charset)) { 2189919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa /*if (mIsDoCoMo) { 2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); 2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "DoCoMo-specific SHIFT_JIS was not found. " 2244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use SHIFT_JIS as is."); 2254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 2264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); 2304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 2319919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa // Log.e(LOG_TAG, 2329919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa // "Career-specific SHIFT_JIS was not found. " 2339919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa // + "Use SHIFT_JIS as is."); 2344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 2354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2369919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa }*/ 2374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 239422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa /* Log.w(LOG_TAG, 2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The charset \"" + charset + "\" is used while " 241422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa + SHIFT_JIS + " is needed to be used."); */ 2424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 2434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = SHIFT_JIS; 2444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2459919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa /* 2464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 2484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 2494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 2504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 2514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 2529919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa }*/ 2534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 2584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = UTF_8; 2594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 2609919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa /*try { 2614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 2624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 2634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 2644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 2654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 2669919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa }*/ 2674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 2684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\""); 2724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 2757e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Initializes this object using default {@link Contacts#CONTENT_URI}. 2767e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * 2777e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * You can call this method or a variant of this method just once. In other words, you cannot 2787e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * reuse this object. 2797e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * 2804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return Returns true when initialization is successful and all the other 2814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * methods are available. Returns false otherwise. 2824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 2834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init() { 2844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return init(null, null); 2854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 287a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa /** 288a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * Special variant of init(), which accepts a Uri for obtaining {@link RawContactsEntity} from 289a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * {@link ContentResolver} with {@link Contacts#_ID}. 290a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * <code> 291a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * String selection = Data.CONTACT_ID + "=?"; 292a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * String[] selectionArgs = new String[] {contactId}; 293a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * Cursor cursor = mContentResolver.query( 294a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * contentUriForRawContactsEntity, null, selection, selectionArgs, null) 295a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa * </code> 2967e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * 2977e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * You can call this method or a variant of this method just once. In other words, you cannot 2987e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * reuse this object. 299677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 300677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @deprecated Use {@link #init(Uri, String[], String, String[], String, Uri)} if you really 301677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * need to change the default Uri. 302a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa */ 303677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa @Deprecated 304a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa public boolean initWithRawContactsEntityUri(Uri contentUriForRawContactsEntity) { 305677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return init(Contacts.CONTENT_URI, sContactsProjection, null, null, null, 306677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa contentUriForRawContactsEntity); 307a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa } 308a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa 3097e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa /** 3107e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Initializes this object using default {@link Contacts#CONTENT_URI} and given selection 3117e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * arguments. 3127e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa */ 3134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init(final String selection, final String[] selectionArgs) { 314677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return init(Contacts.CONTENT_URI, sContactsProjection, selection, selectionArgs, 315677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa null, null); 3164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 3194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note that this is unstable interface, may be deleted in the future. 3204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 3214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init(final Uri contentUri, final String selection, 3224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] selectionArgs, final String sortOrder) { 323677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return init(contentUri, sContactsProjection, selection, selectionArgs, sortOrder, null); 3247e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3257e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 326677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa /** 327846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param contentUri Uri for obtaining the list of contactId. Used with 328846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 329846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param selection selection used with 330846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 331846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param selectionArgs selectionArgs used with 332846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 333846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param sortOrder sortOrder used with 334846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * {@link ContentResolver#query(Uri, String[], String, String[], String)} 335846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * @param contentUriForRawContactsEntity Uri for obtaining entries relevant to each 336846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * contactId. 337846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen * Note that this is an unstable interface, may be deleted in the future. 338846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen */ 339846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen public boolean init(final Uri contentUri, final String selection, 340846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen final String[] selectionArgs, final String sortOrder, 341846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen final Uri contentUriForRawContactsEntity) { 342846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen return init(contentUri, sContactsProjection, selection, selectionArgs, sortOrder, 343846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen contentUriForRawContactsEntity); 344846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen } 345846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen 346846712bf3921bec5f0654f68e95df790b398acd5Martijn Coenen /** 347677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * A variant of init(). Currently just for testing. Use other variants for init(). 348677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 349677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * First we'll create {@link Cursor} for the list of contactId. 350677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 351677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * <code> 352677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * Cursor cursorForId = mContentResolver.query( 353677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * contentUri, projection, selection, selectionArgs, sortOrder); 354677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * </code> 355677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 356677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * After that, we'll obtain data for each contactId in the list. 357677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 358677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * <code> 359677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * Cursor cursorForContent = mContentResolver.query( 360677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * contentUriForRawContactsEntity, null, 361677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * Data.CONTACT_ID + "=?", new String[] {contactId}, null) 362677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * </code> 363677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 364677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link #createOneEntry()} or its variants let the caller obtain each entry from 365677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * <code>cursorForContent</code> above. 366677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 367677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param contentUri Uri for obtaining the list of contactId. Used with 368677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 369677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param projection projection used with 370677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 371677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param selection selection used with 372677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 373677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param selectionArgs selectionArgs used with 374677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 375677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param sortOrder sortOrder used with 376677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * {@link ContentResolver#query(Uri, String[], String, String[], String)} 377677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @param contentUriForRawContactsEntity Uri for obtaining entries relevant to each 378677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * contactId. 379677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @return true when successful 380677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * 381677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @hide 382677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa */ 383677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa public boolean init(final Uri contentUri, final String[] projection, 384677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final String selection, final String[] selectionArgs, 385677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final String sortOrder, Uri contentUriForRawContactsEntity) { 3865f0f9e9f2d3e8b73beaf49d542e10fdec6fa199bMartijn Coenen if (!ContactsContract.AUTHORITY.equals(contentUri.getAuthority())) { 3877e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (DEBUG) Log.d(LOG_TAG, "Unexpected contentUri: " + contentUri); 3887e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mErrorReason = FAILURE_REASON_UNSUPPORTED_URI; 3897e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3907e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3915f0f9e9f2d3e8b73beaf49d542e10fdec6fa199bMartijn Coenen 392677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa if (!initInterFirstPart(contentUriForRawContactsEntity)) { 3937e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3947e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3957e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!initInterCursorCreationPart(contentUri, projection, selection, selectionArgs, 3967e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa sortOrder)) { 3977e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 3987e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 3997e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!initInterMainPart()) { 4007e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 4017e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4027e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return initInterLastPart(); 4037e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4047e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 4057e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa /** 4067e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * Just for testing for now. Do not use. 4077e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa * @hide 4087e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa */ 4097e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa public boolean init(Cursor cursor) { 410677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa if (!initInterFirstPart(null)) { 4117e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 4127e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4137e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mCursorSuppliedFromOutside = true; 4147e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mCursor = cursor; 4157e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!initInterMainPart()) { 4167e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return false; 4177e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4187e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return initInterLastPart(); 4197e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4207e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 421677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa private boolean initInterFirstPart(Uri contentUriForRawContactsEntity) { 422677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa mContentUriForRawContactsEntity = 423677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa (contentUriForRawContactsEntity != null ? contentUriForRawContactsEntity : 424677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa RawContactsEntity.CONTENT_URI); 4257e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (mInitDone) { 4267e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa Log.e(LOG_TAG, "init() is already called"); 4274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4297e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return true; 4307e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4317e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 4327e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean initInterCursorCreationPart( 4337e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa final Uri contentUri, final String[] projection, 4347e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa final String selection, final String[] selectionArgs, final String sortOrder) { 4357e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mCursorSuppliedFromOutside = false; 4364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = mContentResolver.query( 4374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentUri, projection, selection, selectionArgs, sortOrder); 4384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 4397e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa Log.e(LOG_TAG, String.format("Cursor became null unexpectedly")); 4404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO; 4414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4437e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa return true; 4447e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4467e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean initInterMainPart() { 4477e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) { 4487e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (DEBUG) { 4497e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa Log.d(LOG_TAG, 4507e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa String.format("mCursor has an error (getCount: %d): ", mCursor.getCount())); 4514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4527e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa closeCursorIfAppropriate(); 4534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIdColumn = mCursor.getColumnIndex(Contacts._ID); 456677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return mIdColumn >= 0; 4577e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 4584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4597e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private boolean initInterLastPart() { 4607e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mInitDone = true; 461a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa mTerminateCalled = false; 4624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 4634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4658ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa /** 466677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @return a vCard string. 467677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa */ 4688ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa public String createOneEntry() { 4698ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa return createOneEntry(null); 470677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa } 471677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa 472677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa /** 473677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa * @hide 474677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa */ 4758ed6de732dfb8bf8257152e5c5faf7e0ee760464Daisuke Miyakawa public String createOneEntry(Method getEntityIteratorMethod) { 47656174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa if (mIsDoCoMo && !mFirstVCardEmittedInDoCoMoCase) { 47756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa mFirstVCardEmittedInDoCoMoCase = true; 47856174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // Previously we needed to emit empty data for this specific case, but actually 47956174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // this doesn't work now, as resolver doesn't return any data with "-1" contactId. 48056174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // TODO: re-introduce or remove this logic. Needs to modify unit test when we 48156174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // re-introduce the logic. 48256174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa // return createOneEntryInternal("-1", getEntityIteratorMethod); 48356174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa } 48456174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa 485677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final String vcard = createOneEntryInternal(mCursor.getString(mIdColumn), 486677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa getEntityIteratorMethod); 487677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa if (!mCursor.moveToNext()) { 488677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa Log.e(LOG_TAG, "Cursor#moveToNext() returned false"); 489677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa } 490677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa return vcard; 491677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa } 492677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa 4934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String createOneEntryInternal(final String contactId, 494677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa final Method getEntityIteratorMethod) { 4954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Map<String, List<ContentValues>> contentValuesListMap = 4964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa new HashMap<String, List<ContentValues>>(); 4974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // The resolver may return the entity iterator with no data. It is possible. 4984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // e.g. If all the data in the contact of the given contact id are not exportable ones, 4994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // they are hidden from the view of this method, though contact id itself exists. 5004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa EntityIterator entityIterator = null; 5014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 502a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa final Uri uri = mContentUriForRawContactsEntity; 5034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String selection = Data.CONTACT_ID + "=?"; 5044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] selectionArgs = new String[] {contactId}; 5054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (getEntityIteratorMethod != null) { 5064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Please note that this branch is executed by unit tests only 5074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 5084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null, 5094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mContentResolver, uri, selection, selectionArgs, null); 5104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IllegalArgumentException e) { 5114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "IllegalArgumentException has been thrown: " + 5124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 5134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IllegalAccessException e) { 5144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "IllegalAccessException has been thrown: " + 5154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 5164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (InvocationTargetException e) { 51756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa Log.e(LOG_TAG, "InvocationTargetException has been thrown: ", e); 51856174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa throw new RuntimeException("InvocationTargetException has been thrown"); 5194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator = RawContacts.newEntityIterator(mContentResolver.query( 5224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa uri, null, selection, selectionArgs, null)); 5234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (entityIterator == null) { 5264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "EntityIterator is null"); 5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!entityIterator.hasNext()) { 5314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "Data does not exist. contactId: " + contactId); 5324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa while (entityIterator.hasNext()) { 5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Entity entity = entityIterator.next(); 5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (NamedContentValues namedContentValues : entity.getSubValues()) { 5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues contentValues = namedContentValues.values; 5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String key = contentValues.getAsString(Data.MIMETYPE); 5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (key != null) { 5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa List<ContentValues> contentValuesList = 5424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesListMap.get(key); 5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null) { 5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesList = new ArrayList<ContentValues>(); 5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesListMap.put(key, contentValuesList); 5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesList.add(contentValues); 5484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } finally { 5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (entityIterator != null) { 5534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator.close(); 5544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return buildVCard(contentValuesListMap); 5584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5605fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa private VCardPhoneNumberTranslationCallback mPhoneTranslationCallback; 5615fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa /** 5625fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * <p> 5635fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * Set a callback for phone number formatting. It will be called every time when this object 5645fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * receives a phone number for printing. 5655fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * </p> 5665fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * <p> 5675fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * When this is set {@link VCardConfig#FLAG_REFRAIN_PHONE_NUMBER_FORMATTING} will be ignored 5685fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * and the callback should be responsible for everything about phone number formatting. 5695fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * </p> 5705fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * <p> 5715fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * Caution: This interface will change. Please don't use without any strong reason. 5725fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa * </p> 5735fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa */ 5745fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa public void setPhoneNumberTranslationCallback(VCardPhoneNumberTranslationCallback callback) { 5755fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa mPhoneTranslationCallback = callback; 5765fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa } 5775fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa 5784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 5794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Builds and returns vCard using given map, whose key is CONTENT_ITEM_TYPE defined in 5804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {ContactsContract}. Developers can override this method to customize the output. 5814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 5824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String buildVCard(final Map<String, List<ContentValues>> contentValuesListMap) { 5834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesListMap == null) { 5844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "The given map is null. Ignore and return empty String"); 5854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset); 5884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) 5894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) 5905fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE), 5915fffd2ba2d7fc22271251251f89043ab345acd74Daisuke Miyakawa mPhoneTranslationCallback) 5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) 5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) 5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) 5958c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)); 5968c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa if ((mVCardType & VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT) == 0) { 5978c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa builder.appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)); 5988c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa } 5998c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa builder.appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) 6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) 6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) 602422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa .appendSipAddresses(contentValuesListMap.get(SipAddress.CONTENT_ITEM_TYPE)) 6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); 6044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return builder.toString(); 6054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void terminate() { 6097e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa closeCursorIfAppropriate(); 6107e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa mTerminateCalled = true; 6117e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa } 6127e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa 6137e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa private void closeCursorIfAppropriate() { 6147e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa if (!mCursorSuppliedFromOutside && mCursor != null) { 6154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 6164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor.close(); 6174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (SQLiteException e) { 6184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage()); 6194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = null; 6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @Override 62591ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa protected void finalize() throws Throwable { 62691ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa try { 627a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa if (!mTerminateCalled) { 628a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa Log.e(LOG_TAG, "finalized() is called before terminate() being called"); 629a11303ccb430ca40210900823807027cc842bf6cDaisuke Miyakawa } 63091ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa } finally { 63191ff68b93f7a623f168697ebdb895daea3542579Daisuke Miyakawa super.finalize(); 6324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return returns the number of available entities. The return value is undefined 6374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * when this object is not ready yet (typically when {{@link #init()} is not called 6384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * or when {@link #terminate()} is already called). 6394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public int getCount() { 6414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 6424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "This object is not ready yet."); 6434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return 0; 6444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCursor.getCount(); 6464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return true when there's no entity to be built. The return value is undefined 6504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * when this object is not ready yet. 6514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean isAfterLast() { 6534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 6544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "This object is not ready yet."); 6554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 6564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCursor.isAfterLast(); 6584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return Returns the error reason. 6624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String getErrorReason() { 6644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mErrorReason; 6654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa} 667