ContactEditorFragment.java revision 222744ea3cd7233677f0ef88804eb3e2db710e43
1cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann/* 2cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Copyright (C) 2010 Google Inc. 3cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * 4cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * you may not use this file except in compliance with the License. 6cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * You may obtain a copy of the License at 7cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * 8cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * 10cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Unless required by applicable law or agreed to in writing, software 11cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * See the License for the specific language governing permissions and 14cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * limitations under the License 15cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 16cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 17cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannpackage com.android.contacts.views.editor; 18cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 19f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.JoinContactActivity; 20cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport com.android.contacts.R; 21cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport com.android.contacts.model.ContactsSource; 22f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.Editor; 23f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityDelta; 24f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityModifier; 25ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmannimport com.android.contacts.model.EntityDeltaList; 26f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.GoogleSource; 27cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport com.android.contacts.model.Sources; 28f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.ContactsSource.EditType; 29f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.Editor.EditorListener; 30f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityDelta.ValuesDelta; 31f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.ui.ViewIdGenerator; 32f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.ui.widget.BaseContactEditorView; 33f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.ui.widget.PhotoEditorView; 34f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.util.EmptyService; 35f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.util.WeakAsyncTask; 36bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmannimport com.android.contacts.views.ContactLoader; 37f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 38f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.accounts.Account; 39cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity; 40cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.AlertDialog; 41cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Dialog; 42222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.Fragment; 43222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager; 44222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 45cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ActivityNotFoundException; 46f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.content.ContentProviderOperation; 47f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.content.ContentProviderResult; 48f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.content.ContentResolver; 49cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 50cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentValues; 51cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 52cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.DialogInterface; 53cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 54cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader; 55f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.content.OperationApplicationException; 56f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.content.ContentProviderOperation.Builder; 57f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.content.DialogInterface.OnDismissListener; 58f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor; 59f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 60f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.media.MediaScannerConnection; 61cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 62f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.os.AsyncTask; 63cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 64f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.os.Environment; 65f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.os.RemoteException; 669767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock; 67f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.provider.ContactsContract; 68f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.provider.MediaStore; 69f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.provider.ContactsContract.AggregationExceptions; 70cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.Contacts; 71cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.RawContacts; 72cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 73cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 74cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 75f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.view.ContextThemeWrapper; 76cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 77cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu; 78cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater; 79cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem; 80cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 81cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 82f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.widget.ArrayAdapter; 8380d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 84f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.widget.ListAdapter; 85f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.widget.TextView; 86cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast; 87cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 88f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.io.File; 89f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.text.SimpleDateFormat; 90cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport java.util.ArrayList; 91f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections; 92f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Comparator; 93f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Date; 94f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 95222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannpublic class ContactEditorFragment extends Fragment { 96cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 97cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private static final String TAG = "ContactEditorFragment"; 98cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 99f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int LOADER_DATA = 1; 100f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 101d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_URI = "uri"; 102d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_ACTION = "action"; 103f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_EDIT_STATE = "state"; 104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester"; 105f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator"; 106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CURRENT_PHOTO_FILE = "currentphotofile"; 107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_QUERY_SELECTION = "queryselection"; 108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_QUERY_SELECTION_ARGS = "queryselectionargs"; 109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin"; 110f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 111f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static final int SAVE_MODE_DEFAULT = 0; 112f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static final int SAVE_MODE_SPLIT = 1; 113f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static final int SAVE_MODE_JOIN = 2; 114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mRawContactIdRequestingPhoto = -1; 116cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 117f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private final EntityDeltaComparator mComparator = new EntityDeltaComparator(); 118f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 119f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String BUNDLE_SELECT_ACCOUNT_LIST = "account_list"; 120f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 121f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int ICON_SIZE = 96; 122f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 123f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final File PHOTO_DIR = new File( 124f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Environment.getExternalStorageDirectory() + "/DCIM/Camera"); 125f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 126f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private File mCurrentPhotoFile; 127cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 128cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Context mContext; 129f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mAction; 130f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Uri mUri; 131f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mMimeType; 132f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Bundle mIntentExtras; 133cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Listener mListener; 134cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 135f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mQuerySelection; 136f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String[] mQuerySelectionArgs; 137cc8bfc88f5c066b4e1b8d4a08eee52164decf24fDaniel Lehmann 138f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mContactIdForJoin; 139cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 140f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private LinearLayout mContent; 141ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann private EntityDeltaList mState; 142cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 143f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 144cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1459767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann private long mLoaderStartTime; 1469767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann 147cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 148cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 149cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 150cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 151cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public void onAttach(Activity activity) { 152cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann super.onAttach(activity); 153cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann mContext = activity; 154cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 155cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 156cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 157cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 158cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 159cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 160f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 161e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 1623648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 163cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 164cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 165cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 166cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 167222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 168222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onActivityCreated(Bundle savedInstanceState) { 169222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann super.onActivityCreated(savedInstanceState); 170222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 171222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann if (Intent.ACTION_EDIT.equals(mAction)) { 172222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann if (mListener != null) mListener.setTitleTo(R.string.editContact_title_edit); 173222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener); 174222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } else if (Intent.ACTION_INSERT.equals(mAction)) { 175222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann if (mListener != null) mListener.setTitleTo(R.string.editContact_title_insert); 176222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 177222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann doAddAction(); 178222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } else throw new IllegalArgumentException("Unknown Action String " + mAction + 179222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT); 180222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 181222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 182f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void load(String action, Uri uri, String mimeType, Bundle intentExtras) { 183f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mAction = action; 184f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mUri = uri; 185f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mMimeType = mimeType; 186f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mIntentExtras = intentExtras; 187f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 188f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 189f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void setListener(Listener value) { 190f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener = value; 191cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 192cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 193cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 194f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 195d364314c460152db7089b304beec81b3675893baDmitri Plotnikov if (savedState != null) { 196d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // Restore mUri before calling super.onCreate so that onInitializeLoaders 197d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // would already have a uri and an action to work with 198d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mUri = savedState.getParcelable(KEY_URI); 199d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mAction = savedState.getString(KEY_ACTION); 200d364314c460152db7089b304beec81b3675893baDmitri Plotnikov } 201d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 203f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 204f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (savedState == null) { 205f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If savedState is non-null, onRestoreInstanceState() will restore the generator. 206f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = new ViewIdGenerator(); 207f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 208f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Read modifications from instance 209ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = savedState.<EntityDeltaList> getParcelable(KEY_EDIT_STATE); 210f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactIdRequestingPhoto = savedState.getLong( 211f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 212f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR); 213f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String fileName = savedState.getString(KEY_CURRENT_PHOTO_FILE); 214f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (fileName != null) { 215f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mCurrentPhotoFile = new File(fileName); 216cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 217f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mQuerySelection = savedState.getString(KEY_QUERY_SELECTION); 218f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mQuerySelectionArgs = savedState.getStringArray(KEY_QUERY_SELECTION_ARGS); 219f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 220cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 221cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 222cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 223bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann public void setData(ContactLoader.Result data) { 224ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = EntityDeltaList.fromIterator(data.getEntities().iterator()); 225bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann // TODO: Merge in Intent parameters can only be done on the first load. 226bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann // The behaviour for subsequent loads is probably broken, so fix this 227bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann final boolean hasExtras = mIntentExtras != null && mIntentExtras.size() > 0; 228bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann final boolean hasState = mState.size() > 0; 229bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann if (hasExtras && hasState) { 230bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann // Find source defining the first RawContact found 231bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann // TODO: Test this. Can we actually always use the first RawContact. This seems wrong 232bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann final EntityDelta state = mState.get(0); 233bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann final String accountType = state.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 234bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann final Sources sources = Sources.getInstance(mContext); 235bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann final ContactsSource source = sources.getInflatedSource(accountType, 236bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann ContactsSource.LEVEL_CONSTRAINTS); 237bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann EntityModifier.parseExtras(mContext, source, state, mIntentExtras); 238bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 239f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 240f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 241cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 242f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void selectAccountAndCreateContact(ArrayList<Account> accounts, boolean isNewContact) { 243f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // No Accounts available. Create a phone-local contact. 244f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (accounts.isEmpty()) { 245f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann createContact(null, isNewContact); 246f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; // Don't show a dialog. 247f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 248cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 249f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // In the common case of a single account being writable, auto-select 250f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // it without showing a dialog. 251f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (accounts.size() == 1) { 252f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann createContact(accounts.get(0), isNewContact); 253f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; // Don't show a dialog. 254f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 255f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 256f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Bundle bundle = new Bundle(); 257f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bundle.putParcelableArrayList(BUNDLE_SELECT_ACCOUNT_LIST, accounts); 258f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_select_account, bundle); 259cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 260cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 261cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 262f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param account may be null to signal a device-local contact should 263f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * be created. 264f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param prefillFromIntent If this is set, the intent extras will be used to prefill the fields 265cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 266f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void createContact(Account account, boolean prefillFromIntent) { 267cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 268f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentValues values = new ContentValues(); 269f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (account != null) { 270f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.put(RawContacts.ACCOUNT_NAME, account.name); 271f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.put(RawContacts.ACCOUNT_TYPE, account.type); 272f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 273f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_NAME); 274f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_TYPE); 275cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 276cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 277f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Parse any values from incoming intent 278f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values)); 279f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContactsSource source = sources.getInflatedSource( 280f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann account != null ? account.type : null, 281f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContactsSource.LEVEL_CONSTRAINTS); 282f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityModifier.parseExtras(mContext, source, insert, 283f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann prefillFromIntent ? mIntentExtras : null); 284f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 285f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Ensure we have some default fields 286f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityModifier.ensureKindExists(insert, source, Phone.CONTENT_ITEM_TYPE); 287f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityModifier.ensureKindExists(insert, source, Email.CONTENT_ITEM_TYPE); 288f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 289f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mState == null) { 290f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Create state if none exists yet 291ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = EntityDeltaList.fromSingle(insert); 292f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 293f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add contact onto end of existing state 294f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mState.add(insert); 295cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 296f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 297f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 298cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 299cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 300f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void bindEditors() { 301f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 302f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 303cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 304f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 305f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 306cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 307f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 308f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 309f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 310f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int size = mState.size(); 311f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < size; i++) { 312f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 313f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final EntityDelta entity = mState.get(i); 314f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ValuesDelta values = entity.getValues(); 315f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!values.isVisible()) continue; 316f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 317f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 318f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContactsSource source = sources.getInflatedSource(accountType, 319f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContactsSource.LEVEL_CONSTRAINTS); 320f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long rawContactId = values.getAsLong(RawContacts._ID); 321f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 322f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final BaseContactEditorView editor; 323f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!source.readOnly) { 324f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann editor = (BaseContactEditorView) inflater.inflate(R.layout.item_contact_editor, 325f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent, false); 326f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 327f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann editor = (BaseContactEditorView) inflater.inflate( 328f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann R.layout.item_read_only_contact_editor, mContent, false); 329cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 330f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final PhotoEditorView photoEditor = editor.getPhotoEditor(); 331f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann photoEditor.setEditorListener(new PhotoListener(rawContactId, source.readOnly, 332f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann photoEditor)); 333cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 334f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 335f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann editor.setState(entity, source, mViewIdGenerator); 336cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 337f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 338f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 339f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 340cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 341cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 342b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 343eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 344f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann inflater.inflate(R.menu.edit, menu); 345cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 346cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 347b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 348eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onPrepareOptionsMenu(Menu menu) { 349f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann menu.findItem(R.id.menu_split).setVisible(mState != null && mState.size() > 1); 350cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 351cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 352b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 353cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public boolean onOptionsItemSelected(MenuItem item) { 354cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (item.getItemId()) { 355f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_done: 356f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSaveAction(SAVE_MODE_DEFAULT); 357f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_discard: 358f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doRevertAction(); 359f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_add: 360f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doAddAction(); 361f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_delete: 362f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doDeleteAction(); 363f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_split: 364f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSplitContactAction(); 365f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_join: 366f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doJoinContactAction(); 367f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 368f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 369f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 370cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 371f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doAddAction() { 372f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Load Accounts async so that we can present them 373f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann AsyncTask<Void, Void, ArrayList<Account>> loadAccountsTask = 374f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new AsyncTask<Void, Void, ArrayList<Account>>() { 375f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 376f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected ArrayList<Account> doInBackground(Void... params) { 377f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return Sources.getInstance(mContext).getAccounts(true); 378f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 379f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 380f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void onPostExecute(ArrayList<Account> result) { 381f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann selectAccountAndCreateContact(result, true); 382f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 383f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }; 384f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann loadAccountsTask.execute(); 385cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 386f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 387f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 388cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 389f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 390f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Delete the entire contact currently being edited, which usually asks for 391f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * user confirmation before continuing. 392f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 393f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doDeleteAction() { 394f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) 395f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 396f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int readOnlySourcesCnt = 0; 397f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int writableSourcesCnt = 0; 398f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: This shouldn't be called from the UI thread 399f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 400f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (EntityDelta delta : mState) { 401f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String accountType = delta.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 402f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContactsSource contactsSource = sources.getInflatedSource(accountType, 403f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContactsSource.LEVEL_CONSTRAINTS); 404f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (contactsSource != null && contactsSource.readOnly) { 405f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann readOnlySourcesCnt += 1; 406f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 407f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann writableSourcesCnt += 1; 408cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 409cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 410cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 411f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (readOnlySourcesCnt > 0 && writableSourcesCnt > 0) { 412f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_confirm_readonly_delete); 413f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (readOnlySourcesCnt > 0 && writableSourcesCnt == 0) { 414f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_confirm_readonly_hide); 415f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (readOnlySourcesCnt == 0 && writableSourcesCnt > 1) { 416f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_confirm_multiple_delete); 417cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } else { 418f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_confirm_delete); 419cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 420f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 421f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 422f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 423f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 424f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Pick a specific photo to be added under the currently selected tab. 425f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 426f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /* package */ boolean doPickPhotoAction(long rawContactId) { 427f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 428f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 429f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactIdRequestingPhoto = rawContactId; 430f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 431f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_pick_photo); 432f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 433f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 434cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 435cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public Dialog onCreateDialog(int id, Bundle bundle) { 436cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (id) { 437f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_confirm_delete: 438cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return new AlertDialog.Builder(mContext) 439cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setTitle(R.string.deleteConfirmation_title) 440cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setIcon(android.R.drawable.ic_dialog_alert) 441cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setMessage(R.string.deleteConfirmation) 442cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setNegativeButton(android.R.string.cancel, null) 443f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann .setPositiveButton(android.R.string.ok, new DeleteClickListener()) 444cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setCancelable(false) 445cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .create(); 446f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_confirm_readonly_delete: 447cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return new AlertDialog.Builder(mContext) 448cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setTitle(R.string.deleteConfirmation_title) 449cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setIcon(android.R.drawable.ic_dialog_alert) 450cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setMessage(R.string.readOnlyContactDeleteConfirmation) 451cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setNegativeButton(android.R.string.cancel, null) 452f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann .setPositiveButton(android.R.string.ok, new DeleteClickListener()) 453cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setCancelable(false) 454cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .create(); 455f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_confirm_multiple_delete: 456cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return new AlertDialog.Builder(mContext) 457cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setTitle(R.string.deleteConfirmation_title) 458cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setIcon(android.R.drawable.ic_dialog_alert) 459cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setMessage(R.string.multipleContactDeleteConfirmation) 460cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setNegativeButton(android.R.string.cancel, null) 461f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann .setPositiveButton(android.R.string.ok, new DeleteClickListener()) 462cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setCancelable(false) 463cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .create(); 464f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_confirm_readonly_hide: 465cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return new AlertDialog.Builder(mContext) 466cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setTitle(R.string.deleteConfirmation_title) 467cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setIcon(android.R.drawable.ic_dialog_alert) 468cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .setMessage(R.string.readOnlyContactWarning) 469f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann .setPositiveButton(android.R.string.ok, new DeleteClickListener()) 470f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann .setCancelable(false) 471cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann .create(); 472f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_pick_photo: 473f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return createPickPhotoDialog(); 474f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_split: 475f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return createSplitDialog(); 476f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_dialog_select_account: 477f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return createSelectAccountDialog(bundle); 478f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann default: 479f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return null; 480f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 481f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 482f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 483f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Dialog createSelectAccountDialog(Bundle bundle) { 484f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ArrayList<Account> accounts = bundle.getParcelableArrayList( 485f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann BUNDLE_SELECT_ACCOUNT_LIST); 486f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Wrap our context to inflate list items using correct theme 487f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Context dialogContext = new ContextThemeWrapper(mContext, 488f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann android.R.style.Theme_Light); 489f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater dialogInflater = 490f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann (LayoutInflater)dialogContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 491f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 492f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 493f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 494f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ArrayAdapter<Account> accountAdapter = new ArrayAdapter<Account>(mContext, 495f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann android.R.layout.simple_list_item_2, accounts) { 496f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 497f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public View getView(int position, View convertView, ViewGroup parent) { 498f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (convertView == null) { 499f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann convertView = dialogInflater.inflate(android.R.layout.simple_list_item_2, 500f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann parent, false); 501f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 502f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 503f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: show icon along with title 504f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final TextView text1 = (TextView)convertView.findViewById(android.R.id.text1); 505f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final TextView text2 = (TextView)convertView.findViewById(android.R.id.text2); 506f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 507f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Account account = this.getItem(position); 508f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContactsSource source = sources.getInflatedSource(account.type, 509f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContactsSource.LEVEL_SUMMARY); 510f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 511f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann text1.setText(account.name); 512f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann text2.setText(source.getDisplayLabel(mContext)); 513f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 514f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return convertView; 515f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 516f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }; 517f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 518f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final DialogInterface.OnClickListener clickListener = 519f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new DialogInterface.OnClickListener() { 520f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 521f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann dialog.dismiss(); 522f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 523f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Create new contact based on selected source 524f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Account account = accountAdapter.getItem(which); 525f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann createContact(account, false); 526cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 527f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }; 528f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 529f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final DialogInterface.OnCancelListener cancelListener = 530f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new DialogInterface.OnCancelListener() { 531f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCancel(DialogInterface dialog) { 532f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If nothing remains, close activity 533f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) { 534f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener.closeBecauseAccountSelectorAborted(); 535cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 536cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 537f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }; 538f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 539f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 540f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setTitle(R.string.dialog_new_contact_account); 541f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setSingleChoiceItems(accountAdapter, 0, clickListener); 542f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setOnCancelListener(cancelListener); 543f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Dialog result = builder.create(); 544f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann result.setOnDismissListener(new OnDismissListener() { 545f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onDismiss(DialogInterface dialog) { 546f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: Check if we even need this...seems useless 547f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann //removeDialog(DIALOG_SELECT_ACCOUNT); 548f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 549f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }); 550f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return result; 551f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 552f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 553f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSplitContactAction() { 554f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 555f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 556f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().showDialog(R.id.edit_dialog_split); 557f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 558f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 559f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 560f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Dialog createSplitDialog() { 561f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 562f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setTitle(R.string.splitConfirmation_title); 563f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setIcon(android.R.drawable.ic_dialog_alert); 564f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setMessage(R.string.splitConfirmation); 565f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 566f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 567f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Split the contacts 568f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mState.splitRawContacts(); 569f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doSaveAction(SAVE_MODE_SPLIT); 570f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 571f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }); 572f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setNegativeButton(android.R.string.cancel, null); 573f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setCancelable(false); 574f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return builder.create(); 575f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 576f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 577f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doJoinContactAction() { 578f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSaveAction(SAVE_MODE_JOIN); 579f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 580f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 581f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 582f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Creates a dialog offering two options: take a photo or pick a photo from the gallery. 583f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 584f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Dialog createPickPhotoDialog() { 585f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Wrap our context to inflate list items using correct theme 586f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Context dialogContext = new ContextThemeWrapper(mContext, 587f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann android.R.style.Theme_Light); 588f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 589f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String[] choices = new String[2]; 590f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices[0] = mContext.getString(R.string.take_photo); 591f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices[1] = mContext.getString(R.string.pick_photo); 592f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ListAdapter adapter = new ArrayAdapter<String>(dialogContext, 593f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann android.R.layout.simple_list_item_1, choices); 594f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 595f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final AlertDialog.Builder builder = new AlertDialog.Builder(dialogContext); 596f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setTitle(R.string.attachToContact); 597f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() { 598f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 599f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann dialog.dismiss(); 600f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch(which) { 601f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case 0: 602f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doTakePhoto(); 603f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 604f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case 1: 605f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doPickPhotoFromGallery(); 606f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 607f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 608f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 609f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }); 610f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return builder.create(); 611f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 612f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 613f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 614f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 615f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Launches Gallery to pick a photo. 616f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 617f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void doPickPhotoFromGallery() { 618f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 619f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Launch picker to choose photo for selected contact 620f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = getPhotoPickIntent(); 621f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().startActivityForResult(intent, 622f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann R.id.edit_request_code_photo_picked_with_data); 623f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (ActivityNotFoundException e) { 624f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show(); 625cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 626cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 627cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 628f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 629f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for picking a photo from Gallery, cropping it and returning the bitmap. 630f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 631f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getPhotoPickIntent() { 632f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); 633f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setType("image/*"); 634f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("crop", "true"); 635f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectX", 1); 636f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectY", 1); 637f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputX", ICON_SIZE); 638f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputY", ICON_SIZE); 639f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("return-data", true); 640f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 641f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 642f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 643f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 644f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Check if our internal {@link #mState} is valid, usually checked before 645f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * performing user actions. 646f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 647f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean hasValidState() { 648f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return mState != null && mState.size() > 0; 649f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 650f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 651f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 652f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Create a file name for the icon photo using current time. 653f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 654f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String getPhotoFileName() { 655f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Date date = new Date(System.currentTimeMillis()); 656f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("'IMG'_yyyyMMdd_HHmmss"); 657f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return dateFormat.format(date) + ".jpg"; 658f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 659f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 660f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 661f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Launches Camera to take a picture and store it in a file. 662f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 663f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void doTakePhoto() { 664f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 665f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Launch camera to take photo for selected contact 666f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann PHOTO_DIR.mkdirs(); 667f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mCurrentPhotoFile = new File(PHOTO_DIR, getPhotoFileName()); 668f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = getTakePickIntent(mCurrentPhotoFile); 669f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 670f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().startActivityForResult(intent, R.id.edit_request_code_camera_with_data); 671f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (ActivityNotFoundException e) { 672f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show(); 673f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 674f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 675f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 676f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 677f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for capturing a photo and storing it in a temporary file. 678f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 679f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getTakePickIntent(File f) { 680f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, null); 681f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); 682f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 683f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 684f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 685f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 686f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Sends a newly acquired photo to Gallery for cropping 687f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 688f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void doCropPhoto(File f) { 689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 690f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add the image to the media store 691f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann MediaScannerConnection.scanFile( 692f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext, 693f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[] { f.getAbsolutePath() }, 694f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[] { null }, 695f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann null); 696f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 697f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Launch gallery to crop the photo 698f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = getCropImageIntent(Uri.fromFile(f)); 699f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().startActivityForResult(intent, 700f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann R.id.edit_request_code_photo_picked_with_data); 701f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (Exception e) { 702f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.e(TAG, "Cannot crop image", e); 703f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show(); 704cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 705cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 706cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 707f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 708f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for image cropping. 709f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 710f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getCropImageIntent(Uri photoUri) { 711f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent("com.android.camera.action.CROP"); 712f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setDataAndType(photoUri, "image/*"); 713f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("crop", "true"); 714f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectX", 1); 715f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectY", 1); 716f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputX", ICON_SIZE); 717f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputY", ICON_SIZE); 718f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("return-data", true); 719f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 720f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 721f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 722f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 723f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Saves or creates the contact based on the mode, and if successful 724f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * finishes the activity. 725f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 726f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSaveAction(int saveMode) { 727f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) { 728f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 729f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 730f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 731f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: Status still needed? 732f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann //mStatus = STATUS_SAVING; 733f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final PersistTask task = new PersistTask(this, saveMode); 734f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann task.execute(mState); 735f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 736f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 737f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 738f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 739ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann /** 740ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann * Asynchonously saves the changes made by the user. This can be called even if nothing 741ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann * has changed 742ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann */ 743ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann public void save() { 744ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann doSaveAction(SAVE_MODE_DEFAULT); 745ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann } 746ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann 747f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doRevertAction() { 748f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mListener != null) mListener.closeAfterRevert(); 749f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 750f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 751f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 752f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 753f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void onSaveCompleted(boolean success, int saveMode, Uri contactLookupUri) { 754f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 755f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case SAVE_MODE_DEFAULT: 756f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 757f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final int resultCode; 758f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (success && contactLookupUri != null) { 759f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String requestAuthority = mUri == null ? null : mUri.getAuthority(); 760f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 761f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String legacyAuthority = "contacts"; 762f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 763f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = new Intent(); 764f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (legacyAuthority.equals(requestAuthority)) { 765f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Build legacy Uri when requested by caller 766f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(Contacts.lookupContact( 767f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.getContentResolver(), contactLookupUri)); 768f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyContentUri = Uri.parse("content://contacts/people"); 769f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyUri = ContentUris.withAppendedId( 770f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann legacyContentUri, contactId); 771f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(legacyUri); 772f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 773f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Otherwise pass back a lookup-style Uri 774f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(contactLookupUri); 775f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 776f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 777f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultCode = Activity.RESULT_OK; 778f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 779f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultCode = Activity.RESULT_CANCELED; 780f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 781f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 782f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mListener != null) mListener.closeAfterSaving(resultCode, resultIntent); 783f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 784f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case SAVE_MODE_SPLIT: 785f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mListener != null) mListener.closeAfterSplit(); 786f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 787f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 788f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case SAVE_MODE_JOIN: 789f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann //mStatus = STATUS_EDITING; 790f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (success) { 791f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann showJoinAggregateActivity(contactLookupUri); 792f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 793f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 794f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 795f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 796f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 797f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 798f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 799f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 800f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 801f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 802f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 803f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (contactLookupUri == null) { 804f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 805f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 806f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 807f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 808f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = new Intent(JoinContactActivity.JOIN_CONTACT); 809f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(JoinContactActivity.EXTRA_TARGET_CONTACT_ID, mContactIdForJoin); 810f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann getActivity().startActivityForResult(intent, R.id.edit_request_code_join); 811f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 812f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 813f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private interface JoinContactQuery { 814f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String[] PROJECTION = { 815f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann RawContacts._ID, 816f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann RawContacts.CONTACT_ID, 817f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann RawContacts.NAME_VERIFIED, 818f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann }; 819f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 820f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String SELECTION = RawContacts.CONTACT_ID + "=? OR " + RawContacts.CONTACT_ID + "=?"; 821f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 822f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int _ID = 0; 823f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int CONTACT_ID = 1; 824f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int NAME_VERIFIED = 2; 825f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 826f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 827f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 828f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 829f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 830f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 831f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentResolver resolver = mContext.getContentResolver(); 832f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 833f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Load raw contact IDs for all raw contacts involved - currently edited and selected 834f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // in the join UIs 835f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Cursor c = resolver.query(RawContacts.CONTENT_URI, 836f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann JoinContactQuery.PROJECTION, 837f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann JoinContactQuery.SELECTION, 838f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[]{String.valueOf(contactId), String.valueOf(mContactIdForJoin)}, null); 839f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 840f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann long rawContactIds[]; 841f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann long verifiedNameRawContactId = -1; 842f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 843f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann rawContactIds = new long[c.getCount()]; 844f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < rawContactIds.length; i++) { 845f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann c.moveToNext(); 846f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann long rawContactId = c.getLong(JoinContactQuery._ID); 847f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann rawContactIds[i] = rawContactId; 848f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (c.getLong(JoinContactQuery.CONTACT_ID) == mContactIdForJoin) { 849f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (verifiedNameRawContactId == -1 850f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann || c.getInt(JoinContactQuery.NAME_VERIFIED) != 0) { 851f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann verifiedNameRawContactId = rawContactId; 852f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 853f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 854b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann } 855f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } finally { 856f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann c.close(); 857cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 858f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 859f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // For each pair of raw contacts, insert an aggregation exception 860f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); 861f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < rawContactIds.length; i++) { 862f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int j = 0; j < rawContactIds.length; j++) { 863f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (i != j) { 864f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann buildJoinContactDiff(operations, rawContactIds[i], rawContactIds[j]); 865f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 866f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 867cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 868f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 869f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Mark the original contact as "name verified" to make sure that the contact 870f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // display name does not change as a result of the join 871f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Builder builder = ContentProviderOperation.newUpdate( 872f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContentUris.withAppendedId(RawContacts.CONTENT_URI, verifiedNameRawContactId)); 873f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.withValue(RawContacts.NAME_VERIFIED, 1); 874f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann operations.add(builder.build()); 875f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 876f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Apply all aggregation exceptions as one batch 877f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 878f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resolver.applyBatch(ContactsContract.AUTHORITY, operations); 879f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 880f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // We can use any of the constituent raw contacts to refresh the UI - why not the first 881f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = new Intent(); 882f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setData(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactIds[0])); 883f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 884f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Reload the new state from database 885f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: Reload necessary or do we have a listener? 886f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann //new QueryEntitiesTask(this).execute(intent); 887f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 888f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.contactsJoinedMessage, Toast.LENGTH_LONG).show(); 889f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (RemoteException e) { 890f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.e(TAG, "Failed to apply aggregation exception batch", e); 891f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 892f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (OperationApplicationException e) { 893f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.e(TAG, "Failed to apply aggregation exception batch", e); 894f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 895cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 896f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 897f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 898f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 899f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Construct a {@link AggregationExceptions#TYPE_KEEP_TOGETHER} ContentProviderOperation. 900f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 901f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void buildJoinContactDiff(ArrayList<ContentProviderOperation> operations, 902f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann long rawContactId1, long rawContactId2) { 903f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Builder builder = 904f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI); 905f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER); 906f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 907f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 908f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann operations.add(builder.build()); 909f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 910cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 911cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public static interface Listener { 912cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 913cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Contact was not found, so somehow close this fragment. 914cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 915f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void closeBecauseContactNotFound(); 916f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 917f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 918f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Contact was split, so we can close now 919f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 920f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void closeAfterSplit(); 921f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 922f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 923f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User was presented with an account selection and couldn't decide. 924f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 925f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void closeBecauseAccountSelectorAborted(); 926f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 927f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 928f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User has tapped Revert, close the fragment now. 929f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 930f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void closeAfterRevert(); 931cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 932cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 933f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User has removed the contact, close the fragment now. 934cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 935f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void closeAfterDelete(); 936f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 937f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 938f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Set the Title (e.g. of the Activity) 939f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 940f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void setTitleTo(int resourceId); 941f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 942f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 943f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Contact was 944f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param resultCode 945f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param resultIntent 946f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 947f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void closeAfterSaving(int resultCode, Intent resultIntent); 948f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 949f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 950f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private class EntityDeltaComparator implements Comparator<EntityDelta> { 951f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 952f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Compare EntityDeltas for sorting the stack of editors. 953f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 954f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public int compare(EntityDelta one, EntityDelta two) { 955f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check direct equality 956f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (one.equals(two)) { 957f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 0; 958f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 959f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 960f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 961f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String accountType = one.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 962f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContactsSource oneSource = sources.getInflatedSource(accountType, 963f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContactsSource.LEVEL_SUMMARY); 964f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann accountType = two.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 965f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContactsSource twoSource = sources.getInflatedSource(accountType, 966f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContactsSource.LEVEL_SUMMARY); 967f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 968f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check read-only 969f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneSource.readOnly && !twoSource.readOnly) { 970f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 971f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoSource.readOnly && !oneSource.readOnly) { 972f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 973f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 974f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 975f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account type 976f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean skipAccountTypeCheck = false; 977f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean oneIsGoogle = oneSource instanceof GoogleSource; 978f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean twoIsGoogle = twoSource instanceof GoogleSource; 979f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneIsGoogle && !twoIsGoogle) { 980f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 981f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoIsGoogle && !oneIsGoogle) { 982f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 983f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (oneIsGoogle && twoIsGoogle){ 984f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann skipAccountTypeCheck = true; 985f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 986f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 987f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int value; 988f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!skipAccountTypeCheck) { 9892776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru if (oneSource.accountType == null) { 9902776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru return 1; 9912776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru } 992f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann value = oneSource.accountType.compareTo(twoSource.accountType); 993f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 994f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 995f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 996f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 997f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 998f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account name 999f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta oneValues = one.getValues(); 1000f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String oneAccount = oneValues.getAsString(RawContacts.ACCOUNT_NAME); 1001f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneAccount == null) oneAccount = ""; 1002f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta twoValues = two.getValues(); 1003f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String twoAccount = twoValues.getAsString(RawContacts.ACCOUNT_NAME); 1004f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (twoAccount == null) twoAccount = ""; 1005f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann value = oneAccount.compareTo(twoAccount); 1006f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1007f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 1008f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1009f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1010f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Both are in the same account, fall back to contact ID 1011f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long oneId = oneValues.getAsLong(RawContacts._ID); 1012f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long twoId = twoValues.getAsLong(RawContacts._ID); 1013f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneId == null) { 1014f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1015f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoId == null) { 1016f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1017f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1018f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1019f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return (int)(oneId - twoId); 1020f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1021f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1022f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1023f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1024f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Class that listens to requests coming from photo editors 1025f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1026f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private class PhotoListener implements EditorListener, DialogInterface.OnClickListener { 1027f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mRawContactId; 1028f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean mReadOnly; 1029f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private PhotoEditorView mEditor; 1030f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1031f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public PhotoListener(long rawContactId, boolean readOnly, PhotoEditorView editor) { 1032f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactId = rawContactId; 1033f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mReadOnly = readOnly; 1034f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mEditor = editor; 1035f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1036f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1037f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onDeleted(Editor editor) { 1038f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Do nothing 1039f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1040f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1041f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onRequest(int request) { 1042f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return; 1043f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1044f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (request == EditorListener.REQUEST_PICK_PHOTO) { 1045f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mEditor.hasSetPhoto()) { 1046f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // There is an existing photo, offer to remove, replace, or promoto to primary 1047f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann createPhotoDialog().show(); 1048f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (!mReadOnly) { 1049f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // No photo set and not read-only, try to set the photo 1050f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doPickPhotoAction(mRawContactId); 1051f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1052f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1053f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1054cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1055cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 1056f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Prepare dialog for picking a new {@link EditType} or entering a 1057f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * custom label. This dialog is limited to the valid types as determined 1058f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * by {@link EntityModifier}. 1059cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 1060f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public Dialog createPhotoDialog() { 1061f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Wrap our context to inflate list items using correct theme 1062f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Context dialogContext = new ContextThemeWrapper(mContext, 1063f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann android.R.style.Theme_Light); 1064f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1065f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String[] choices; 1066f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mReadOnly) { 1067f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices = new String[1]; 1068f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices[0] = mContext.getString(R.string.use_photo_as_primary); 1069f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1070f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices = new String[3]; 1071f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices[0] = mContext.getString(R.string.use_photo_as_primary); 1072f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices[1] = mContext.getString(R.string.removePicture); 1073f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann choices[2] = mContext.getString(R.string.changePicture); 1074f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1075f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ListAdapter adapter = new ArrayAdapter<String>(dialogContext, 1076f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann android.R.layout.simple_list_item_1, choices); 1077f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1078f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final AlertDialog.Builder builder = new AlertDialog.Builder(dialogContext); 1079f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setTitle(R.string.attachToContact); 1080f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann builder.setSingleChoiceItems(adapter, -1, this); 1081f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return builder.create(); 1082f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1083cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1084cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 1085f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Called when something in the dialog is clicked 1086cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 1087f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 1088f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann dialog.dismiss(); 1089f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1090f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (which) { 1091f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case 0: 1092f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Set the photo as super primary 1093f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mEditor.setSuperPrimary(true); 1094f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1095f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // And set all other photos as not super primary 1096f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int count = mContent.getChildCount(); 1097f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < count; i++) { 1098f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann View childView = mContent.getChildAt(i); 1099f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (childView instanceof BaseContactEditorView) { 1100f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann BaseContactEditorView editor = (BaseContactEditorView) childView; 1101f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann PhotoEditorView photoEditor = editor.getPhotoEditor(); 1102f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!photoEditor.equals(mEditor)) { 1103f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann photoEditor.setSuperPrimary(false); 1104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1105f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case 1: 1110f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove the photo 1111f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mEditor.setPhotoBitmap(null); 1112f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1113f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case 2: 1115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Pick a new photo for the contact 1116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doPickPhotoAction(mRawContactId); 1117f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1118f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1119f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1120f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1121f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1122f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1123f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private class DeleteClickListener implements DialogInterface.OnClickListener { 1124f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 1125f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: Don't do this from the UI thread 1126f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 1127f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Mark all raw contacts for deletion 1128f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (EntityDelta delta : mState) { 1129f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann delta.markDeleted(); 1130f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1131f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Save the deletes 1132f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doSaveAction(SAVE_MODE_DEFAULT); 1133f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener.closeAfterDelete(); 1134f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1135f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1136f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1137f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: There has to be a nicer way than this WeakAsyncTask...? Maybe call a service? 1138f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1139f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Background task for persisting edited contact data, using the changes 1140f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * defined by a set of {@link EntityDelta}. This task starts 1141f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * {@link EmptyService} to make sure the background thread can finish 1142f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * persisting in cases where the system wants to reclaim our process. 1143f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1144f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static class PersistTask extends 1145ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann WeakAsyncTask<EntityDeltaList, Void, Integer, ContactEditorFragment> { 1146f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int PERSIST_TRIES = 3; 1147f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1148f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int RESULT_UNCHANGED = 0; 1149f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int RESULT_SUCCESS = 1; 1150f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int RESULT_FAILURE = 2; 1151f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1152f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private final Context mContext; 1153f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1154f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private int mSaveMode; 1155f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Uri mContactLookupUri = null; 1156f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1157f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public PersistTask(ContactEditorFragment target, int saveMode) { 1158f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super(target); 1159f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mSaveMode = saveMode; 1160f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext = target.mContext; 1161f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1162f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1163f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** {@inheritDoc} */ 1164f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1165f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void onPreExecute(ContactEditorFragment target) { 1166f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Before starting this task, start an empty service to protect our 1167f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // process from being reclaimed by the system. 1168f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.startService(new Intent(mContext, EmptyService.class)); 1169f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1170f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1171f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** {@inheritDoc} */ 1172f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1173ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann protected Integer doInBackground(ContactEditorFragment target, EntityDeltaList... params) { 1174f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentResolver resolver = mContext.getContentResolver(); 1175f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1176ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann EntityDeltaList state = params[0]; 1177f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1178f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Trim any empty fields, and RawContacts, before persisting 1179f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Sources sources = Sources.getInstance(mContext); 1180f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityModifier.trimEmpty(state, sources); 1181f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1182f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Attempt to persist changes 1183f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int tries = 0; 1184f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Integer result = RESULT_FAILURE; 1185f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann while (tries++ < PERSIST_TRIES) { 1186f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 1187f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Build operations and try applying 1188f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ArrayList<ContentProviderOperation> diff = state.buildDiff(); 1189f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContentProviderResult[] results = null; 1190f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!diff.isEmpty()) { 1191f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann results = resolver.applyBatch(ContactsContract.AUTHORITY, diff); 1192f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1193f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1194f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long rawContactId = getRawContactId(state, diff, results); 1195f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (rawContactId != -1) { 1196f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri rawContactUri = ContentUris.withAppendedId( 1197f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann RawContacts.CONTENT_URI, rawContactId); 1198f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1199f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // convert the raw contact URI to a contact URI 1200f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactLookupUri = RawContacts.getContactLookupUri(resolver, 1201f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann rawContactUri); 1202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1203f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann result = (diff.size() > 0) ? RESULT_SUCCESS : RESULT_UNCHANGED; 1204f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1205f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1206f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (RemoteException e) { 1207f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Something went wrong, bail without success 1208f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.e(TAG, "Problem persisting user edits", e); 1209f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1210f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1211f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (OperationApplicationException e) { 1212f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Version consistency failed, re-parent change and try again 1213f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.w(TAG, "Version consistency failed, re-parenting: " + e.toString()); 1214ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann final EntityDeltaList newState = EntityDeltaList.fromQuery(resolver, 1215f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann target.mQuerySelection, target.mQuerySelectionArgs, null); 1216ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann state = EntityDeltaList.mergeAfter(newState, state); 1217f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1218f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1219f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1220f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return result; 1221f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1222f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1223ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann private long getRawContactId(EntityDeltaList state, 1224f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ArrayList<ContentProviderOperation> diff, 1225f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentProviderResult[] results) { 1226f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann long rawContactId = state.findRawContactId(); 1227f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (rawContactId != -1) { 1228f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return rawContactId; 1229f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1230f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1231f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // we gotta do some searching for the id 1232f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final int diffSize = diff.size(); 1233f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < diffSize; i++) { 1234f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ContentProviderOperation operation = diff.get(i); 1235f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (operation.getType() == ContentProviderOperation.TYPE_INSERT 1236f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann && operation.getUri().getEncodedPath().contains( 1237f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann RawContacts.CONTENT_URI.getEncodedPath())) { 1238f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return ContentUris.parseId(results[i].uri); 1239f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1240f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1241f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1242f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1243f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1244f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** {@inheritDoc} */ 1245f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1246f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void onPostExecute(ContactEditorFragment target, Integer result) { 1247f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (result == RESULT_SUCCESS && mSaveMode != SAVE_MODE_JOIN) { 1248f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 1249f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (result == RESULT_FAILURE) { 1250f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 1251f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1252f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1253f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Stop the service that was protecting us 1254f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.stopService(new Intent(mContext, EmptyService.class)); 1255f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1256f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann target.onSaveCompleted(result != RESULT_FAILURE, mSaveMode, mContactLookupUri); 1257f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1258f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1259f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1260f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1261f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 1262d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putParcelable(KEY_URI, mUri); 1263d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putString(KEY_ACTION, mAction); 1264d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 1265f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (hasValidState()) { 1266f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Store entities with modifications 1267f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_EDIT_STATE, mState); 1268f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1269f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1270f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 1271f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator); 1272f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mCurrentPhotoFile != null) { 1273f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putString(KEY_CURRENT_PHOTO_FILE, mCurrentPhotoFile.toString()); 1274f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1275f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putString(KEY_QUERY_SELECTION, mQuerySelection); 1276f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putStringArray(KEY_QUERY_SELECTION_ARGS, mQuerySelectionArgs); 1277f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 1278f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 1279f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1280f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1281d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 1282f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 1283f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Ignore failed requests 1284f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (resultCode != Activity.RESULT_OK) return; 1285f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (requestCode) { 1286f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_request_code_photo_picked_with_data: { 1287f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann BaseContactEditorView requestingEditor = null; 1288f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 1289f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann View childView = mContent.getChildAt(i); 1290f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (childView instanceof BaseContactEditorView) { 1291f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann BaseContactEditorView editor = (BaseContactEditorView) childView; 1292f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (editor.getRawContactId() == mRawContactIdRequestingPhoto) { 1293f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann requestingEditor = editor; 1294f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1295f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1296f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1297f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1298f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1299f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (requestingEditor != null) { 1300f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Bitmap photo = data.getParcelableExtra("data"); 1301f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann requestingEditor.setPhotoBitmap(photo); 1302f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactIdRequestingPhoto = -1; 1303f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1304f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // The contact that requested the photo is no longer present. 1305f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO: Show error message 1306f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1307f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1308f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1309f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1310f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1311f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_request_code_camera_with_data: { 1312f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doCropPhoto(mCurrentPhotoFile); 1313f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1314f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1315f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.edit_request_code_join: { 1316f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 1317f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 1318f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 1319f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1320f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1321f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1322cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 13239cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 13249cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov public Uri getUri() { 13259cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov return mUri; 13269cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1327222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1328222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann /** 1329222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann * The listener for the data loader 1330222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann */ 1331222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener = 1332222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann new LoaderCallbacks<ContactLoader.Result>() { 1333222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1334222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) { 1335222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann mLoaderStartTime = SystemClock.elapsedRealtime(); 1336222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return new ContactLoader(mContext, mUri); 1337222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1338222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1339222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1340222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) { 1341222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long loaderCurrentTime = SystemClock.elapsedRealtime(); 1342222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime)); 1343222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann if (data == ContactLoader.Result.NOT_FOUND) { 1344222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann // Item has been deleted 1345222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.i(TAG, "No contact found. Closing activity"); 1346222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann if (mListener != null) mListener.closeBecauseContactNotFound(); 1347222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return; 1348222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1349222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1350222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataStartTime = SystemClock.elapsedRealtime(); 1351222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann setData(data); 1352222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataEndTime = SystemClock.elapsedRealtime(); 1353222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime)); 1354222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1355222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann }; 13562ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1357