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