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"); 54199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * you may not use this file except in compliance with the License. 64199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * You may obtain a copy of 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, 124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * See the License for the specific language governing permissions and 144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * limitations under the License. 154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapackage com.android.vcard; 174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 18f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.content.ContentProviderOperation; 19f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.content.ContentProviderResult; 204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentResolver; 21f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.content.OperationApplicationException; 224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.net.Uri; 23f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.os.RemoteException; 24f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.provider.ContactsContract; 254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log; 264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList; 284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/** 304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <P> 314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VCardEntryHandler} implementation which commits the entry to ContentResolver. 324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </P> 334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <P> 344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note:<BR /> 354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Each vCard may contain big photo images encoded by BASE64, 364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * If we store all vCard entries in memory, OutOfMemoryError may be thrown. 374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Thus, this class push each VCard entry into ContentResolver immediately. 384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </P> 394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardEntryCommitter implements VCardEntryHandler { 4102117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa public static String LOG_TAG = VCardConstants.LOG_TAG; 424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private final ContentResolver mContentResolver; 444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa private long mTimeToCommit; 45f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa private int mCounter; 46f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa private ArrayList<ContentProviderOperation> mOperationList; 4702117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa private final ArrayList<Uri> mCreatedUris = new ArrayList<Uri>(); 484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public VCardEntryCommitter(ContentResolver resolver) { 504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mContentResolver = resolver; 514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 53f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa @Override 544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void onStart() { 554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 57f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa @Override 584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void onEnd() { 59f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa if (mOperationList != null) { 60f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa mCreatedUris.add(pushIntoContentResolver(mOperationList)); 61f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa } 62f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa 634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa if (VCardConfig.showPerformanceLog()) { 644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit)); 654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 68f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa @Override 694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public void onEntryCreated(final VCardEntry vcardEntry) { 70f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa final long start = System.currentTimeMillis(); 71f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa mOperationList = vcardEntry.constructInsertOperations(mContentResolver, mOperationList); 72f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa mCounter++; 73f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa if (mCounter >= 20) { 74f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa mCreatedUris.add(pushIntoContentResolver(mOperationList)); 75f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa mCounter = 0; 76f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa mOperationList = null; 77f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa } 784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa mTimeToCommit += System.currentTimeMillis() - start; 794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa 81f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa private Uri pushIntoContentResolver(ArrayList<ContentProviderOperation> operationList) { 82f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa try { 83f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa final ContentProviderResult[] results = mContentResolver.applyBatch( 84f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa ContactsContract.AUTHORITY, operationList); 85f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa 86f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa // the first result is always the raw_contact. return it's uri so 87f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa // that it can be found later. do null checking for badly behaving 88f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa // ContentResolvers 89f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa return ((results == null || results.length == 0 || results[0] == null) 90f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa ? null : results[0].uri); 91f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa } catch (RemoteException e) { 92f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); 93f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa return null; 94f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa } catch (OperationApplicationException e) { 95f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); 96f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa return null; 97f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa } 98f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa } 99f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa 1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa /** 1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Returns the list of created Uris. This list should not be modified by the caller as it is 1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * not a clone. 1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */ 1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa public ArrayList<Uri> getCreatedUris() { 1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa return mCreatedUris; 1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa } 1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}