ContactSelectionActivity.java revision d11bca23766abf3325cebbec5b1b225e3fe4663f
1/*
2 * Copyright (C) 2007 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.R;
20import com.android.contacts.list.ContactEntryListFragment;
21import com.android.contacts.list.ContactPickerFragment;
22import com.android.contacts.list.ContactsIntentResolver;
23import com.android.contacts.list.ContactsRequest;
24import com.android.contacts.list.DirectoryListLoader;
25import com.android.contacts.list.OnContactPickerActionListener;
26import com.android.contacts.list.OnPhoneNumberPickerActionListener;
27import com.android.contacts.list.OnPostalAddressPickerActionListener;
28import com.android.contacts.list.PhoneNumberPickerFragment;
29import com.android.contacts.list.PostalAddressPickerFragment;
30import com.android.contacts.widget.ContextMenuAdapter;
31
32import android.app.Activity;
33import android.app.Fragment;
34import android.content.Intent;
35import android.net.Uri;
36import android.os.Bundle;
37import android.provider.ContactsContract.Contacts;
38import android.text.TextUtils;
39import android.view.MenuItem;
40import android.view.View;
41import android.view.View.OnClickListener;
42import android.widget.Button;
43import android.widget.SearchView;
44import android.widget.SearchView.OnQueryChangeListener;
45
46/**
47 * Displays a list of contacts (or phone numbers or postal addresses) for the
48 * purposes of selecting one.
49 */
50public class ContactSelectionActivity extends Activity
51        implements View.OnCreateContextMenuListener, OnQueryChangeListener, OnClickListener {
52    private static final String TAG = "ContactSelectionActivity";
53
54    private static final String KEY_ACTION_CODE = "actionCode";
55    private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20;
56
57    private ContactsIntentResolver mIntentResolver;
58    protected ContactEntryListFragment<?> mListFragment;
59
60    private int mActionCode = -1;
61
62    private ContactsRequest mRequest;
63    private SearchView mSearchView;
64
65    public ContactSelectionActivity() {
66        mIntentResolver = new ContactsIntentResolver(this);
67    }
68
69    @Override
70    public void onAttachFragment(Fragment fragment) {
71        if (fragment instanceof ContactEntryListFragment<?>) {
72            mListFragment = (ContactEntryListFragment<?>) fragment;
73            setupActionListener();
74        }
75    }
76
77    @Override
78    protected void onCreate(Bundle savedState) {
79        super.onCreate(savedState);
80
81        if (savedState != null) {
82            mActionCode = savedState.getInt(KEY_ACTION_CODE);
83        }
84
85        // Extract relevant information from the intent
86        mRequest = mIntentResolver.resolveIntent(getIntent());
87        if (!mRequest.isValid()) {
88            setResult(RESULT_CANCELED);
89            finish();
90            return;
91        }
92
93        Intent redirect = mRequest.getRedirectIntent();
94        if (redirect != null) {
95            // Need to start a different activity
96            startActivity(redirect);
97            finish();
98            return;
99        }
100
101        configureActivityTitle();
102
103        setContentView(R.layout.contact_picker);
104
105        configureListFragment();
106
107        mSearchView = (SearchView)findViewById(R.id.search_view);
108        mSearchView.setQueryHint(getString(R.string.hint_findContacts));
109        mSearchView.setOnQueryChangeListener(this);
110
111        // This is a hack to prevent the search view from grabbing focus
112        // at this point.  If search view were visible, it would always grabs focus
113        // because it is the first focusable widget in the window.
114        mSearchView.setVisibility(View.INVISIBLE);
115        mSearchView.post(new Runnable() {
116
117            @Override
118            public void run() {
119                mSearchView.setVisibility(View.VISIBLE);
120            }
121        });
122
123        Button cancel = (Button) findViewById(R.id.cancel);
124        cancel.setOnClickListener(this);
125    }
126
127    @Override
128    protected void onSaveInstanceState(Bundle outState) {
129        super.onSaveInstanceState(outState);
130        outState.putInt(KEY_ACTION_CODE, mActionCode);
131    }
132
133    private void configureActivityTitle() {
134        if (mRequest.getActivityTitle() != null) {
135            setTitle(mRequest.getActivityTitle());
136            return;
137        }
138
139        int actionCode = mRequest.getActionCode();
140        switch (actionCode) {
141            case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
142                setTitle(R.string.contactPickerActivityTitle);
143                break;
144            }
145
146            case ContactsRequest.ACTION_PICK_CONTACT: {
147                setTitle(R.string.contactPickerActivityTitle);
148                break;
149            }
150
151            case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
152                setTitle(R.string.contactPickerActivityTitle);
153                break;
154            }
155
156            case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
157                setTitle(R.string.shortcutActivityTitle);
158                break;
159            }
160
161            case ContactsRequest.ACTION_PICK_PHONE: {
162                setTitle(R.string.contactPickerActivityTitle);
163                break;
164            }
165
166            case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
167                setTitle(R.string.callShortcutActivityTitle);
168                break;
169            }
170
171            case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
172                setTitle(R.string.messageShortcutActivityTitle);
173                break;
174            }
175
176            case ContactsRequest.ACTION_PICK_POSTAL: {
177                setTitle(R.string.contactPickerActivityTitle);
178                break;
179            }
180        }
181    }
182
183    /**
184     * Creates the fragment based on the current request.
185     */
186    public void configureListFragment() {
187        if (mActionCode == mRequest.getActionCode()) {
188            return;
189        }
190
191        mActionCode = mRequest.getActionCode();
192        switch (mActionCode) {
193            case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
194                ContactPickerFragment fragment = new ContactPickerFragment();
195                fragment.setCreateContactEnabled(true);
196                fragment.setEditMode(true);
197                fragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
198                mListFragment = fragment;
199                break;
200            }
201
202            case ContactsRequest.ACTION_PICK_CONTACT: {
203                ContactPickerFragment fragment = new ContactPickerFragment();
204                fragment.setSearchMode(mRequest.isSearchMode());
205                mListFragment = fragment;
206                break;
207            }
208
209            case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
210                ContactPickerFragment fragment = new ContactPickerFragment();
211                fragment.setCreateContactEnabled(!mRequest.isSearchMode());
212                mListFragment = fragment;
213                break;
214            }
215
216            case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
217                ContactPickerFragment fragment = new ContactPickerFragment();
218                fragment.setSearchMode(mRequest.isSearchMode());
219                fragment.setQueryString(mRequest.getQueryString());
220                fragment.setShortcutRequested(true);
221                mListFragment = fragment;
222                break;
223            }
224
225            case ContactsRequest.ACTION_PICK_PHONE: {
226                PhoneNumberPickerFragment fragment = new PhoneNumberPickerFragment();
227                mListFragment = fragment;
228                break;
229            }
230
231            case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
232                PhoneNumberPickerFragment fragment = new PhoneNumberPickerFragment();
233                fragment.setShortcutAction(Intent.ACTION_CALL);
234                fragment.setSearchMode(mRequest.isSearchMode());
235
236                mListFragment = fragment;
237                break;
238            }
239
240            case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
241                PhoneNumberPickerFragment fragment = new PhoneNumberPickerFragment();
242                fragment.setShortcutAction(Intent.ACTION_SENDTO);
243
244                mListFragment = fragment;
245                break;
246            }
247
248            case ContactsRequest.ACTION_PICK_POSTAL: {
249                PostalAddressPickerFragment fragment = new PostalAddressPickerFragment();
250                mListFragment = fragment;
251                break;
252            }
253
254            default:
255                throw new IllegalStateException("Invalid action code: " + mActionCode);
256        }
257
258        mListFragment.setLegacyCompatibilityMode(mRequest.isLegacyCompatibilityMode());
259        mListFragment.setContactsRequest(mRequest);
260        mListFragment.setSearchMode(mRequest.isSearchMode());
261        mListFragment.setQueryString(mRequest.getQueryString());
262        mListFragment.setDirectoryResultLimit(DEFAULT_DIRECTORY_RESULT_LIMIT);
263
264        getFragmentManager().openTransaction()
265                .replace(R.id.list_container, mListFragment)
266                .commit();
267    }
268
269    public void setupActionListener() {
270        if (mListFragment instanceof ContactPickerFragment) {
271            ((ContactPickerFragment) mListFragment).setOnContactPickerActionListener(
272                    new ContactPickerActionListener());
273        } else if (mListFragment instanceof PhoneNumberPickerFragment) {
274            ((PhoneNumberPickerFragment) mListFragment).setOnPhoneNumberPickerActionListener(
275                    new PhoneNumberPickerActionListener());
276        } else if (mListFragment instanceof PostalAddressPickerFragment) {
277            ((PostalAddressPickerFragment) mListFragment).setOnPostalAddressPickerActionListener(
278                    new PostalAddressPickerActionListener());
279        } else {
280            throw new IllegalStateException("Unsupported list fragment type: " + mListFragment);
281        }
282    }
283
284    private final class ContactPickerActionListener implements OnContactPickerActionListener {
285        @Override
286        public void onCreateNewContactAction() {
287            Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
288            startActivityAndForwardResult(intent);
289        }
290
291        @Override
292        public void onEditContactAction(Uri contactLookupUri) {
293            Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
294            startActivityAndForwardResult(intent);
295        }
296
297        @Override
298        public void onPickContactAction(Uri contactUri) {
299            returnPickerResult(contactUri);
300        }
301
302        @Override
303        public void onShortcutIntentCreated(Intent intent) {
304            returnPickerResult(intent);
305        }
306    }
307
308    private final class PhoneNumberPickerActionListener implements
309            OnPhoneNumberPickerActionListener {
310        @Override
311        public void onPickPhoneNumberAction(Uri dataUri) {
312            returnPickerResult(dataUri);
313        }
314
315        @Override
316        public void onShortcutIntentCreated(Intent intent) {
317            returnPickerResult(intent);
318        }
319    }
320
321    private final class PostalAddressPickerActionListener implements
322            OnPostalAddressPickerActionListener {
323        @Override
324        public void onPickPostalAddressAction(Uri dataUri) {
325            returnPickerResult(dataUri);
326        }
327    }
328
329    public void startActivityAndForwardResult(final Intent intent) {
330        intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
331
332        // Forward extras to the new activity
333        Bundle extras = getIntent().getExtras();
334        if (extras != null) {
335            intent.putExtras(extras);
336        }
337        startActivity(intent);
338        finish();
339    }
340
341    @Override
342    public boolean onContextItemSelected(MenuItem item) {
343        ContextMenuAdapter menuAdapter = mListFragment.getContextMenuAdapter();
344        if (menuAdapter != null) {
345            return menuAdapter.onContextItemSelected(item);
346        }
347
348        return super.onContextItemSelected(item);
349    }
350
351    @Override
352    public boolean onQueryTextChanged(String newText) {
353        mListFragment.setQueryString(newText);
354        mListFragment.setSearchMode(!TextUtils.isEmpty(newText));
355        return false;
356    }
357
358    @Override
359    public boolean onSubmitQuery(String query) {
360        return false;
361    }
362
363    public void returnPickerResult(Uri data) {
364        Intent intent = new Intent();
365        intent.setData(data);
366        returnPickerResult(intent);
367    }
368
369    public void returnPickerResult(Intent intent) {
370        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
371        setResult(RESULT_OK, intent);
372        finish();
373    }
374
375    @Override
376    public void onClick(View v) {
377        if (v.getId() == R.id.cancel) {
378            setResult(RESULT_CANCELED);
379            finish();
380        }
381    }
382}
383