• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.contacts.activities;
18 
19 import android.app.ActionBar;
20 import android.app.ActionBar.LayoutParams;
21 import android.app.Activity;
22 import android.app.Fragment;
23 import android.content.ActivityNotFoundException;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.net.Uri;
27 import android.os.Bundle;
28 import android.provider.ContactsContract.Contacts;
29 import android.provider.ContactsContract.Intents.Insert;
30 import android.text.TextUtils;
31 import android.util.Log;
32 import android.view.LayoutInflater;
33 import android.view.Menu;
34 import android.view.MenuInflater;
35 import android.view.MenuItem;
36 import android.view.View;
37 import android.view.View.OnClickListener;
38 import android.view.View.OnFocusChangeListener;
39 import android.view.inputmethod.InputMethodManager;
40 import android.widget.SearchView;
41 import android.widget.SearchView.OnCloseListener;
42 import android.widget.SearchView.OnQueryTextListener;
43 import android.widget.Toast;
44 
45 import com.android.contacts.ContactsActivity;
46 import com.android.contacts.R;
47 import com.android.contacts.common.activity.RequestPermissionsActivity;
48 import com.android.contacts.common.list.ContactEntryListFragment;
49 import com.android.contacts.common.util.ImplicitIntentsUtil;
50 import com.android.contacts.editor.EditorIntents;
51 import com.android.contacts.list.ContactPickerFragment;
52 import com.android.contacts.list.ContactsIntentResolver;
53 import com.android.contacts.list.ContactsRequest;
54 import com.android.contacts.common.list.DirectoryListLoader;
55 import com.android.contacts.list.EmailAddressPickerFragment;
56 import com.android.contacts.list.JoinContactListFragment;
57 import com.android.contacts.list.LegacyPhoneNumberPickerFragment;
58 import com.android.contacts.list.OnContactPickerActionListener;
59 import com.android.contacts.list.OnEmailAddressPickerActionListener;
60 import com.android.contacts.list.UiIntentActions;
61 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
62 import com.android.contacts.list.OnPostalAddressPickerActionListener;
63 import com.android.contacts.common.list.PhoneNumberPickerFragment;
64 import com.android.contacts.list.PostalAddressPickerFragment;
65 import com.google.common.collect.Sets;
66 
67 import java.util.Set;
68 
69 /**
70  * Displays a list of contacts (or phone numbers or postal addresses) for the
71  * purposes of selecting one.
72  */
73 public class ContactSelectionActivity extends ContactsActivity
74         implements View.OnCreateContextMenuListener, OnQueryTextListener, OnClickListener,
75                 OnCloseListener, OnFocusChangeListener {
76     private static final String TAG = "ContactSelectionActivity";
77 
78     private static final int SUBACTIVITY_ADD_TO_EXISTING_CONTACT = 0;
79 
80     private static final String KEY_ACTION_CODE = "actionCode";
81     private static final String KEY_SEARCH_MODE = "searchMode";
82     private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20;
83 
84     private ContactsIntentResolver mIntentResolver;
85     protected ContactEntryListFragment<?> mListFragment;
86 
87     private int mActionCode = -1;
88     private boolean mIsSearchMode;
89     private boolean mIsSearchSupported;
90 
91     private ContactsRequest mRequest;
92     private SearchView mSearchView;
93     private View mSearchViewContainer;
94 
ContactSelectionActivity()95     public ContactSelectionActivity() {
96         mIntentResolver = new ContactsIntentResolver(this);
97     }
98 
99     @Override
onAttachFragment(Fragment fragment)100     public void onAttachFragment(Fragment fragment) {
101         if (fragment instanceof ContactEntryListFragment<?>) {
102             mListFragment = (ContactEntryListFragment<?>) fragment;
103             setupActionListener();
104         }
105     }
106 
107     @Override
onCreate(Bundle savedState)108     protected void onCreate(Bundle savedState) {
109         super.onCreate(savedState);
110 
111         if (RequestPermissionsActivity.startPermissionActivity(this)) {
112             return;
113         }
114 
115         if (savedState != null) {
116             mActionCode = savedState.getInt(KEY_ACTION_CODE);
117             mIsSearchMode = savedState.getBoolean(KEY_SEARCH_MODE);
118         }
119 
120         // Extract relevant information from the intent
121         mRequest = mIntentResolver.resolveIntent(getIntent());
122         if (!mRequest.isValid()) {
123             setResult(RESULT_CANCELED);
124             finish();
125             return;
126         }
127 
128         configureActivityTitle();
129 
130         setContentView(R.layout.contact_picker);
131 
132         if (mActionCode != mRequest.getActionCode()) {
133             mActionCode = mRequest.getActionCode();
134             configureListFragment();
135         }
136 
137         prepareSearchViewAndActionBar();
138     }
139 
prepareSearchViewAndActionBar()140     private void prepareSearchViewAndActionBar() {
141         final ActionBar actionBar = getActionBar();
142         mSearchViewContainer = LayoutInflater.from(actionBar.getThemedContext())
143                 .inflate(R.layout.custom_action_bar, null);
144         mSearchView = (SearchView) mSearchViewContainer.findViewById(R.id.search_view);
145 
146         // Postal address pickers (and legacy pickers) don't support search, so just show
147         // "HomeAsUp" button and title.
148         if (mRequest.getActionCode() == ContactsRequest.ACTION_PICK_POSTAL ||
149                 mRequest.isLegacyCompatibilityMode()) {
150             mSearchView.setVisibility(View.GONE);
151             if (actionBar != null) {
152                 actionBar.setDisplayShowHomeEnabled(true);
153                 actionBar.setDisplayHomeAsUpEnabled(true);
154                 actionBar.setDisplayShowTitleEnabled(true);
155             }
156             mIsSearchSupported = false;
157             configureSearchMode();
158             return;
159         }
160 
161         actionBar.setDisplayShowHomeEnabled(true);
162         actionBar.setDisplayHomeAsUpEnabled(true);
163 
164         // In order to make the SearchView look like "shown via search menu", we need to
165         // manually setup its state. See also DialtactsActivity.java and ActionBarAdapter.java.
166         mSearchView.setIconifiedByDefault(true);
167         mSearchView.setQueryHint(getString(R.string.hint_findContacts));
168         mSearchView.setIconified(false);
169         mSearchView.setFocusable(true);
170 
171         mSearchView.setOnQueryTextListener(this);
172         mSearchView.setOnCloseListener(this);
173         mSearchView.setOnQueryTextFocusChangeListener(this);
174 
175         actionBar.setCustomView(mSearchViewContainer,
176                 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
177         actionBar.setDisplayShowCustomEnabled(true);
178 
179         mIsSearchSupported = true;
180         configureSearchMode();
181     }
182 
configureSearchMode()183     private void configureSearchMode() {
184         final ActionBar actionBar = getActionBar();
185         if (mIsSearchMode) {
186             actionBar.setDisplayShowTitleEnabled(false);
187             mSearchViewContainer.setVisibility(View.VISIBLE);
188             mSearchView.requestFocus();
189         } else {
190             actionBar.setDisplayShowTitleEnabled(true);
191             mSearchViewContainer.setVisibility(View.GONE);
192             mSearchView.setQuery(null, true);
193         }
194         invalidateOptionsMenu();
195     }
196 
197     @Override
onOptionsItemSelected(MenuItem item)198     public boolean onOptionsItemSelected(MenuItem item) {
199         switch (item.getItemId()) {
200             case android.R.id.home:
201                 // Go back to previous screen, intending "cancel"
202                 setResult(RESULT_CANCELED);
203                 onBackPressed();
204                 return true;
205             case R.id.menu_search:
206                 mIsSearchMode = !mIsSearchMode;
207                 configureSearchMode();
208                 return true;
209         }
210         return super.onOptionsItemSelected(item);
211     }
212 
213     @Override
onSaveInstanceState(Bundle outState)214     protected void onSaveInstanceState(Bundle outState) {
215         super.onSaveInstanceState(outState);
216         outState.putInt(KEY_ACTION_CODE, mActionCode);
217         outState.putBoolean(KEY_SEARCH_MODE, mIsSearchMode);
218     }
219 
configureActivityTitle()220     private void configureActivityTitle() {
221         if (!TextUtils.isEmpty(mRequest.getActivityTitle())) {
222             setTitle(mRequest.getActivityTitle());
223             return;
224         }
225 
226         int actionCode = mRequest.getActionCode();
227         switch (actionCode) {
228             case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
229                 setTitle(R.string.contactInsertOrEditActivityTitle);
230                 break;
231             }
232 
233             case ContactsRequest.ACTION_PICK_CONTACT: {
234                 setTitle(R.string.contactPickerActivityTitle);
235                 break;
236             }
237 
238             case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
239                 setTitle(R.string.contactPickerActivityTitle);
240                 break;
241             }
242 
243             case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
244                 setTitle(R.string.shortcutActivityTitle);
245                 break;
246             }
247 
248             case ContactsRequest.ACTION_PICK_PHONE: {
249                 setTitle(R.string.contactPickerActivityTitle);
250                 break;
251             }
252 
253             case ContactsRequest.ACTION_PICK_EMAIL: {
254                 setTitle(R.string.contactPickerActivityTitle);
255                 break;
256             }
257 
258             case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
259                 setTitle(R.string.callShortcutActivityTitle);
260                 break;
261             }
262 
263             case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
264                 setTitle(R.string.messageShortcutActivityTitle);
265                 break;
266             }
267 
268             case ContactsRequest.ACTION_PICK_POSTAL: {
269                 setTitle(R.string.contactPickerActivityTitle);
270                 break;
271             }
272 
273             case ContactsRequest.ACTION_PICK_JOIN: {
274                 setTitle(R.string.titleJoinContactDataWith);
275                 break;
276             }
277         }
278     }
279 
280     /**
281      * Creates the fragment based on the current request.
282      */
configureListFragment()283     public void configureListFragment() {
284         switch (mActionCode) {
285             case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
286                 ContactPickerFragment fragment = new ContactPickerFragment();
287                 fragment.setEditMode(true);
288                 fragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
289                 fragment.setCreateContactEnabled(!mRequest.isSearchMode());
290                 mListFragment = fragment;
291                 break;
292             }
293 
294             case ContactsRequest.ACTION_DEFAULT:
295             case ContactsRequest.ACTION_PICK_CONTACT: {
296                 ContactPickerFragment fragment = new ContactPickerFragment();
297                 fragment.setIncludeProfile(mRequest.shouldIncludeProfile());
298                 mListFragment = fragment;
299                 break;
300             }
301 
302             case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
303                 ContactPickerFragment fragment = new ContactPickerFragment();
304                 fragment.setCreateContactEnabled(!mRequest.isSearchMode());
305                 mListFragment = fragment;
306                 break;
307             }
308 
309             case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
310                 ContactPickerFragment fragment = new ContactPickerFragment();
311                 fragment.setShortcutRequested(true);
312                 mListFragment = fragment;
313                 break;
314             }
315 
316             case ContactsRequest.ACTION_PICK_PHONE: {
317                 PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
318                 mListFragment = fragment;
319                 break;
320             }
321 
322             case ContactsRequest.ACTION_PICK_EMAIL: {
323                 mListFragment = new EmailAddressPickerFragment();
324                 break;
325             }
326 
327             case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
328                 PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
329                 fragment.setShortcutAction(Intent.ACTION_CALL);
330 
331                 mListFragment = fragment;
332                 break;
333             }
334 
335             case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
336                 PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
337                 fragment.setShortcutAction(Intent.ACTION_SENDTO);
338 
339                 mListFragment = fragment;
340                 break;
341             }
342 
343             case ContactsRequest.ACTION_PICK_POSTAL: {
344                 PostalAddressPickerFragment fragment = new PostalAddressPickerFragment();
345 
346                 mListFragment = fragment;
347                 break;
348             }
349 
350             case ContactsRequest.ACTION_PICK_JOIN: {
351                 JoinContactListFragment joinFragment = new JoinContactListFragment();
352                 joinFragment.setTargetContactId(getTargetContactId());
353                 mListFragment = joinFragment;
354                 break;
355             }
356 
357             default:
358                 throw new IllegalStateException("Invalid action code: " + mActionCode);
359         }
360 
361         // Setting compatibility is no longer needed for PhoneNumberPickerFragment since that logic
362         // has been separated into LegacyPhoneNumberPickerFragment.  But we still need to set
363         // compatibility for other fragments.
364         mListFragment.setLegacyCompatibilityMode(mRequest.isLegacyCompatibilityMode());
365         mListFragment.setDirectoryResultLimit(DEFAULT_DIRECTORY_RESULT_LIMIT);
366 
367         getFragmentManager().beginTransaction()
368                 .replace(R.id.list_container, mListFragment)
369                 .commitAllowingStateLoss();
370     }
371 
getPhoneNumberPickerFragment(ContactsRequest request)372     private PhoneNumberPickerFragment getPhoneNumberPickerFragment(ContactsRequest request) {
373         if (mRequest.isLegacyCompatibilityMode()) {
374             return new LegacyPhoneNumberPickerFragment();
375         } else {
376             return new PhoneNumberPickerFragment();
377         }
378     }
379 
setupActionListener()380     public void setupActionListener() {
381         if (mListFragment instanceof ContactPickerFragment) {
382             ((ContactPickerFragment) mListFragment).setOnContactPickerActionListener(
383                     new ContactPickerActionListener());
384         } else if (mListFragment instanceof PhoneNumberPickerFragment) {
385             ((PhoneNumberPickerFragment) mListFragment).setOnPhoneNumberPickerActionListener(
386                     new PhoneNumberPickerActionListener());
387         } else if (mListFragment instanceof PostalAddressPickerFragment) {
388             ((PostalAddressPickerFragment) mListFragment).setOnPostalAddressPickerActionListener(
389                     new PostalAddressPickerActionListener());
390         } else if (mListFragment instanceof EmailAddressPickerFragment) {
391             ((EmailAddressPickerFragment) mListFragment).setOnEmailAddressPickerActionListener(
392                     new EmailAddressPickerActionListener());
393         } else if (mListFragment instanceof JoinContactListFragment) {
394             ((JoinContactListFragment) mListFragment).setOnContactPickerActionListener(
395                     new JoinContactActionListener());
396         } else {
397             throw new IllegalStateException("Unsupported list fragment type: " + mListFragment);
398         }
399     }
400 
401     private final class ContactPickerActionListener implements OnContactPickerActionListener {
402         @Override
onCreateNewContactAction()403         public void onCreateNewContactAction() {
404             startCreateNewContactActivity();
405         }
406 
407         @Override
onEditContactAction(Uri contactLookupUri)408         public void onEditContactAction(Uri contactLookupUri) {
409             Bundle extras = getIntent().getExtras();
410             if (launchAddToContactDialog(extras)) {
411                 // Show a confirmation dialog to add the value(s) to the existing contact.
412                 Intent intent = new Intent(ContactSelectionActivity.this,
413                         ConfirmAddDetailActivity.class);
414                 intent.setData(contactLookupUri);
415                 if (extras != null) {
416                     // First remove name key if present because the dialog does not support name
417                     // editing. This is fine because the user wants to add information to an
418                     // existing contact, who should already have a name and we wouldn't want to
419                     // override the name.
420                     extras.remove(Insert.NAME);
421                     intent.putExtras(extras);
422                 }
423 
424                 // Wait for the activity result because we want to keep the picker open (in case the
425                 // user cancels adding the info to a contact and wants to pick someone else).
426                 startActivityForResult(intent, SUBACTIVITY_ADD_TO_EXISTING_CONTACT);
427             } else {
428                 // Otherwise launch the full contact editor.
429                 startActivityAndForwardResult(EditorIntents.createEditContactIntent(
430                         contactLookupUri, /* materialPalette =*/ null, /* photoId =*/ -1,
431                         /* nameId =*/ -1));
432             }
433         }
434 
435         @Override
onPickContactAction(Uri contactUri)436         public void onPickContactAction(Uri contactUri) {
437             returnPickerResult(contactUri);
438         }
439 
440         @Override
onShortcutIntentCreated(Intent intent)441         public void onShortcutIntentCreated(Intent intent) {
442             returnPickerResult(intent);
443         }
444 
445         /**
446          * Returns true if is a single email or single phone number provided in the {@link Intent}
447          * extras bundle so that a pop-up confirmation dialog can be used to add the data to
448          * a contact. Otherwise return false if there are other intent extras that require launching
449          * the full contact editor. Ignore extras with the key {@link Insert.NAME} because names
450          * are a special case and we typically don't want to replace the name of an existing
451          * contact.
452          */
launchAddToContactDialog(Bundle extras)453         private boolean launchAddToContactDialog(Bundle extras) {
454             if (extras == null) {
455                 return false;
456             }
457 
458             // Copy extras because the set may be modified in the next step
459             Set<String> intentExtraKeys = Sets.newHashSet();
460             intentExtraKeys.addAll(extras.keySet());
461 
462             // Ignore name key because this is an existing contact.
463             if (intentExtraKeys.contains(Insert.NAME)) {
464                 intentExtraKeys.remove(Insert.NAME);
465             }
466 
467             int numIntentExtraKeys = intentExtraKeys.size();
468             if (numIntentExtraKeys == 2) {
469                 boolean hasPhone = intentExtraKeys.contains(Insert.PHONE) &&
470                         intentExtraKeys.contains(Insert.PHONE_TYPE);
471                 boolean hasEmail = intentExtraKeys.contains(Insert.EMAIL) &&
472                         intentExtraKeys.contains(Insert.EMAIL_TYPE);
473                 return hasPhone || hasEmail;
474             } else if (numIntentExtraKeys == 1) {
475                 return intentExtraKeys.contains(Insert.PHONE) ||
476                         intentExtraKeys.contains(Insert.EMAIL);
477             }
478             // Having 0 or more than 2 intent extra keys means that we should launch
479             // the full contact editor to properly handle the intent extras.
480             return false;
481         }
482     }
483 
484     private final class PhoneNumberPickerActionListener implements
485             OnPhoneNumberPickerActionListener {
486         @Override
onPickPhoneNumberAction(Uri dataUri)487         public void onPickPhoneNumberAction(Uri dataUri) {
488             returnPickerResult(dataUri);
489         }
490 
491         @Override
onCallNumberDirectly(String phoneNumber)492         public void onCallNumberDirectly(String phoneNumber) {
493             Log.w(TAG, "Unsupported call.");
494         }
495 
496         @Override
onCallNumberDirectly(String phoneNumber, boolean isVideoCall)497         public void onCallNumberDirectly(String phoneNumber, boolean isVideoCall) {
498             Log.w(TAG, "Unsupported call.");
499         }
500 
501         @Override
onShortcutIntentCreated(Intent intent)502         public void onShortcutIntentCreated(Intent intent) {
503             returnPickerResult(intent);
504         }
505 
onHomeInActionBarSelected()506         public void onHomeInActionBarSelected() {
507             ContactSelectionActivity.this.onBackPressed();
508         }
509     }
510 
511     private final class JoinContactActionListener implements OnContactPickerActionListener {
512         @Override
onPickContactAction(Uri contactUri)513         public void onPickContactAction(Uri contactUri) {
514             Intent intent = new Intent(null, contactUri);
515             setResult(RESULT_OK, intent);
516             finish();
517         }
518 
519         @Override
onShortcutIntentCreated(Intent intent)520         public void onShortcutIntentCreated(Intent intent) {
521         }
522 
523         @Override
onCreateNewContactAction()524         public void onCreateNewContactAction() {
525         }
526 
527         @Override
onEditContactAction(Uri contactLookupUri)528         public void onEditContactAction(Uri contactLookupUri) {
529         }
530     }
531 
532     private final class PostalAddressPickerActionListener implements
533             OnPostalAddressPickerActionListener {
534         @Override
onPickPostalAddressAction(Uri dataUri)535         public void onPickPostalAddressAction(Uri dataUri) {
536             returnPickerResult(dataUri);
537         }
538     }
539 
540     private final class EmailAddressPickerActionListener implements
541             OnEmailAddressPickerActionListener {
542         @Override
onPickEmailAddressAction(Uri dataUri)543         public void onPickEmailAddressAction(Uri dataUri) {
544             returnPickerResult(dataUri);
545         }
546     }
547 
startActivityAndForwardResult(final Intent intent)548     public void startActivityAndForwardResult(final Intent intent) {
549         intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
550 
551         // Forward extras to the new activity
552         Bundle extras = getIntent().getExtras();
553         if (extras != null) {
554             intent.putExtras(extras);
555         }
556         try {
557             startActivity(intent);
558         } catch (ActivityNotFoundException e) {
559             Log.e(TAG, "startActivity() failed: " + e);
560             Toast.makeText(ContactSelectionActivity.this, R.string.missing_app,
561                     Toast.LENGTH_SHORT).show();
562         }
563         finish();
564     }
565 
566     @Override
onQueryTextChange(String newText)567     public boolean onQueryTextChange(String newText) {
568         mListFragment.setQueryString(newText, true);
569         return false;
570     }
571 
572     @Override
onQueryTextSubmit(String query)573     public boolean onQueryTextSubmit(String query) {
574         return false;
575     }
576 
577     @Override
onClose()578     public boolean onClose() {
579         if (!TextUtils.isEmpty(mSearchView.getQuery())) {
580             mSearchView.setQuery(null, true);
581         }
582         return true;
583     }
584 
585     @Override
onFocusChange(View view, boolean hasFocus)586     public void onFocusChange(View view, boolean hasFocus) {
587         switch (view.getId()) {
588             case R.id.search_view: {
589                 if (hasFocus) {
590                     showInputMethod(mSearchView.findFocus());
591                 }
592             }
593         }
594     }
595 
returnPickerResult(Uri data)596     public void returnPickerResult(Uri data) {
597         Intent intent = new Intent();
598         intent.setData(data);
599         returnPickerResult(intent);
600     }
601 
returnPickerResult(Intent intent)602     public void returnPickerResult(Intent intent) {
603         intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
604         setResult(RESULT_OK, intent);
605         finish();
606     }
607 
608     @Override
onClick(View view)609     public void onClick(View view) {
610         switch (view.getId()) {
611             case R.id.floating_action_button: {
612                 startCreateNewContactActivity();
613                 break;
614             }
615         }
616     }
617 
getTargetContactId()618     private long getTargetContactId() {
619         Intent intent = getIntent();
620         final long targetContactId = intent.getLongExtra(
621                 UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
622         if (targetContactId == -1) {
623             Log.e(TAG, "Intent " + intent.getAction() + " is missing required extra: "
624                     + UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY);
625             setResult(RESULT_CANCELED);
626             finish();
627             return -1;
628         }
629         return targetContactId;
630     }
631 
startCreateNewContactActivity()632     private void startCreateNewContactActivity() {
633         Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
634         intent.putExtra(ContactEditorActivity.INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true);
635         startActivityAndForwardResult(intent);
636     }
637 
showInputMethod(View view)638     private void showInputMethod(View view) {
639         final InputMethodManager imm = (InputMethodManager)
640                 getSystemService(Context.INPUT_METHOD_SERVICE);
641         if (imm != null) {
642             if (!imm.showSoftInput(view, 0)) {
643                 Log.w(TAG, "Failed to show soft input method.");
644             }
645         }
646     }
647 
648     @Override
onActivityResult(int requestCode, int resultCode, Intent data)649     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
650         super.onActivityResult(requestCode, resultCode, data);
651         if (requestCode == SUBACTIVITY_ADD_TO_EXISTING_CONTACT) {
652             if (resultCode == Activity.RESULT_OK) {
653                 if (data != null) {
654                     ImplicitIntentsUtil.startActivityInAppIfPossible(this, data);
655                 }
656                 finish();
657             }
658         }
659     }
660 
661     @Override
onCreateOptionsMenu(Menu menu)662     public boolean onCreateOptionsMenu(Menu menu) {
663         super.onCreateOptionsMenu(menu);
664 
665         final MenuInflater inflater = getMenuInflater();
666         inflater.inflate(R.menu.search_menu, menu);
667 
668         final MenuItem searchItem = menu.findItem(R.id.menu_search);
669         searchItem.setVisible(!mIsSearchMode && mIsSearchSupported);
670         return true;
671     }
672 
673     @Override
onBackPressed()674     public void onBackPressed() {
675         if (mIsSearchMode) {
676             mIsSearchMode = false;
677             configureSearchMode();
678         } else {
679             super.onBackPressed();
680         }
681     }
682 }
683