VCardComposer.java revision da2f6ef422b360827f2c5231552d8c9fad0ed8b1
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 18422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport com.android.vcard.exception.VCardException; 19422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa 204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentResolver; 214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues; 224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.Context; 234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.Entity; 244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.Entity.NamedContentValues; 25422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.content.EntityIterator; 264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.database.Cursor; 274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.database.sqlite.SQLiteException; 284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.net.Uri; 294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email; 304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event; 314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Im; 324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Nickname; 334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Note; 344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Organization; 354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone; 364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo; 374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Relation; 38422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Website; 42422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.Contacts; 43422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.Data; 44422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.RawContacts; 45422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawaimport android.provider.ContactsContract.RawContactsEntity; 464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.text.TextUtils; 474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.CharsetUtils; 484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log; 494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.BufferedWriter; 514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.FileOutputStream; 524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.IOException; 534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.OutputStream; 544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.OutputStreamWriter; 554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.UnsupportedEncodingException; 564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.Writer; 574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.lang.reflect.InvocationTargetException; 584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.lang.reflect.Method; 594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.charset.UnsupportedCharsetException; 604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList; 614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap; 624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List; 634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map; 644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/** 664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class for composing vCard from Contacts information. 684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Usually, this class should be used like this. 714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <pre class="prettyprint">VCardComposer composer = null; 734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * try { 744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer = new VCardComposer(context); 754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer.addHandler( 764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer.new HandlerForOutputStream(outputStream)); 774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (!composer.init()) { 784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * // Do something handling the situation. 794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return; 804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * while (!composer.isAfterLast()) { 824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (mCanceled) { 834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * // Assume a user may cancel this operation during the export. 844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return; 854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (!composer.createOneEntry()) { 874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * // Do something handling the error situation. 884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * return; 894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } finally { 924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * if (composer != null) { 934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * composer.terminate(); 944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * } 954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * }</pre> 964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Users have to manually take care of memory efficiency. Even one vCard may contain 984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * image of non-trivial size for mobile devices. 994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VCardBuilder} is used to build each vCard. 1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardComposer { 1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String LOG_TAG = "VCardComposer"; 1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO = 1084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Failed to get database information"; 1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_NO_ENTRY = 1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "There's no exportable in the database"; 1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_NOT_INITIALIZED = 1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The vCard composer object is not correctly initialized"; 1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** Should be visible only from developers... (no need to translate, hopefully) */ 1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String FAILURE_REASON_UNSUPPORTED_URI = 1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The Uri vCard composer received is not supported by the composer."; 1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String NO_ERROR = "No error"; 1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String VCARD_TYPE_STRING_DOCOMO = "docomo"; 1234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Strictly speaking, "Shift_JIS" is the most appropriate, but we use upper version here, 1254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // since usual vCard devices for Japanese devices already use it. 1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String SHIFT_JIS = "SHIFT_JIS"; 1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String UTF_8 = "UTF-8"; 1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Special URI for testing. 1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final String VCARD_TEST_AUTHORITY = "com.android.unit_tests.vcard"; 1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final Uri VCARD_TEST_AUTHORITY_URI = 1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Uri.parse("content://" + VCARD_TEST_AUTHORITY); 1354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static final Uri CONTACTS_TEST_CONTENT_URI = 1364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Uri.withAppendedPath(VCARD_TEST_AUTHORITY_URI, "contacts"); 1374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final Map<Integer, String> sImMap; 1394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa static { 1414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap = new HashMap<Integer, String>(); 1424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM); 1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN); 1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO); 1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ); 1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER); 1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa sImMap.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME); 1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // We don't add Google talk here since it has to be handled separately. 1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public static interface OneEntryHandler { 1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean onInit(Context context); 1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean onEntryCreated(String vcard); 1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void onTerminate(); 1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * An useful handler for emitting vCard String to an OutputStream object one by one. 1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p> 1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The input OutputStream object is closed() on {@link #onTerminate()}. 1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Must not close the stream outside this class. 1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p> 1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public final class HandlerForOutputStream implements OneEntryHandler { 1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @SuppressWarnings("hiding") 1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String LOG_TAG = "VCardComposer.HandlerForOutputStream"; 1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean mOnTerminateIsCalled = false; 1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final OutputStream mOutputStream; // mWriter will close this. 1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private Writer mWriter; 1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Input stream will be closed on the detruction of this object. 1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public HandlerForOutputStream(final OutputStream outputStream) { 1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mOutputStream = outputStream; 1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 182da2f6ef422b360827f2c5231552d8c9fad0ed8b1Daisuke Miyakawa @Override 1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean onInit(final Context context) { 1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mWriter = new BufferedWriter(new OutputStreamWriter( 1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mOutputStream, mCharset)); 1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedEncodingException e1) { 1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Unsupported charset: " + mCharset); 1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = "Encoding is not supported (usually this does not happen!): " 1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + mCharset; 1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 1964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Create one empty entry. 1974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mWriter.write(createOneEntryInternal("-1", null)); 1984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (VCardException e) { 1994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "VCardException has been thrown during on Init(): " + 2004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IOException e) { 2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "IOException occurred during exportOneContactData: " 2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + e.getMessage()); 2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = "IOException occurred: " + e.getMessage(); 2074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 213da2f6ef422b360827f2c5231552d8c9fad0ed8b1Daisuke Miyakawa @Override 2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean onEntryCreated(String vcard) { 2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mWriter.write(vcard); 2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IOException e) { 2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "IOException occurred during exportOneContactData: " 2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + e.getMessage()); 2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = "IOException occurred: " + e.getMessage(); 2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 2254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 227da2f6ef422b360827f2c5231552d8c9fad0ed8b1Daisuke Miyakawa @Override 2284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void onTerminate() { 2294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mOnTerminateIsCalled = true; 2304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mWriter != null) { 2314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Flush and sync the data so that a user is able to pull 2334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // the SDCard just after 2344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // the export. 2354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mWriter.flush(); 2364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mOutputStream != null 2374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa && mOutputStream instanceof FileOutputStream) { 2384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ((FileOutputStream) mOutputStream).getFD().sync(); 2394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IOException e) { 2414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, 2424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "IOException during closing the output stream: " 2434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + e.getMessage()); 2444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } finally { 2454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa closeOutputStream(); 2464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void closeOutputStream() { 2514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 2524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mWriter.close(); 2534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IOException e) { 2544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "IOException is thrown during close(). Ignoring."); 2554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @Override 2594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void finalize() { 2604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!mOnTerminateIsCalled) { 2614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa onTerminate(); 2624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final Context mContext; 2674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final int mVCardType; 2684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mCareHandlerErrors; 2694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final ContentResolver mContentResolver; 2704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final boolean mIsDoCoMo; 2724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private Cursor mCursor; 2734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private int mIdColumn; 2744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final String mCharset; 2764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private boolean mTerminateIsCalled; 2774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final List<OneEntryHandler> mHandlerList; 2784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String mErrorReason = NO_ERROR; 2804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private static final String[] sContactsProjection = new String[] { 2824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Contacts._ID, 2834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa }; 2844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context) { 2864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, VCardConfig.VCARD_TYPE_DEFAULT, null, true); 2874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 2904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The variant which sets charset to null and sets careHandlerErrors to true. 2914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 2924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context, int vcardType) { 2934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, null, true); 2944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 2964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(Context context, int vcardType, String charset) { 2974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, charset, true); 2984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 2994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 3014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The variant which sets charset to null. 3024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 3034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(final Context context, final int vcardType, 3044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean careHandlerErrors) { 3054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa this(context, vcardType, null, careHandlerErrors); 3064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 3094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Construct for supporting call log entry vCard composing. 3104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * 3114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param context Context to be used during the composition. 3124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param vcardType The type of vCard, typically available via {@link VCardConfig}. 3134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param charset The charset to be used. Use null when you don't need the charset. 3144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param careHandlerErrors If true, This object returns false everytime 3154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * a Handler object given via {{@link #addHandler(OneEntryHandler)} returns false. 3164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * If false, this ignores those errors. 3174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 3184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardComposer(final Context context, final int vcardType, String charset, 3194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean careHandlerErrors) { 3204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mContext = context; 3214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mVCardType = vcardType; 3224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCareHandlerErrors = careHandlerErrors; 3234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mContentResolver = context.getContentResolver(); 3244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 3264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mHandlerList = new ArrayList<OneEntryHandler>(); 3274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = (TextUtils.isEmpty(charset) ? VCardConfig.DEFAULT_EXPORT_CHARSET : charset); 3294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final boolean shouldAppendCharsetParam = !( 330be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa VCardConfig.isVersion30(vcardType) && UTF_8.equalsIgnoreCase(charset)); 3314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo || shouldAppendCharsetParam) { 3334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (SHIFT_JIS.equalsIgnoreCase(charset)) { 3344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIsDoCoMo) { 3354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 3364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); 3374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 3384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, 3394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "DoCoMo-specific SHIFT_JIS was not found. " 3404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use SHIFT_JIS as is."); 3414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 3424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 3454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); 3464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 347422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa /* Log.e(LOG_TAG, 3484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific SHIFT_JIS was not found. " 349422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa + "Use SHIFT_JIS as is."); */ 3504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = SHIFT_JIS; 3514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 3544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 355422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa /* Log.w(LOG_TAG, 3564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "The charset \"" + charset + "\" is used while " 357422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa + SHIFT_JIS + " is needed to be used."); */ 3584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 3594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = SHIFT_JIS; 3604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 3624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 3634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 3644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 3654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 3664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 3674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 3694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (TextUtils.isEmpty(charset)) { 3734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = UTF_8; 3744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 3754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 3764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa charset = CharsetUtils.charsetForVendor(charset).name(); 3774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (UnsupportedCharsetException e) { 3784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.i(LOG_TAG, 3794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa "Career-specific \"" + charset + "\" was not found (as usual). " 3804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa + "Use it as is."); 3814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCharset = charset; 3834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\""); 3874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 3904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Must be called before {@link #init()}. 3914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 3924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void addHandler(OneEntryHandler handler) { 3934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (handler != null) { 3944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mHandlerList.add(handler); 3954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 3974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 3984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 3994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return Returns true when initialization is successful and all the other 4004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * methods are available. Returns false otherwise. 4014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 4024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init() { 4034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return init(null, null); 4044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init(final String selection, final String[] selectionArgs) { 4074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return init(Contacts.CONTENT_URI, selection, selectionArgs, null); 4084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 4114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note that this is unstable interface, may be deleted in the future. 4124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 4134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean init(final Uri contentUri, final String selection, 4144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] selectionArgs, final String sortOrder) { 4154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentUri == null) { 4164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCareHandlerErrors) { 4204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final List<OneEntryHandler> finishedList = new ArrayList<OneEntryHandler>( 4214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mHandlerList.size()); 4224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (OneEntryHandler handler : mHandlerList) { 4234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!handler.onInit(mContext)) { 4244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (OneEntryHandler finished : finishedList) { 4254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa finished.onTerminate(); 4264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Just ignore the false returned from onInit(). 4324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (OneEntryHandler handler : mHandlerList) { 4334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa handler.onInit(mContext); 4344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] projection; 4384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (Contacts.CONTENT_URI.equals(contentUri) || 4394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa CONTACTS_TEST_CONTENT_URI.equals(contentUri)) { 4404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa projection = sContactsProjection; 4414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = FAILURE_REASON_UNSUPPORTED_URI; 4434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = mContentResolver.query( 4464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentUri, projection, selection, selectionArgs, sortOrder); 4474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 4494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO; 4504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (getCount() == 0 || !mCursor.moveToFirst()) { 4544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 4554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor.close(); 4564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (SQLiteException e) { 4574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage()); 4584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } finally { 4594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = null; 4604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = FAILURE_REASON_NO_ENTRY; 4614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mIdColumn = mCursor.getColumnIndex(Contacts._ID); 4664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 4684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean createOneEntry() { 4714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return createOneEntry(null); 4724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 4744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 4754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @param getEntityIteratorMethod For Dependency Injection. 4764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @hide just for testing. 4774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 4784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean createOneEntry(Method getEntityIteratorMethod) { 4794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null || mCursor.isAfterLast()) { 4804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mErrorReason = FAILURE_REASON_NOT_INITIALIZED; 4814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String vcard; 4844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 4854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mIdColumn >= 0) { 4864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa vcard = createOneEntryInternal(mCursor.getString(mIdColumn), 4874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa getEntityIteratorMethod); 4884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 4894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn); 4904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 4914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 4924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (VCardException e) { 4934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "VCardException has been thrown: " + e.getMessage()); 4944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 4954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (OutOfMemoryError error) { 4964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Maybe some data (e.g. photo) is too big to have in memory. But it 4974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // should be rare. 4984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "OutOfMemoryError occured. Ignore the entry."); 4994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa System.gc(); 5004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // TODO: should tell users what happened? 5014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 5024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } finally { 5034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor.moveToNext(); 5044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // This function does not care the OutOfMemoryError on the handler side :-P 5074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCareHandlerErrors) { 5084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa List<OneEntryHandler> finishedList = new ArrayList<OneEntryHandler>( 5094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mHandlerList.size()); 5104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (OneEntryHandler handler : mHandlerList) { 5114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!handler.onEntryCreated(vcard)) { 5124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 5134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (OneEntryHandler handler : mHandlerList) { 5174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa handler.onEntryCreated(vcard); 5184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return true; 5224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private String createOneEntryInternal(final String contactId, 5254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Method getEntityIteratorMethod) throws VCardException { 5264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Map<String, List<ContentValues>> contentValuesListMap = 5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa new HashMap<String, List<ContentValues>>(); 5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // The resolver may return the entity iterator with no data. It is possible. 5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // e.g. If all the data in the contact of the given contact id are not exportable ones, 5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // they are hidden from the view of this method, though contact id itself exists. 5314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa EntityIterator entityIterator = null; 5324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 5334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final Uri uri = RawContactsEntity.CONTENT_URI.buildUpon() 5344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // .appendQueryParameter("for_export_only", "1") 5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1") 5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .build(); 5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String selection = Data.CONTACT_ID + "=?"; 5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final String[] selectionArgs = new String[] {contactId}; 5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (getEntityIteratorMethod != null) { 5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa // Please note that this branch is executed by unit tests only 5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 5424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null, 5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mContentResolver, uri, selection, selectionArgs, null); 5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IllegalArgumentException e) { 5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "IllegalArgumentException has been thrown: " + 5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (IllegalAccessException e) { 5484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "IllegalAccessException has been thrown: " + 5494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getMessage()); 5504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (InvocationTargetException e) { 5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "InvocationTargetException has been thrown: "); 5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa StackTraceElement[] stackTraceElements = e.getCause().getStackTrace(); 5534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (StackTraceElement element : stackTraceElements) { 5544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, " at " + element.toString()); 5554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa throw new VCardException("InvocationTargetException has been thrown: " + 5574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa e.getCause().getMessage()); 5584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 5604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator = RawContacts.newEntityIterator(mContentResolver.query( 5614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa uri, null, selection, selectionArgs, null)); 5624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (entityIterator == null) { 5654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "EntityIterator is null"); 5664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!entityIterator.hasNext()) { 5704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "Data does not exist. contactId: " + contactId); 5714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 5724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa while (entityIterator.hasNext()) { 5754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Entity entity = entityIterator.next(); 5764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (NamedContentValues namedContentValues : entity.getSubValues()) { 5774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa ContentValues contentValues = namedContentValues.values; 5784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa String key = contentValues.getAsString(Data.MIMETYPE); 5794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (key != null) { 5804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa List<ContentValues> contentValuesList = 5814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesListMap.get(key); 5824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesList == null) { 5834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesList = new ArrayList<ContentValues>(); 5844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesListMap.put(key, contentValuesList); 5854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa contentValuesList.add(contentValues); 5874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } finally { 5914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (entityIterator != null) { 5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa entityIterator.close(); 5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return buildVCard(contentValuesListMap); 5974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 5984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 5994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Builds and returns vCard using given map, whose key is CONTENT_ITEM_TYPE defined in 6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {ContactsContract}. Developers can override this method to customize the output. 6024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String buildVCard(final Map<String, List<ContentValues>> contentValuesListMap) { 6044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (contentValuesListMap == null) { 6054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "The given map is null. Ignore and return empty String"); 6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return ""; 6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } else { 6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset); 6094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) 6104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) 6114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) 6124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) 6134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) 6144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) 6158c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)); 6168c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa if ((mVCardType & VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT) == 0) { 6178c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa builder.appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)); 6188c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa } 6198c1cdbbccd5169122c183f6fbfd4436faacf2a1dDaisuke Miyakawa builder.appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) 6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) 6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) 622422643669a44d08ca8b22a73286fae988a288b0eDaisuke Miyakawa .appendSipAddresses(contentValuesListMap.get(SipAddress.CONTENT_ITEM_TYPE)) 6234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); 6244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return builder.toString(); 6254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void terminate() { 6294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa for (OneEntryHandler handler : mHandlerList) { 6304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa handler.onTerminate(); 6314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor != null) { 6344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa try { 6354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor.close(); 6364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } catch (SQLiteException e) { 6374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage()); 6384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mCursor = null; 6404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mTerminateIsCalled = true; 6434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa @Override 6464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void finalize() { 6474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (!mTerminateIsCalled) { 6484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "terminate() is not called yet. We call it in finalize() step."); 6494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa terminate(); 6504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return returns the number of available entities. The return value is undefined 6554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * when this object is not ready yet (typically when {{@link #init()} is not called 6564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * or when {@link #terminate()} is already called). 6574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public int getCount() { 6594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 6604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "This object is not ready yet."); 6614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return 0; 6624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCursor.getCount(); 6644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return true when there's no entity to be built. The return value is undefined 6684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * when this object is not ready yet. 6694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public boolean isAfterLast() { 6714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (mCursor == null) { 6724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.w(LOG_TAG, "This object is not ready yet."); 6734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return false; 6744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCursor.isAfterLast(); 6764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 6784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 6794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * @return Returns the error reason. 6804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 6814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public String getErrorReason() { 6824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mErrorReason; 6834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 6844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa} 685