ContactEditorBaseActivity.java revision 2bac9401f5020cc726bef6ea301a85116db41c6e
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 protected int mActionBarTitleResId; 71 72 /** 73 * Contract for contact editors Fragments that are managed by this Activity. 74 */ 75 public interface ContactEditor { 76 77 /** 78 * Modes that specify what the AsyncTask has to perform after saving 79 */ 80 public interface SaveMode { 81 /** 82 * Close the editor after saving 83 */ 84 public static final int CLOSE = 0; 85 86 /** 87 * Reload the data so that the user can continue editing 88 */ 89 public static final int RELOAD = 1; 90 91 /** 92 * Split the contact after saving 93 */ 94 public static final int SPLIT = 2; 95 96 /** 97 * Join another contact after saving 98 */ 99 public static final int JOIN = 3; 100 101 /** 102 * Navigate to the compact editor view after saving. 103 */ 104 public static final int COMPACT = 4; 105 } 106 107 /** 108 * The status of the contact editor. 109 */ 110 public interface Status { 111 /** 112 * The loader is fetching data 113 */ 114 public static final int LOADING = 0; 115 116 /** 117 * Not currently busy. We are waiting for the user to enter data 118 */ 119 public static final int EDITING = 1; 120 121 /** 122 * The data is currently being saved. This is used to prevent more 123 * auto-saves (they shouldn't overlap) 124 */ 125 public static final int SAVING = 2; 126 127 /** 128 * Prevents any more saves. This is used if in the following cases: 129 * - After Save/Close 130 * - After Revert 131 * - After the user has accepted an edit suggestion 132 * - After the user chooses to expand the compact editor 133 */ 134 public static final int CLOSING = 3; 135 136 /** 137 * Prevents saving while running a child activity. 138 */ 139 public static final int SUB_ACTIVITY = 4; 140 } 141 142 /** 143 * Sets the hosting Activity that will receive callbacks from the contact editor. 144 */ 145 void setListener(ContactEditorBaseFragment.Listener listener); 146 147 /** 148 * Initialize the contact editor. 149 */ 150 void load(String action, Uri lookupUri, Bundle intentExtras); 151 152 /** 153 * Applies extras from the hosting Activity to the first writable raw contact. 154 */ 155 void setIntentExtras(Bundle extras); 156 157 /** 158 * Saves or creates the contact based on the mode, and if successful 159 * finishes the activity. 160 */ 161 boolean save(int saveMode); 162 163 /** 164 * If there are no unsaved changes, just close the editor, otherwise the user is prompted 165 * before discarding unsaved changes. 166 */ 167 boolean revert(); 168 169 /** 170 * Invoked after the contact is saved. 171 */ 172 void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, 173 Uri contactLookupUri, Long joinContactId); 174 175 /** 176 * Invoked after the contact is joined. 177 */ 178 void onJoinCompleted(Uri uri); 179 } 180 181 /** 182 * Boolean intent key that specifies that this activity should finish itself 183 * (instead of launching a new view intent) after the editor changes have been 184 * saved. 185 */ 186 public static final String INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED = 187 "finishActivityOnSaveCompleted"; 188 189 protected ContactEditor mFragment; 190 private boolean mFinishActivityOnSaveCompleted; 191 192 private DialogManager mDialogManager = new DialogManager(this); 193 194 @Override 195 public void onCreate(Bundle savedState) { 196 super.onCreate(savedState); 197 198 final Intent intent = getIntent(); 199 final String action = intent.getAction(); 200 201 // Determine whether or not this activity should be finished after the user is done 202 // editing the contact or if this activity should launch another activity to view the 203 // contact's details. 204 mFinishActivityOnSaveCompleted = intent.getBooleanExtra( 205 INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, false); 206 207 // The only situation where action could be ACTION_JOIN_COMPLETED is if the 208 // user joined the contact with another and closed the activity before 209 // the save operation was completed. The activity should remain closed then. 210 if (ACTION_JOIN_COMPLETED.equals(action)) { 211 finish(); 212 return; 213 } 214 215 if (ACTION_SAVE_COMPLETED.equals(action)) { 216 finish(); 217 return; 218 } 219 220 ActionBar actionBar = getActionBar(); 221 if (actionBar != null) { 222 if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) { 223 mActionBarTitleResId = R.string.contact_editor_title_existing_contact; 224 } else { 225 mActionBarTitleResId = R.string.contact_editor_title_new_contact; 226 } 227 actionBar.setTitle(getResources().getString(mActionBarTitleResId)); 228 actionBar.setDisplayShowHomeEnabled(true); 229 actionBar.setDisplayHomeAsUpEnabled(true); 230 } 231 } 232 233 @Override 234 protected void onPause() { 235 super.onPause(); 236 final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 237 final View currentFocus = getCurrentFocus(); 238 if (imm != null && currentFocus != null) { 239 imm.hideSoftInputFromWindow(currentFocus.getWindowToken(), 0); 240 } 241 } 242 243 @Override 244 protected void onNewIntent(Intent intent) { 245 super.onNewIntent(intent); 246 247 if (mFragment == null) { 248 return; 249 } 250 251 String action = intent.getAction(); 252 if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) { 253 mFragment.setIntentExtras(intent.getExtras()); 254 } else if (ACTION_SAVE_COMPLETED.equals(action)) { 255 mFragment.onSaveCompleted(true, 256 intent.getIntExtra(ContactEditorFragment.SAVE_MODE_EXTRA_KEY, 257 ContactEditor.SaveMode.CLOSE), 258 intent.getBooleanExtra(ContactSaveService.EXTRA_SAVE_SUCCEEDED, false), 259 intent.getData(), 260 intent.getLongExtra(ContactEditorFragment.JOIN_CONTACT_ID_EXTRA_KEY, -1)); 261 } else if (ACTION_JOIN_COMPLETED.equals(action)) { 262 mFragment.onJoinCompleted(intent.getData()); 263 } 264 } 265 266 @Override 267 protected Dialog onCreateDialog(int id, Bundle args) { 268 if (DialogManager.isManagedId(id)) return mDialogManager.onCreateDialog(id, args); 269 270 // Nobody knows about the Dialog 271 Log.w(TAG, "Unknown dialog requested, id: " + id + ", args: " + args); 272 return null; 273 } 274 275 @Override 276 public void onBackPressed() { 277 if (mFragment != null) { 278 mFragment.revert(); 279 } 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 if (mFinishActivityOnSaveCompleted) { 298 setResult(resultIntent == null ? RESULT_CANCELED : RESULT_OK, resultIntent); 299 } else if (resultIntent != null) { 300 ImplicitIntentsUtil.startActivityInApp(ContactEditorBaseActivity.this, 301 resultIntent); 302 } 303 finish(); 304 } 305 306 @Override 307 public void onContactSplit(Uri newLookupUri) { 308 finish(); 309 } 310 311 @Override 312 public void onContactNotFound() { 313 finish(); 314 } 315 316 @Override 317 public void onEditOtherContactRequested( 318 Uri contactLookupUri, ArrayList<ContentValues> values) { 319 final Intent intent = EditorIntents.createEditOtherContactIntent( 320 contactLookupUri, values); 321 ImplicitIntentsUtil.startActivityInApp(ContactEditorBaseActivity.this, intent); 322 finish(); 323 } 324 325 @Override 326 public void onCustomCreateContactActivityRequested(AccountWithDataSet account, 327 Bundle intentExtras) { 328 final AccountTypeManager accountTypes = 329 AccountTypeManager.getInstance(ContactEditorBaseActivity.this); 330 final AccountType accountType = accountTypes.getAccountType( 331 account.type, account.dataSet); 332 333 Intent intent = new Intent(); 334 intent.setClassName(accountType.syncAdapterPackageName, 335 accountType.getCreateContactActivityClassName()); 336 intent.setAction(Intent.ACTION_INSERT); 337 intent.setType(Contacts.CONTENT_ITEM_TYPE); 338 if (intentExtras != null) { 339 intent.putExtras(intentExtras); 340 } 341 intent.putExtra(RawContacts.ACCOUNT_NAME, account.name); 342 intent.putExtra(RawContacts.ACCOUNT_TYPE, account.type); 343 intent.putExtra(RawContacts.DATA_SET, account.dataSet); 344 intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 345 | Intent.FLAG_ACTIVITY_FORWARD_RESULT); 346 startActivity(intent); 347 finish(); 348 } 349 350 @Override 351 public void onCustomEditContactActivityRequested(AccountWithDataSet account, 352 Uri rawContactUri, Bundle intentExtras, boolean redirect) { 353 final AccountTypeManager accountTypes = 354 AccountTypeManager.getInstance(ContactEditorBaseActivity.this); 355 final AccountType accountType = accountTypes.getAccountType( 356 account.type, account.dataSet); 357 358 Intent intent = new Intent(); 359 intent.setClassName(accountType.syncAdapterPackageName, 360 accountType.getEditContactActivityClassName()); 361 intent.setAction(Intent.ACTION_EDIT); 362 intent.setData(rawContactUri); 363 if (intentExtras != null) { 364 intent.putExtras(intentExtras); 365 } 366 367 if (redirect) { 368 intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 369 | Intent.FLAG_ACTIVITY_FORWARD_RESULT); 370 startActivity(intent); 371 finish(); 372 } else { 373 startActivity(intent); 374 } 375 } 376 }; 377 378 @Override 379 public DialogManager getDialogManager() { 380 return mDialogManager; 381 } 382} 383