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