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