ContactEditorBaseActivity.java revision c90cc15b804fb00339a3b98e5c951549f9b03599
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.contacts.activities; 18 19import com.android.contacts.ContactSaveService; 20import com.android.contacts.ContactsActivity; 21import com.android.contacts.R; 22import com.android.contacts.common.model.AccountTypeManager; 23import com.android.contacts.common.model.account.AccountType; 24import com.android.contacts.common.model.account.AccountWithDataSet; 25import com.android.contacts.common.util.ImplicitIntentsUtil; 26import com.android.contacts.editor.ContactEditorBaseFragment; 27import com.android.contacts.editor.ContactEditorFragment; 28import com.android.contacts.editor.EditorIntents; 29import com.android.contacts.interactions.ContactDeletionInteraction; 30import com.android.contacts.util.DialogManager; 31 32import android.app.ActionBar; 33import android.app.Dialog; 34import android.content.ContentValues; 35import android.content.Intent; 36import android.net.Uri; 37import android.os.Bundle; 38import android.provider.ContactsContract.Contacts; 39import android.provider.ContactsContract.RawContacts; 40import android.util.Log; 41import android.view.View; 42import android.view.inputmethod.InputMethodManager; 43 44import java.util.ArrayList; 45 46/** 47 * Base Activity for contact editors. 48 */ 49abstract public class ContactEditorBaseActivity extends ContactsActivity 50 implements DialogManager.DialogShowingViewActivity { 51 protected static final String TAG = "ContactEditorActivity"; 52 53 /** 54 * Intent action to edit a contact with all available field inputs displayed. 55 * 56 * Only used to open the "fully expanded" editor -- {@link ContactEditorActivity}. 57 */ 58 public static final String ACTION_EDIT = "com.android.contacts.action.FULL_EDIT"; 59 60 /** 61 * Intent action to insert a new contact with all available field inputs displayed. 62 * 63 * Only used to open the "fully expanded" editor -- {@link ContactEditorActivity}. 64 */ 65 public static final String ACTION_INSERT = "com.android.contacts.action.FULL_INSERT"; 66 67 public static final String ACTION_JOIN_COMPLETED = "joinCompleted"; 68 public static final String ACTION_SAVE_COMPLETED = "saveCompleted"; 69 70 /** 71 * Contract for contact editors Fragments that are managed by this Activity. 72 */ 73 public interface ContactEditor { 74 75 /** 76 * Modes that specify what the AsyncTask has to perform after saving 77 */ 78 public interface SaveMode { 79 /** 80 * Close the editor after saving 81 */ 82 public static final int CLOSE = 0; 83 84 /** 85 * Reload the data so that the user can continue editing 86 */ 87 public static final int RELOAD = 1; 88 89 /** 90 * Split the contact after saving 91 */ 92 public static final int SPLIT = 2; 93 94 /** 95 * Join another contact after saving 96 */ 97 public static final int JOIN = 3; 98 99 /** 100 * Navigate to the compact editor view after saving. 101 */ 102 public static final int COMPACT = 4; 103 } 104 105 /** 106 * The status of the contact editor. 107 */ 108 public interface Status { 109 /** 110 * The loader is fetching data 111 */ 112 public static final int LOADING = 0; 113 114 /** 115 * Not currently busy. We are waiting for the user to enter data 116 */ 117 public static final int EDITING = 1; 118 119 /** 120 * The data is currently being saved. This is used to prevent more 121 * auto-saves (they shouldn't overlap) 122 */ 123 public static final int SAVING = 2; 124 125 /** 126 * Prevents any more saves. This is used if in the following cases: 127 * - After Save/Close 128 * - After Revert 129 * - After the user has accepted an edit suggestion 130 * - After the user chooses to expand the compact editor 131 */ 132 public static final int CLOSING = 3; 133 134 /** 135 * Prevents saving while running a child activity. 136 */ 137 public static final int SUB_ACTIVITY = 4; 138 } 139 140 /** 141 * Sets the hosting Activity that will receive callbacks from the contact editor. 142 */ 143 void setListener(ContactEditorBaseFragment.Listener listener); 144 145 /** 146 * Initialize the contact editor. 147 */ 148 void load(String action, Uri lookupUri, Bundle intentExtras); 149 150 /** 151 * Applies extras from the hosting Activity to the first writable raw contact. 152 */ 153 void setIntentExtras(Bundle extras); 154 155 /** 156 * Saves or creates the contact based on the mode, and if successful 157 * finishes the activity. 158 * 159 * @param backPressed whether the save was initiated as a result of a back button press 160 * or because the framework stopped the editor Activity 161 */ 162 boolean save(int saveMode, boolean backPressed); 163 164 /** 165 * If there are no unsaved changes, just close the editor, otherwise the user is prompted 166 * before discarding unsaved changes. 167 */ 168 boolean revert(); 169 170 /** 171 * Invoked after the contact is saved. 172 */ 173 void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, 174 Uri contactLookupUri, Bundle updatedPhotos, boolean backPressed, long photoId, 175 long nameId); 176 177 /** 178 * Invoked after the contact is joined. 179 */ 180 void onJoinCompleted(Uri uri); 181 } 182 183 /** 184 * Boolean intent key that specifies that this activity should finish itself 185 * (instead of launching a new view intent) after the editor changes have been 186 * saved. 187 */ 188 public static final String INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED = 189 "finishActivityOnSaveCompleted"; 190 191 protected ContactEditor mFragment; 192 private boolean mFinishActivityOnSaveCompleted; 193 194 private DialogManager mDialogManager = new DialogManager(this); 195 196 @Override 197 public void onCreate(Bundle savedState) { 198 super.onCreate(savedState); 199 200 final Intent intent = getIntent(); 201 final String action = intent.getAction(); 202 203 // Determine whether or not this activity should be finished after the user is done 204 // editing the contact or if this activity should launch another activity to view the 205 // contact's details. 206 mFinishActivityOnSaveCompleted = intent.getBooleanExtra( 207 INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, false); 208 209 // The only situation where action could be ACTION_JOIN_COMPLETED is if the 210 // user joined the contact with another and closed the activity before 211 // the save operation was completed. The activity should remain closed then. 212 if (ACTION_JOIN_COMPLETED.equals(action)) { 213 finish(); 214 return; 215 } 216 217 if (ACTION_SAVE_COMPLETED.equals(action)) { 218 finish(); 219 return; 220 } 221 222 ActionBar actionBar = getActionBar(); 223 if (actionBar != null) { 224 if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) { 225 actionBar.setTitle(getResources().getString( 226 R.string.contact_editor_title_existing_contact)); 227 } else { 228 actionBar.setTitle(getResources().getString( 229 R.string.contact_editor_title_new_contact)); 230 } 231 actionBar.setDisplayShowHomeEnabled(true); 232 actionBar.setDisplayHomeAsUpEnabled(true); 233 } 234 } 235 236 @Override 237 protected void onPause() { 238 super.onPause(); 239 final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 240 final View currentFocus = getCurrentFocus(); 241 if (imm != null && currentFocus != null) { 242 imm.hideSoftInputFromWindow(currentFocus.getWindowToken(), 0); 243 } 244 } 245 246 @Override 247 protected void onNewIntent(Intent intent) { 248 super.onNewIntent(intent); 249 250 if (mFragment == null) { 251 return; 252 } 253 254 String action = intent.getAction(); 255 if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) { 256 mFragment.setIntentExtras(intent.getExtras()); 257 } else if (ACTION_SAVE_COMPLETED.equals(action)) { 258 mFragment.onSaveCompleted(true, 259 intent.getIntExtra(ContactEditorFragment.SAVE_MODE_EXTRA_KEY, 260 ContactEditor.SaveMode.CLOSE), 261 intent.getBooleanExtra(ContactSaveService.EXTRA_SAVE_SUCCEEDED, false), 262 intent.getData(), 263 (Bundle) intent.getParcelableExtra(ContactSaveService.EXTRA_UPDATED_PHOTOS), 264 intent.getBooleanExtra(ContactEditorFragment.INTENT_EXTRA_SAVE_BACK_PRESSED, 265 false), 266 intent.getLongExtra(ContactEditorFragment.INTENT_EXTRA_PHOTO_ID, -1), 267 intent.getLongExtra(ContactEditorFragment.INTENT_EXTRA_NAME_ID, -1)); 268 } else if (ACTION_JOIN_COMPLETED.equals(action)) { 269 mFragment.onJoinCompleted(intent.getData()); 270 } 271 } 272 273 @Override 274 protected Dialog onCreateDialog(int id, Bundle args) { 275 if (DialogManager.isManagedId(id)) return mDialogManager.onCreateDialog(id, args); 276 277 // Nobody knows about the Dialog 278 Log.w(TAG, "Unknown dialog requested, id: " + id + ", args: " + args); 279 return null; 280 } 281 282 protected final ContactEditorBaseFragment.Listener mFragmentListener = 283 new ContactEditorBaseFragment.Listener() { 284 285 @Override 286 public void onDeleteRequested(Uri contactUri) { 287 ContactDeletionInteraction.start(ContactEditorBaseActivity.this, contactUri, true); 288 } 289 290 @Override 291 public void onReverted() { 292 finish(); 293 } 294 295 @Override 296 public void onSaveFinished(Intent resultIntent) { 297 final boolean backPressed = resultIntent == null ? false : resultIntent.getBooleanExtra( 298 ContactEditorBaseFragment.INTENT_EXTRA_SAVE_BACK_PRESSED, false); 299 if (mFinishActivityOnSaveCompleted) { 300 setResult(resultIntent == null ? RESULT_CANCELED : RESULT_OK, resultIntent); 301 } else if (resultIntent != null) { 302 if (backPressed) { 303 ImplicitIntentsUtil.startActivityInApp(ContactEditorBaseActivity.this, 304 resultIntent); 305 } 306 } 307 finish(); 308 } 309 310 @Override 311 public void onContactSplit(Uri newLookupUri) { 312 finish(); 313 } 314 315 @Override 316 public void onContactNotFound() { 317 finish(); 318 } 319 320 @Override 321 public void onEditOtherContactRequested( 322 Uri contactLookupUri, ArrayList<ContentValues> values) { 323 final Intent intent = EditorIntents.createEditOtherContactIntent( 324 contactLookupUri, values); 325 ImplicitIntentsUtil.startActivityInApp(ContactEditorBaseActivity.this, intent); 326 finish(); 327 } 328 329 @Override 330 public void onCustomCreateContactActivityRequested(AccountWithDataSet account, 331 Bundle intentExtras) { 332 final AccountTypeManager accountTypes = 333 AccountTypeManager.getInstance(ContactEditorBaseActivity.this); 334 final AccountType accountType = accountTypes.getAccountType( 335 account.type, account.dataSet); 336 337 Intent intent = new Intent(); 338 intent.setClassName(accountType.syncAdapterPackageName, 339 accountType.getCreateContactActivityClassName()); 340 intent.setAction(Intent.ACTION_INSERT); 341 intent.setType(Contacts.CONTENT_ITEM_TYPE); 342 if (intentExtras != null) { 343 intent.putExtras(intentExtras); 344 } 345 intent.putExtra(RawContacts.ACCOUNT_NAME, account.name); 346 intent.putExtra(RawContacts.ACCOUNT_TYPE, account.type); 347 intent.putExtra(RawContacts.DATA_SET, account.dataSet); 348 intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 349 | Intent.FLAG_ACTIVITY_FORWARD_RESULT); 350 startActivity(intent); 351 finish(); 352 } 353 354 @Override 355 public void onCustomEditContactActivityRequested(AccountWithDataSet account, 356 Uri rawContactUri, Bundle intentExtras, boolean redirect) { 357 final AccountTypeManager accountTypes = 358 AccountTypeManager.getInstance(ContactEditorBaseActivity.this); 359 final AccountType accountType = accountTypes.getAccountType( 360 account.type, account.dataSet); 361 362 Intent intent = new Intent(); 363 intent.setClassName(accountType.syncAdapterPackageName, 364 accountType.getEditContactActivityClassName()); 365 intent.setAction(Intent.ACTION_EDIT); 366 intent.setData(rawContactUri); 367 if (intentExtras != null) { 368 intent.putExtras(intentExtras); 369 } 370 371 if (redirect) { 372 intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 373 | Intent.FLAG_ACTIVITY_FORWARD_RESULT); 374 startActivity(intent); 375 finish(); 376 } else { 377 startActivity(intent); 378 } 379 } 380 }; 381 382 @Override 383 public DialogManager getDialogManager() { 384 return mDialogManager; 385 } 386} 387