137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan/* 237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Copyright (C) 2011 The Android Open Source Project 337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * 437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Licensed under the Apache License, Version 2.0 (the "License"); 537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * you may not use this file except in compliance with the License. 637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * You may obtain a copy of the License at 737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * 837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * http://www.apache.org/licenses/LICENSE-2.0 937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * 1037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Unless required by applicable law or agreed to in writing, software 1137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * distributed under the License is distributed on an "AS IS" BASIS, 1237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * See the License for the specific language governing permissions and 1437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * limitations under the License 1537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 1637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 1737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanpackage com.android.contacts.activities; 1837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 1937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.app.Activity; 2037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.app.Dialog; 2137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.app.ProgressDialog; 2237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.AsyncQueryHandler; 2337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.ContentProviderOperation; 2437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.ContentProviderResult; 2537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.ContentResolver; 2637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.ContentUris; 2737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.Context; 2837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.Intent; 2937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.content.OperationApplicationException; 3037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.database.Cursor; 3137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.graphics.Bitmap; 3237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.graphics.BitmapFactory; 3337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.net.Uri; 3437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.net.Uri.Builder; 3537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.os.AsyncTask; 3637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.os.Bundle; 3737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.os.RemoteException; 3837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract; 3937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Email; 4037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Im; 4137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Nickname; 4237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Phone; 4337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Photo; 44ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onukiimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 4537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 4637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.Contacts; 4737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.Data; 4837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.provider.ContactsContract.RawContacts; 49c90f95e63684363d10ffe5ef8f08f2159fb5bfc0Dave Santoroimport android.provider.ContactsContract.RawContactsEntity; 5037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.telephony.PhoneNumberUtils; 5137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.text.TextUtils; 5237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.util.Log; 5337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.view.LayoutInflater; 5437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.view.View; 5537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.view.View.OnClickListener; 5637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.view.ViewGroup; 5737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.widget.ImageView; 5837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.widget.TextView; 5937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport android.widget.Toast; 6037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 61e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 62e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.Editor; 63e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.ViewIdGenerator; 64e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.model.AccountTypeManager; 65851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContact; 66851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactDelta; 67851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactDelta.ValuesDelta; 68851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactDeltaList; 69851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactModifier; 70851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.account.AccountType; 71851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.account.AccountWithDataSet; 72851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.dataitem.DataKind; 73e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.DialogManager; 74e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.EmptyService; 75e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 7637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport java.lang.ref.WeakReference; 7737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport java.util.ArrayList; 7837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanimport java.util.HashMap; 79ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onukiimport java.util.List; 8037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 8137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan/** 8237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * This is a dialog-themed activity for confirming the addition of a detail to an existing contact 8337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * (once the user has selected this contact from a list of all contacts). The incoming intent 8437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * must have an extra with max 1 phone or email specified, using 85a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki * {@link android.provider.ContactsContract.Intents.Insert#PHONE} with type 86a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki * {@link android.provider.ContactsContract.Intents.Insert#PHONE_TYPE} or 87a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki * {@link android.provider.ContactsContract.Intents.Insert#EMAIL} with type 88a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki * {@link android.provider.ContactsContract.Intents.Insert#EMAIL_TYPE} intent keys. 89ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * 90ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * If the selected contact doesn't contain editable raw_contacts, it'll create a new raw_contact 91ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * on the first editable account found, and the data will be added to this raw_contact. The newly 92ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * created raw_contact will be joined with the selected contact with aggregation-exceptions. 93ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * 94ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * TODO: Don't open this activity if there's no editable accounts. 95ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * If there's no editable accounts on the system, we'll set {@link #mIsReadOnly} and the dialog 96ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * just says "contact is not editable". It's slightly misleading because this really means 97ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * "there's no editable accounts", but in this case we shouldn't show the contact picker in the 98ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * first place. 99ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * Note when there's no accounts, it *is* okay to show the picker / dialog, because the local-only 100ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * contacts are writable. 10137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 10237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuanpublic class ConfirmAddDetailActivity extends Activity implements 10337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan DialogManager.DialogShowingViewActivity { 10437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 105a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private static final String TAG = "ConfirmAdd"; // The class name is too long to be a tag. 106a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 10737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 10837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private LayoutInflater mInflater; 10937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private View mRootView; 11037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private TextView mDisplayNameView; 11137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private TextView mReadOnlyWarningView; 11237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private ImageView mPhotoView; 11337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private ViewGroup mEditorContainerView; 114fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan private static WeakReference<ProgressDialog> sProgressDialog; 11537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 11637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private AccountTypeManager mAccountTypeManager; 11737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private ContentResolver mContentResolver; 11837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 11937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private AccountType mEditableAccountType; 12037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private Uri mContactUri; 12137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private long mContactId; 12237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private String mDisplayName; 123a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private boolean mIsReadOnly; 12437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 12537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private QueryHandler mQueryHandler; 126a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki 127851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu /** {@link RawContactDeltaList} for the entire selected contact. */ 128851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private RawContactDeltaList mEntityDeltaList; 12937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 130851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu /** {@link RawContactDeltaList} for the editable account */ 131851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private RawContactDelta mRawContactDelta; 132a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki 13337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private String mMimetype = Phone.CONTENT_ITEM_TYPE; 13437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 13537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 13637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * DialogManager may be needed if the user wants to apply a "custom" label to the contact detail 13737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 13837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private final DialogManager mDialogManager = new DialogManager(this); 13937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 14037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 14137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * PhotoQuery contains the projection used for retrieving the name and photo 14237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * ID of a contact. 14337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 14437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private interface ContactQuery { 14537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final String[] COLUMNS = new String[] { 14637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Contacts._ID, 14737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Contacts.LOOKUP_KEY, 14837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Contacts.PHOTO_ID, 14937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Contacts.DISPLAY_NAME, 15037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan }; 15137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int _ID = 0; 15237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int LOOKUP_KEY = 1; 15337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int PHOTO_ID = 2; 15437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int DISPLAY_NAME = 3; 15537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 15637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 15737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 15837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * PhotoQuery contains the projection used for retrieving the raw bytes of 15937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * the contact photo. 16037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 16137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private interface PhotoQuery { 16237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final String[] COLUMNS = new String[] { 16337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Photo.PHOTO 16437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan }; 16537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 16637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int PHOTO = 0; 16737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 16837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 16937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 17037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * ExtraInfoQuery contains the projection used for retrieving the extra info 17137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * on a contact (only needed if someone else exists with the same name as 17237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * this contact). 17337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 17437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private interface ExtraInfoQuery { 17537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final String[] COLUMNS = new String[] { 17637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan RawContacts.CONTACT_ID, 17737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Data.MIMETYPE, 17837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Data.DATA1, 17937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan }; 18037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int CONTACT_ID = 0; 18137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int MIMETYPE = 1; 18237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final int DATA1 = 2; 18337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 18437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 18537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 18637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * List of mimetypes to use in order of priority to display for a contact in 18737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * a disambiguation case. For example, if the contact does not have a 18837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * nickname, use the email field, and etc. 18937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 190a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private static final String[] MIME_TYPE_PRIORITY_LIST = new String[] { 191a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki Nickname.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE, Im.CONTENT_ITEM_TYPE, 192a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki StructuredPostal.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE }; 19337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 19437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int TOKEN_CONTACT_INFO = 0; 19537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int TOKEN_PHOTO_QUERY = 1; 19637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int TOKEN_DISAMBIGUATION_QUERY = 2; 19737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int TOKEN_EXTRA_INFO_QUERY = 3; 19837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 19937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private final OnClickListener mDetailsButtonClickListener = new OnClickListener() { 20037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 20137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public void onClick(View v) { 202a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki if (mIsReadOnly) { 20337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan onSaveCompleted(true); 20437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else { 20537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan doSaveAction(); 20637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 20737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 20837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan }; 20937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 21037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private final OnClickListener mDoneButtonClickListener = new OnClickListener() { 21137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 21237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public void onClick(View v) { 21337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan doSaveAction(); 21437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 21537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan }; 21637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 21737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private final OnClickListener mCancelButtonClickListener = new OnClickListener() { 21837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 21937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public void onClick(View v) { 22037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setResult(RESULT_CANCELED); 22137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan finish(); 22237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 22337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan }; 22437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 22537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 22637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan protected void onCreate(Bundle icicle) { 22737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan super.onCreate(icicle); 22837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 22937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 23037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mContentResolver = getContentResolver(); 23137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 23237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final Intent intent = getIntent(); 23337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mContactUri = intent.getData(); 23437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 23537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (mContactUri == null) { 23637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setResult(RESULT_CANCELED); 23737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan finish(); 23837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 23937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 24037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Bundle extras = intent.getExtras(); 24137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (extras != null) { 24237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (extras.containsKey(ContactsContract.Intents.Insert.PHONE)) { 24337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mMimetype = Phone.CONTENT_ITEM_TYPE; 24437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else if (extras.containsKey(ContactsContract.Intents.Insert.EMAIL)) { 24537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mMimetype = Email.CONTENT_ITEM_TYPE; 24637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else { 24737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan throw new IllegalStateException("Error: No valid mimetype found in intent extras"); 24837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 24937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 25037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 25137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mAccountTypeManager = AccountTypeManager.getInstance(this); 25237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 25337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setContentView(R.layout.confirm_add_detail_activity); 25437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 25537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mRootView = findViewById(R.id.root_view); 25637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mReadOnlyWarningView = (TextView) findViewById(R.id.read_only_warning); 25737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 25837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Setup "header" (containing contact info) to save the detail and then go to the editor 25937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan findViewById(R.id.open_details_push_layer).setOnClickListener(mDetailsButtonClickListener); 26037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 26137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Setup "done" button to save the detail to the contact and exit. 26237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan findViewById(R.id.btn_done).setOnClickListener(mDoneButtonClickListener); 26337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 26437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Setup "cancel" button to return to previous activity. 26537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan findViewById(R.id.btn_cancel).setOnClickListener(mCancelButtonClickListener); 26637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 26737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Retrieve references to all the Views in the dialog activity. 26837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mDisplayNameView = (TextView) findViewById(R.id.name); 26937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mPhotoView = (ImageView) findViewById(R.id.photo); 27037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mEditorContainerView = (ViewGroup) findViewById(R.id.editor_container); 27137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 272a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki resetAsyncQueryHandler(); 273a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki startContactQuery(mContactUri); 27437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 27537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan new QueryEntitiesTask(this).execute(intent); 27637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 27737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 27837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 27937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public DialogManager getDialogManager() { 28037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return mDialogManager; 28137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 28237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 28337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 28437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan protected Dialog onCreateDialog(int id, Bundle args) { 28537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (DialogManager.isManagedId(id)) return mDialogManager.onCreateDialog(id, args); 28637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 28737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Nobody knows about the Dialog 28837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Log.w(TAG, "Unknown dialog requested, id: " + id + ", args: " + args); 28937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return null; 29037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 29137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 29237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 29337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Reset the query handler by creating a new QueryHandler instance. 29437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 29537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void resetAsyncQueryHandler() { 29637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // the api AsyncQueryHandler.cancelOperation() doesn't really work. Since we really 29737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // need the old async queries to be cancelled, let's do it the hard way. 29837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mQueryHandler = new QueryHandler(mContentResolver); 29937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 30037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 30137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 30237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Internal method to query contact by Uri. 30337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * 30437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * @param contactUri the contact uri 30537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 306a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private void startContactQuery(Uri contactUri) { 30737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mQueryHandler.startQuery(TOKEN_CONTACT_INFO, contactUri, contactUri, ContactQuery.COLUMNS, 30837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan null, null, null); 30937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 31037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 31137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 31237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Internal method to query contact photo by photo id and uri. 31337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * 31437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * @param photoId the photo id. 31537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * @param lookupKey the lookup uri. 31637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 317a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private void startPhotoQuery(long photoId, Uri lookupKey) { 31837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mQueryHandler.startQuery(TOKEN_PHOTO_QUERY, lookupKey, 31937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan ContentUris.withAppendedId(Data.CONTENT_URI, photoId), 32037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan PhotoQuery.COLUMNS, null, null, null); 32137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 32237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 32337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 32437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Internal method to query for contacts with a given display name. 32537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * 32637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * @param contactDisplayName the display name to look for. 32737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 32837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void startDisambiguationQuery(String contactDisplayName) { 32937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Apply a limit of 1 result to the query because we only need to 33037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // determine whether or not at least one other contact has the same 33137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // name. We don't need to find ALL other contacts with the same name. 3321d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan final Builder builder = Contacts.CONTENT_URI.buildUpon(); 33337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan builder.appendQueryParameter("limit", String.valueOf(1)); 3341d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan final Uri uri = builder.build(); 3351d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan 3361d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan final String displayNameSelection; 3371d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan final String[] selectionArgs; 3381d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan if (TextUtils.isEmpty(contactDisplayName)) { 3391d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan displayNameSelection = Contacts.DISPLAY_NAME_PRIMARY + " IS NULL"; 3401d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan selectionArgs = new String[] { String.valueOf(mContactId) }; 3411d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan } else { 3421d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan displayNameSelection = Contacts.DISPLAY_NAME_PRIMARY + " = ?"; 3431d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan selectionArgs = new String[] { contactDisplayName, String.valueOf(mContactId) }; 3441d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan } 34537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mQueryHandler.startQuery(TOKEN_DISAMBIGUATION_QUERY, null, uri, 34637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan new String[] { Contacts._ID } /* unused projection but a valid one was needed */, 3471d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan displayNameSelection + " AND " + Contacts.PHOTO_ID + " IS NULL AND " 3481d5fdfb2cec7d082c007b5f7ede20be44c24dc1aKatherine Kuan + Contacts._ID + " <> ?", selectionArgs, null); 34937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 35037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 35137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 35237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Internal method to query for extra data fields for this contact. 35337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 35437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void startExtraInfoQuery() { 35537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mQueryHandler.startQuery(TOKEN_EXTRA_INFO_QUERY, null, Data.CONTENT_URI, 35637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan ExtraInfoQuery.COLUMNS, RawContacts.CONTACT_ID + " = ?", 35737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan new String[] { String.valueOf(mContactId) }, null); 35837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 35937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 360851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private static class QueryEntitiesTask extends AsyncTask<Intent, Void, RawContactDeltaList> { 36137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 36237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private ConfirmAddDetailActivity activityTarget; 36337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private String mSelection; 36437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 36537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public QueryEntitiesTask(ConfirmAddDetailActivity target) { 36637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan activityTarget = target; 36737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 36837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 36937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 370851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu protected RawContactDeltaList doInBackground(Intent... params) { 37137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 37237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final Intent intent = params[0]; 37337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 37437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final ContentResolver resolver = activityTarget.getContentResolver(); 37537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 37637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Handle both legacy and new authorities 37737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final Uri data = intent.getData(); 37837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final String authority = data.getAuthority(); 37937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final String mimeType = intent.resolveType(resolver); 38037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 38137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mSelection = "0"; 38237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan String selectionArg = null; 38337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (ContactsContract.AUTHORITY.equals(authority)) { 38437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (Contacts.CONTENT_ITEM_TYPE.equals(mimeType)) { 38537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Handle selected aggregate 38637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final long contactId = ContentUris.parseId(data); 38737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan selectionArg = String.valueOf(contactId); 38837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mSelection = RawContacts.CONTACT_ID + "=?"; 38937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else if (RawContacts.CONTENT_ITEM_TYPE.equals(mimeType)) { 39037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final long rawContactId = ContentUris.parseId(data); 39137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final long contactId = queryForContactId(resolver, rawContactId); 39237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan selectionArg = String.valueOf(contactId); 39337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mSelection = RawContacts.CONTACT_ID + "=?"; 39437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 39537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else if (android.provider.Contacts.AUTHORITY.equals(authority)) { 39637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final long rawContactId = ContentUris.parseId(data); 39737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan selectionArg = String.valueOf(rawContactId); 39837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mSelection = Data.RAW_CONTACT_ID + "=?"; 39937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 40037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 401c90f95e63684363d10ffe5ef8f08f2159fb5bfc0Dave Santoro // Note that this query does not need to concern itself with whether the contact is 402c90f95e63684363d10ffe5ef8f08f2159fb5bfc0Dave Santoro // the user's profile, since the profile does not show up in the picker. 403851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu return RawContactDeltaList.fromQuery(RawContactsEntity.CONTENT_URI, 404c90f95e63684363d10ffe5ef8f08f2159fb5bfc0Dave Santoro activityTarget.getContentResolver(), mSelection, 40537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan new String[] { selectionArg }, null); 40637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 40737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 40837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static long queryForContactId(ContentResolver resolver, long rawContactId) { 40937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Cursor contactIdCursor = null; 41037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan long contactId = -1; 41137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan try { 41237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan contactIdCursor = resolver.query(RawContacts.CONTENT_URI, 41337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan new String[] { RawContacts.CONTACT_ID }, 41437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan RawContacts._ID + "=?", new String[] { String.valueOf(rawContactId) }, 41537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan null); 41637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (contactIdCursor != null && contactIdCursor.moveToFirst()) { 41737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan contactId = contactIdCursor.getLong(0); 41837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 41937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } finally { 42037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (contactIdCursor != null) { 42137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan contactIdCursor.close(); 42237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 42337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 42437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return contactId; 42537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 42637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 42737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 428851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu protected void onPostExecute(RawContactDeltaList entityList) { 42937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (activityTarget.isFinishing()) { 43037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return; 43137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 432ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki if ((entityList == null) || (entityList.size() == 0)) { 433ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki Log.e(TAG, "Contact not found."); 434ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki activityTarget.finish(); 435ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki return; 436ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 437ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 43837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan activityTarget.setEntityDeltaList(entityList); 43937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 44037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 44137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 44237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private class QueryHandler extends AsyncQueryHandler { 44337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 44437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public QueryHandler(ContentResolver cr) { 44537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan super(cr); 44637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 44737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 44837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 44937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 45037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan try { 45137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (this != mQueryHandler) { 45237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Log.d(TAG, "onQueryComplete: discard result, the query handler is reset!"); 45337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return; 45437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 45537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (ConfirmAddDetailActivity.this.isFinishing()) { 45637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return; 45737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 45837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 45937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan switch (token) { 46037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan case TOKEN_PHOTO_QUERY: { 46137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Set the photo 46237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Bitmap photoBitmap = null; 46337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (cursor != null && cursor.moveToFirst() 46437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan && !cursor.isNull(PhotoQuery.PHOTO)) { 46537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan byte[] photoData = cursor.getBlob(PhotoQuery.PHOTO); 46637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan photoBitmap = BitmapFactory.decodeByteArray(photoData, 0, 46737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan photoData.length, null); 46837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 46937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 47037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (photoBitmap != null) { 47137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mPhotoView.setImageBitmap(photoBitmap); 47237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 47337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 47437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 47537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 47637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan case TOKEN_CONTACT_INFO: { 47737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Set the contact's name 47837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (cursor != null && cursor.moveToFirst()) { 47937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Get the cursor values 48037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mDisplayName = cursor.getString(ContactQuery.DISPLAY_NAME); 48137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final long photoId = cursor.getLong(ContactQuery.PHOTO_ID); 48237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 48337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // If there is no photo ID, then do a disambiguation 48437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // query because other contacts could have the same 48537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // name as this contact. 48637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (photoId == 0) { 48737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mContactId = cursor.getLong(ContactQuery._ID); 48837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan startDisambiguationQuery(mDisplayName); 48937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else { 49037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Otherwise do the photo query. 49137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Uri lookupUri = Contacts.getLookupUri(mContactId, 49237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan cursor.getString(ContactQuery.LOOKUP_KEY)); 493a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki startPhotoQuery(photoId, lookupUri); 49437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Display the name because there is no 49537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // disambiguation query. 49637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setDisplayName(); 497a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki showDialogContent(); 49837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 49937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 50037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 50137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 50237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan case TOKEN_DISAMBIGUATION_QUERY: { 50337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // If a cursor was returned with more than 0 results, 50437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // then at least one other contact exists with the same 50537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // name as this contact. Extra info on this contact must 50637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // be displayed to disambiguate the contact, so retrieve 50737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // those additional fields. Otherwise, no other contacts 50837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // with this name exists, so do nothing further. 50937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (cursor != null && cursor.getCount() > 0) { 51037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan startExtraInfoQuery(); 51137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else { 51237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // If there are no other contacts with this name, 51337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // then display the name. 51437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setDisplayName(); 515a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki showDialogContent(); 51637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 51737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 51837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 51937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan case TOKEN_EXTRA_INFO_QUERY: { 52037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // This case should only occur if there are one or more 52137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // other contacts with the same contact name. 52237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (cursor != null && cursor.moveToFirst()) { 52337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan HashMap<String, String> hashMapCursorData = new 52437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan HashMap<String, String>(); 52537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 52637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Convert the cursor data into a hashmap of 52737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // (mimetype, data value) pairs. If a contact has 52837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // multiple values with the same mimetype, it's fine 52937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // to override that hashmap entry because we only 53037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // need one value of that type. 53137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan while (!cursor.isAfterLast()) { 53237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final String mimeType = cursor.getString(ExtraInfoQuery.MIMETYPE); 53337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (!TextUtils.isEmpty(mimeType)) { 53437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan String value = cursor.getString(ExtraInfoQuery.DATA1); 53537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (!TextUtils.isEmpty(value)) { 53637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // As a special case, phone numbers 53737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // should be formatted in a specific way. 53837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) { 53937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan value = PhoneNumberUtils.formatNumber(value); 54037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 54137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan hashMapCursorData.put(mimeType, value); 54237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 54337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 54437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan cursor.moveToNext(); 54537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 54637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 54737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Find the first non-empty field according to the 54837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // mimetype priority list and display this under the 54937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // contact's display name to disambiguate the contact. 550a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki for (String mimeType : MIME_TYPE_PRIORITY_LIST) { 55137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (hashMapCursorData.containsKey(mimeType)) { 55237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setDisplayName(); 55337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setExtraInfoField(hashMapCursorData.get(mimeType)); 55437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 55537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 55637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 557a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki showDialogContent(); 55837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 55937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 56037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 56137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 56237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } finally { 56337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (cursor != null) { 56437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan cursor.close(); 56537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 56637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 56737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 56837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 56937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 570851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private void setEntityDeltaList(RawContactDeltaList entityList) { 571a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki if (entityList == null) { 572a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki throw new IllegalStateException(); 573a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki } 574a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki if (VERBOSE_LOGGING) { 575a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki Log.v(TAG, "setEntityDeltaList: " + entityList); 576a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki } 577a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki 57837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mEntityDeltaList = entityList; 57937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 580ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // Find the editable raw_contact. 581851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mRawContactDelta = mEntityDeltaList.getFirstWritableRawContact(this); 582ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 583ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // If no editable raw_contacts are found, create one. 584851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (mRawContactDelta == null) { 585851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mRawContactDelta = addEditableRawContact(this, mEntityDeltaList); 586ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 587851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if ((mRawContactDelta != null) && VERBOSE_LOGGING) { 588ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki Log.v(TAG, "setEntityDeltaList: created editable raw_contact " + entityList); 589ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 590ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 591ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 592851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (mRawContactDelta == null) { 593ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // Selected contact is read-only, and there's no editable account. 594a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki mIsReadOnly = true; 595a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki mEditableAccountType = null; 596a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki } else { 597a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki mIsReadOnly = false; 59837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 599851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mEditableAccountType = mRawContactDelta.getRawContactAccountType(this); 600a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki 601a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki // Handle any incoming values that should be inserted 602a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki final Bundle extras = getIntent().getExtras(); 603a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki if (extras != null && extras.size() > 0) { 604851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // If there are any intent extras, add them as additional fields in the 605851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // RawContactDelta. 606851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.parseExtras(this, mEditableAccountType, mRawContactDelta, 607851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu extras); 608a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki } 60937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 610a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki 611a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki bindEditor(); 61237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 61337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 61437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 615851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * Create an {@link RawContactDelta} for a raw_contact on the first editable account found, and add 616ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * to the list. Also copy the structured name from an existing (read-only) raw_contact to the 617ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki * new one, if any of the read-only contacts has a name. 618ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki */ 619851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private static RawContactDelta addEditableRawContact(Context context, 620851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList entityDeltaList) { 621ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // First, see if there's an editable account. 622ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki final AccountTypeManager accounts = AccountTypeManager.getInstance(context); 623ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki final List<AccountWithDataSet> editableAccounts = accounts.getAccounts(true); 624ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki if (editableAccounts.size() == 0) { 625ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // No editable account type found. The dialog will be read-only mode. 626ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki return null; 627ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 628ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki final AccountWithDataSet editableAccount = editableAccounts.get(0); 629ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki final AccountType accountType = accounts.getAccountType( 630ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki editableAccount.type, editableAccount.dataSet); 631ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 632851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // Create a new RawContactDelta for the new raw_contact. 633851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContact rawContact = new RawContact(context); 634851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.setAccount(editableAccount); 635ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 636851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta entityDelta = new RawContactDelta(ValuesDelta.fromAfter( 637851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.getValues())); 638ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 639ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // Then, copy the structure name from an existing (read-only) raw_contact. 640851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContactDelta entity : entityDeltaList) { 641ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki final ArrayList<ValuesDelta> readOnlyNames = 642ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki entity.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE); 643ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki if ((readOnlyNames != null) && (readOnlyNames.size() > 0)) { 644ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki final ValuesDelta readOnlyName = readOnlyNames.get(0); 645851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final ValuesDelta newName = RawContactModifier.ensureKindExists(entityDelta, 646ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki accountType, StructuredName.CONTENT_ITEM_TYPE); 647ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 648ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // Copy all the data fields. 649851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu newName.copyStructuredNameFieldsFrom(readOnlyName); 650ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki break; 651ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 652ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 653ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 654851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // Add the new RawContactDelta to the list. 655ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki entityDeltaList.add(entityDelta); 656ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 657ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki return entityDelta; 658ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki } 659ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki 660ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki /** 66137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Rebuild the editor to match our underlying {@link #mEntityDeltaList} object. 66237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 66337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void bindEditor() { 66437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (mEntityDeltaList == null) { 665a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki throw new IllegalStateException(); 66637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 66737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 66837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // If no valid raw contact (to insert the data) was found, we won't have an editable 66937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // account type to use. In this case, display an error message and hide the "OK" button. 670a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki if (mIsReadOnly) { 67137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mReadOnlyWarningView.setText(getString(R.string.contact_read_only)); 67237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mReadOnlyWarningView.setVisibility(View.VISIBLE); 67337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mEditorContainerView.setVisibility(View.GONE); 67437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan findViewById(R.id.btn_done).setVisibility(View.GONE); 67537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Nothing more to be done, just show the UI 676a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki showDialogContent(); 67737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return; 67837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 67937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 68037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Otherwise display an editor that allows the user to add the data to this raw contact. 68137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan for (DataKind kind : mEditableAccountType.getSortedDataKinds()) { 68237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Skip kind that are not editable 68337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (!kind.editable) continue; 68437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (mMimetype.equals(kind.mimeType)) { 685851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (ValuesDelta valuesDelta : mRawContactDelta.getMimeEntries(mMimetype)) { 68637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Skip entries that aren't visible 68737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (!valuesDelta.isVisible()) continue; 68837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (valuesDelta.isInsert()) { 689851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu inflateEditorView(kind, valuesDelta, mRawContactDelta); 69037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return; 69137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 69237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 69337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 69437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 69537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 69637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 69737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 69837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Creates an EditorView for the given entry. This function must be used while constructing 69937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * the views corresponding to the the object-model. The resulting EditorView is also added 70037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * to the end of mEditors 70137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 702851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private void inflateEditorView(DataKind dataKind, ValuesDelta valuesDelta, RawContactDelta state) { 70337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final View view = mInflater.inflate(dataKind.editorLayoutResourceId, mEditorContainerView, 70437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan false); 70537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 70637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (view instanceof Editor) { 70737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Editor editor = (Editor) view; 70837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Don't allow deletion of the field because there is only 1 detail in this editor. 70937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan editor.setDeletable(false); 71037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan editor.setValues(dataKind, valuesDelta, state, false, new ViewIdGenerator()); 71137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 71237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 71337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mEditorContainerView.addView(view); 71437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 71537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 71637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 71737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Set the display name to the correct TextView. Don't do this until it is 71837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * certain there is no need for a disambiguation field (otherwise the screen 71937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * will flicker because the name will be centered and then moved upwards). 72037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 72137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void setDisplayName() { 72237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mDisplayNameView.setText(mDisplayName); 72337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 72437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 72537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 72637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Set the TextView (for extra contact info) with the given value and make the 72737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * TextView visible. 72837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 72937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void setExtraInfoField(String value) { 73037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan TextView extraTextView = (TextView) findViewById(R.id.extra_info); 73137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan extraTextView.setVisibility(View.VISIBLE); 73237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan extraTextView.setText(value); 73337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 73437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 73537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 73637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Shows all the contents of the dialog to the user at one time. This should only be called 73737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * once all the queries have completed, otherwise the screen will flash as additional data 73837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * comes in. 73937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 740a84cf9274905479f09eb01dd3e7c6fbc2c5c6145Makoto Onuki private void showDialogContent() { 74137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mRootView.setVisibility(View.VISIBLE); 74237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 74337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 74437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 74537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Saves or creates the contact based on the mode, and if successful 74637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * finishes the activity. 74737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 74837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void doSaveAction() { 74937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final PersistTask task = new PersistTask(this, mAccountTypeManager); 75037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan task.execute(mEntityDeltaList); 75137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 75237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 75337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 75437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * Background task for persisting edited contact data, using the changes 755851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * defined by a set of {@link RawContactDelta}. This task starts 75637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * {@link EmptyService} to make sure the background thread can finish 75737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * persisting in cases where the system wants to reclaim our process. 75837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 759851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private static class PersistTask extends AsyncTask<RawContactDeltaList, Void, Integer> { 76037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // In the future, use ContactSaver instead of WeakAsyncTask because of 76137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // the danger of the activity being null during a save action 76237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int PERSIST_TRIES = 3; 76337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 76437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int RESULT_UNCHANGED = 0; 76537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int RESULT_SUCCESS = 1; 76637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private static final int RESULT_FAILURE = 2; 76737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 76837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private ConfirmAddDetailActivity activityTarget; 76937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 77037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private AccountTypeManager mAccountTypeManager; 77137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 77237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan public PersistTask(ConfirmAddDetailActivity target, AccountTypeManager accountTypeManager) { 77337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan activityTarget = target; 77437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mAccountTypeManager = accountTypeManager; 77537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 77637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 77737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 77837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan protected void onPreExecute() { 779fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan sProgressDialog = new WeakReference<ProgressDialog>(ProgressDialog.show(activityTarget, 780fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan null, activityTarget.getText(R.string.savingContact))); 78137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 78237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Before starting this task, start an empty service to protect our 78337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // process from being reclaimed by the system. 78437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final Context context = activityTarget; 78537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan context.startService(new Intent(context, EmptyService.class)); 78637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 78737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 78837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 789851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu protected Integer doInBackground(RawContactDeltaList... params) { 79037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final Context context = activityTarget; 79137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final ContentResolver resolver = context.getContentResolver(); 79237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 793851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state = params[0]; 79437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 795e491b1f517f26b059778bd997f03f4f33fc8c15eKatherine Kuan if (state == null) { 796e491b1f517f26b059778bd997f03f4f33fc8c15eKatherine Kuan return RESULT_FAILURE; 797e491b1f517f26b059778bd997f03f4f33fc8c15eKatherine Kuan } 798e491b1f517f26b059778bd997f03f4f33fc8c15eKatherine Kuan 79937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Trim any empty fields, and RawContacts, before persisting 800851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.trimEmpty(state, mAccountTypeManager); 80137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 80237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Attempt to persist changes 80337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan int tries = 0; 80437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Integer result = RESULT_FAILURE; 80537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan while (tries++ < PERSIST_TRIES) { 80637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan try { 80737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Build operations and try applying 808ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // Note: In case we've created a new raw_contact because the selected contact 809ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // is read-only, buildDiff() will create aggregation exceptions to join 810ac71b5305d49614f5560519509fa41ce9276a3f7Makoto Onuki // the new one to the existing contact. 81137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final ArrayList<ContentProviderOperation> diff = state.buildDiff(); 81237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan ContentProviderResult[] results = null; 81337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (!diff.isEmpty()) { 81437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan results = resolver.applyBatch(ContactsContract.AUTHORITY, diff); 81537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 81637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 81737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan result = (diff.size() > 0) ? RESULT_SUCCESS : RESULT_UNCHANGED; 81837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 81937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 82037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } catch (RemoteException e) { 82137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Something went wrong, bail without success 82237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Log.e(TAG, "Problem persisting user edits", e); 82337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 82437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 82537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } catch (OperationApplicationException e) { 82637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Version consistency failed, bail without success 82737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Log.e(TAG, "Version consistency failed", e); 82837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan break; 82937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 83037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 83137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 83237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan return result; 83337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 83437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 83537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** {@inheritDoc} */ 83637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan @Override 83737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan protected void onPostExecute(Integer result) { 83837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan final Context context = activityTarget; 83937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 840fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan dismissProgressDialog(); 84137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 84237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Show a toast message based on the success or failure of the save action. 84337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (result == RESULT_SUCCESS) { 84437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Toast.makeText(context, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 84537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else if (result == RESULT_FAILURE) { 84637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Toast.makeText(context, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 84737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 84837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 84937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan // Stop the service that was protecting us 85037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan context.stopService(new Intent(context, EmptyService.class)); 85137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan activityTarget.onSaveCompleted(result != RESULT_FAILURE); 85237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 85337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 85437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan 855fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan @Override 856fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan protected void onStop() { 857fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan super.onStop(); 858fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan // Dismiss the progress dialog here to prevent leaking the window on orientation change. 859fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan dismissProgressDialog(); 860fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan } 861fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan 862fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan /** 863fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan * Dismiss the progress dialog (check if it is null because it is a {@link WeakReference}). 864fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan */ 865fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan private static void dismissProgressDialog() { 866fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan ProgressDialog dialog = (sProgressDialog == null) ? null : sProgressDialog.get(); 867fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan if (dialog != null) { 868fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan dialog.dismiss(); 869fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan } 870fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan sProgressDialog = null; 871fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan } 872fcfc522887202cbda6e7681ae4ec8f5252f23bacKatherine Kuan 87337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan /** 87437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * This method is intended to be executed after the background task for saving edited info has 87537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * finished. The method sets the activity result (and intent if applicable) and finishes the 87637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * activity. 87737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan * @param success is true if the save task completed successfully, or false otherwise. 87837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan */ 87937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan private void onSaveCompleted(boolean success) { 88037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (success) { 88137bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan Intent intent = new Intent(Intent.ACTION_VIEW, mContactUri); 88237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setResult(RESULT_OK, intent); 88337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } else { 88437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan setResult(RESULT_CANCELED); 88537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 88637bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan finish(); 88737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 888e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng} 889