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