ContactEditorBaseActivity.java revision 28a27279554af7b1e5ff664d3da97954c462a797
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        boolean save(int saveMode);
160
161        /**
162         * If there are no unsaved changes, just close the editor, otherwise the user is prompted
163         * before discarding unsaved changes.
164         */
165        boolean revert();
166
167        /**
168         * Invoked after the contact is saved.
169         */
170        void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
171                Uri contactLookupUri);
172
173        /**
174         * Invoked after the contact is joined.
175         */
176        void onJoinCompleted(Uri uri);
177    }
178
179    /**
180     * Boolean intent key that specifies that this activity should finish itself
181     * (instead of launching a new view intent) after the editor changes have been
182     * saved.
183     */
184    public static final String INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED =
185            "finishActivityOnSaveCompleted";
186
187    protected ContactEditor mFragment;
188    private boolean mFinishActivityOnSaveCompleted;
189
190    private DialogManager mDialogManager = new DialogManager(this);
191
192    @Override
193    public void onCreate(Bundle savedState) {
194        super.onCreate(savedState);
195
196        final Intent intent = getIntent();
197        final String action = intent.getAction();
198
199        // Determine whether or not this activity should be finished after the user is done
200        // editing the contact or if this activity should launch another activity to view the
201        // contact's details.
202        mFinishActivityOnSaveCompleted = intent.getBooleanExtra(
203                INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, false);
204
205        // The only situation where action could be ACTION_JOIN_COMPLETED is if the
206        // user joined the contact with another and closed the activity before
207        // the save operation was completed.  The activity should remain closed then.
208        if (ACTION_JOIN_COMPLETED.equals(action)) {
209            finish();
210            return;
211        }
212
213        if (ACTION_SAVE_COMPLETED.equals(action)) {
214            finish();
215            return;
216        }
217
218        ActionBar actionBar = getActionBar();
219        if (actionBar != null) {
220            if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) {
221                actionBar.setTitle(getResources().getString(
222                        R.string.contact_editor_title_existing_contact));
223            } else {
224                actionBar.setTitle(getResources().getString(
225                        R.string.contact_editor_title_new_contact));
226            }
227            actionBar.setDisplayShowHomeEnabled(true);
228            actionBar.setDisplayHomeAsUpEnabled(true);
229        }
230    }
231
232    @Override
233    protected void onPause() {
234        super.onPause();
235        final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
236        final View currentFocus = getCurrentFocus();
237        if (imm != null && currentFocus != null) {
238            imm.hideSoftInputFromWindow(currentFocus.getWindowToken(), 0);
239        }
240    }
241
242    @Override
243    protected void onNewIntent(Intent intent) {
244        super.onNewIntent(intent);
245
246        if (mFragment == null) {
247            return;
248        }
249
250        String action = intent.getAction();
251        if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) {
252            mFragment.setIntentExtras(intent.getExtras());
253        } else if (ACTION_SAVE_COMPLETED.equals(action)) {
254            mFragment.onSaveCompleted(true,
255                    intent.getIntExtra(ContactEditorFragment.SAVE_MODE_EXTRA_KEY,
256                            ContactEditor.SaveMode.CLOSE),
257                    intent.getBooleanExtra(ContactSaveService.EXTRA_SAVE_SUCCEEDED, false),
258                    intent.getData());
259        } else if (ACTION_JOIN_COMPLETED.equals(action)) {
260            mFragment.onJoinCompleted(intent.getData());
261        }
262    }
263
264    @Override
265    protected Dialog onCreateDialog(int id, Bundle args) {
266        if (DialogManager.isManagedId(id)) return mDialogManager.onCreateDialog(id, args);
267
268        // Nobody knows about the Dialog
269        Log.w(TAG, "Unknown dialog requested, id: " + id + ", args: " + args);
270        return null;
271    }
272
273    @Override
274    public void onBackPressed() {
275        if (mFragment != null) {
276            mFragment.save(ContactEditor.SaveMode.CLOSE);
277        }
278    }
279
280    protected final ContactEditorBaseFragment.Listener  mFragmentListener =
281            new ContactEditorBaseFragment.Listener() {
282
283        @Override
284        public void onDeleteRequested(Uri contactUri) {
285            ContactDeletionInteraction.start(ContactEditorBaseActivity.this, contactUri, true);
286        }
287
288        @Override
289        public void onReverted() {
290            finish();
291        }
292
293        @Override
294        public void onSaveFinished(Intent resultIntent) {
295            if (mFinishActivityOnSaveCompleted) {
296                setResult(resultIntent == null ? RESULT_CANCELED : RESULT_OK, resultIntent);
297            } else if (resultIntent != null) {
298                ImplicitIntentsUtil.startActivityInApp(ContactEditorBaseActivity.this,
299                        resultIntent);
300            }
301            finish();
302        }
303
304        @Override
305        public void onContactSplit(Uri newLookupUri) {
306            finish();
307        }
308
309        @Override
310        public void onContactNotFound() {
311            finish();
312        }
313
314        @Override
315        public void onEditOtherContactRequested(
316                Uri contactLookupUri, ArrayList<ContentValues> values) {
317            final Intent intent = EditorIntents.createEditOtherContactIntent(
318                    contactLookupUri, values);
319            ImplicitIntentsUtil.startActivityInApp(ContactEditorBaseActivity.this, intent);
320            finish();
321        }
322
323        @Override
324        public void onCustomCreateContactActivityRequested(AccountWithDataSet account,
325                Bundle intentExtras) {
326            final AccountTypeManager accountTypes =
327                    AccountTypeManager.getInstance(ContactEditorBaseActivity.this);
328            final AccountType accountType = accountTypes.getAccountType(
329                    account.type, account.dataSet);
330
331            Intent intent = new Intent();
332            intent.setClassName(accountType.syncAdapterPackageName,
333                    accountType.getCreateContactActivityClassName());
334            intent.setAction(Intent.ACTION_INSERT);
335            intent.setType(Contacts.CONTENT_ITEM_TYPE);
336            if (intentExtras != null) {
337                intent.putExtras(intentExtras);
338            }
339            intent.putExtra(RawContacts.ACCOUNT_NAME, account.name);
340            intent.putExtra(RawContacts.ACCOUNT_TYPE, account.type);
341            intent.putExtra(RawContacts.DATA_SET, account.dataSet);
342            intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
343                    | Intent.FLAG_ACTIVITY_FORWARD_RESULT);
344            startActivity(intent);
345            finish();
346        }
347
348        @Override
349        public void onCustomEditContactActivityRequested(AccountWithDataSet account,
350                Uri rawContactUri, Bundle intentExtras, boolean redirect) {
351            final AccountTypeManager accountTypes =
352                    AccountTypeManager.getInstance(ContactEditorBaseActivity.this);
353            final AccountType accountType = accountTypes.getAccountType(
354                    account.type, account.dataSet);
355
356            Intent intent = new Intent();
357            intent.setClassName(accountType.syncAdapterPackageName,
358                    accountType.getEditContactActivityClassName());
359            intent.setAction(Intent.ACTION_EDIT);
360            intent.setData(rawContactUri);
361            if (intentExtras != null) {
362                intent.putExtras(intentExtras);
363            }
364
365            if (redirect) {
366                intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
367                        | Intent.FLAG_ACTIVITY_FORWARD_RESULT);
368                startActivity(intent);
369                finish();
370            } else {
371                startActivity(intent);
372            }
373        }
374    };
375
376    @Override
377    public DialogManager getDialogManager() {
378        return mDialogManager;
379    }
380}
381