Home | History | Annotate | Download | only in activities
      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 
     17 package com.android.contacts.activities;
     18 
     19 import com.android.contacts.ContactSaveService;
     20 import com.android.contacts.ContactsActivity;
     21 import com.android.contacts.R;
     22 import com.android.contacts.common.model.AccountTypeManager;
     23 import com.android.contacts.common.model.account.AccountType;
     24 import com.android.contacts.common.model.account.AccountWithDataSet;
     25 import com.android.contacts.common.util.ImplicitIntentsUtil;
     26 import com.android.contacts.editor.ContactEditorBaseFragment;
     27 import com.android.contacts.editor.ContactEditorFragment;
     28 import com.android.contacts.editor.EditorIntents;
     29 import com.android.contacts.interactions.ContactDeletionInteraction;
     30 import com.android.contacts.util.DialogManager;
     31 
     32 import android.app.ActionBar;
     33 import android.app.Dialog;
     34 import android.content.ContentValues;
     35 import android.content.Intent;
     36 import android.net.Uri;
     37 import android.os.Bundle;
     38 import android.provider.ContactsContract.Contacts;
     39 import android.provider.ContactsContract.RawContacts;
     40 import android.util.Log;
     41 import android.view.View;
     42 import android.view.inputmethod.InputMethodManager;
     43 
     44 import java.util.ArrayList;
     45 
     46 /**
     47  * Base Activity for contact editors.
     48  */
     49 abstract 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