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.Fragment; 20 import android.content.ActivityNotFoundException; 21 import android.content.Intent; 22 import android.graphics.PorterDuff; 23 import android.graphics.drawable.Drawable; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.provider.ContactsContract.Contacts; 27 import android.support.v4.content.ContextCompat; 28 import android.support.v7.widget.Toolbar; 29 import android.text.TextUtils; 30 import android.util.Log; 31 import android.view.Menu; 32 import android.view.MenuInflater; 33 import android.view.MenuItem; 34 import android.view.View; 35 import android.view.View.OnClickListener; 36 import android.view.View.OnFocusChangeListener; 37 import android.widget.TextView; 38 import android.widget.Toast; 39 40 import com.android.contacts.AppCompatContactsActivity; 41 import com.android.contacts.R; 42 import com.android.contacts.editor.EditorIntents; 43 import com.android.contacts.list.ContactEntryListFragment; 44 import com.android.contacts.list.ContactPickerFragment; 45 import com.android.contacts.list.ContactsIntentResolver; 46 import com.android.contacts.list.ContactsRequest; 47 import com.android.contacts.list.DirectoryListLoader; 48 import com.android.contacts.list.EmailAddressPickerFragment; 49 import com.android.contacts.list.GroupMemberPickerFragment; 50 import com.android.contacts.list.JoinContactListFragment; 51 import com.android.contacts.list.LegacyPhoneNumberPickerFragment; 52 import com.android.contacts.list.MultiSelectContactsListFragment; 53 import com.android.contacts.list.MultiSelectContactsListFragment.OnCheckBoxListActionListener; 54 import com.android.contacts.list.MultiSelectEmailAddressesListFragment; 55 import com.android.contacts.list.MultiSelectPhoneNumbersListFragment; 56 import com.android.contacts.list.OnContactPickerActionListener; 57 import com.android.contacts.list.OnEmailAddressPickerActionListener; 58 import com.android.contacts.list.OnPhoneNumberPickerActionListener; 59 import com.android.contacts.list.OnPostalAddressPickerActionListener; 60 import com.android.contacts.list.PhoneNumberPickerFragment; 61 import com.android.contacts.list.PostalAddressPickerFragment; 62 import com.android.contacts.list.UiIntentActions; 63 import com.android.contacts.logging.ListEvent; 64 import com.android.contacts.util.ImplicitIntentsUtil; 65 import com.android.contacts.util.ViewUtil; 66 67 import java.util.ArrayList; 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 AppCompatContactsActivity implements 74 View.OnCreateContextMenuListener, ActionBarAdapter.Listener, OnClickListener, 75 OnFocusChangeListener, OnCheckBoxListActionListener { 76 private static final String TAG = "ContactSelection"; 77 78 private static final String KEY_ACTION_CODE = "actionCode"; 79 private static final String KEY_SEARCH_MODE = "searchMode"; 80 private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20; 81 82 private ContactsIntentResolver mIntentResolver; 83 protected ContactEntryListFragment<?> mListFragment; 84 85 private int mActionCode = -1; 86 private boolean mIsSearchMode; 87 private boolean mIsSearchSupported; 88 89 private ContactsRequest mRequest; 90 91 private ActionBarAdapter mActionBarAdapter; 92 private Toolbar mToolbar; 93 ContactSelectionActivity()94 public ContactSelectionActivity() { 95 mIntentResolver = new ContactsIntentResolver(this); 96 } 97 98 @Override onAttachFragment(Fragment fragment)99 public void onAttachFragment(Fragment fragment) { 100 if (fragment instanceof ContactEntryListFragment<?>) { 101 mListFragment = (ContactEntryListFragment<?>) fragment; 102 setupActionListener(); 103 } 104 } 105 106 @Override onCreate(Bundle savedState)107 protected void onCreate(Bundle savedState) { 108 super.onCreate(savedState); 109 110 RequestPermissionsActivity.startPermissionActivityIfNeeded(this); 111 112 if (savedState != null) { 113 mActionCode = savedState.getInt(KEY_ACTION_CODE); 114 mIsSearchMode = savedState.getBoolean(KEY_SEARCH_MODE); 115 } 116 117 // Extract relevant information from the intent 118 mRequest = mIntentResolver.resolveIntent(getIntent()); 119 if (!mRequest.isValid()) { 120 setResult(RESULT_CANCELED); 121 finish(); 122 return; 123 } 124 125 setContentView(R.layout.contact_picker); 126 127 if (mActionCode != mRequest.getActionCode()) { 128 mActionCode = mRequest.getActionCode(); 129 configureListFragment(); 130 } 131 132 prepareSearchViewAndActionBar(savedState); 133 configureActivityTitle(); 134 } 135 isSelectionMode()136 public boolean isSelectionMode() { 137 return mActionBarAdapter.isSelectionMode(); 138 } 139 isSearchMode()140 public boolean isSearchMode() { 141 return mActionBarAdapter.isSearchMode(); 142 } 143 prepareSearchViewAndActionBar(Bundle savedState)144 private void prepareSearchViewAndActionBar(Bundle savedState) { 145 mToolbar = getView(R.id.toolbar); 146 setSupportActionBar(mToolbar); 147 148 // Add a shadow under the toolbar. 149 ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources()); 150 151 mActionBarAdapter = new ActionBarAdapter(this, this, getSupportActionBar(), mToolbar, 152 R.string.enter_contact_name); 153 mActionBarAdapter.setShowHomeIcon(true); 154 mActionBarAdapter.setShowHomeAsUp(true); 155 mActionBarAdapter.initialize(savedState, mRequest); 156 157 // Postal address pickers (and legacy pickers) don't support search, so just show 158 // "HomeAsUp" button and title. 159 mIsSearchSupported = mRequest.getActionCode() != ContactsRequest.ACTION_PICK_POSTAL 160 && mRequest.getActionCode() != ContactsRequest.ACTION_PICK_EMAILS 161 && mRequest.getActionCode() != ContactsRequest.ACTION_PICK_PHONES 162 && !mRequest.isLegacyCompatibilityMode(); 163 configureSearchMode(); 164 } 165 configureSearchMode()166 private void configureSearchMode() { 167 mActionBarAdapter.setSearchMode(mIsSearchMode); 168 invalidateOptionsMenu(); 169 } 170 171 @Override onOptionsItemSelected(MenuItem item)172 public boolean onOptionsItemSelected(MenuItem item) { 173 final int id = item.getItemId(); 174 if (id == android.R.id.home) {// Go back to previous screen, intending "cancel" 175 setResult(RESULT_CANCELED); 176 onBackPressed(); 177 } else if (id == R.id.menu_search) { 178 mIsSearchMode = !mIsSearchMode; 179 configureSearchMode(); 180 } else { 181 return super.onOptionsItemSelected(item); 182 } 183 return true; 184 } 185 186 @Override onSaveInstanceState(Bundle outState)187 protected void onSaveInstanceState(Bundle outState) { 188 super.onSaveInstanceState(outState); 189 outState.putInt(KEY_ACTION_CODE, mActionCode); 190 outState.putBoolean(KEY_SEARCH_MODE, mIsSearchMode); 191 if (mActionBarAdapter != null) { 192 mActionBarAdapter.onSaveInstanceState(outState); 193 } 194 } 195 configureActivityTitle()196 private void configureActivityTitle() { 197 if (!TextUtils.isEmpty(mRequest.getActivityTitle())) { 198 getSupportActionBar().setTitle(mRequest.getActivityTitle()); 199 return; 200 } 201 int titleResId = -1; 202 int actionCode = mRequest.getActionCode(); 203 switch (actionCode) { 204 case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: { 205 titleResId = R.string.contactInsertOrEditActivityTitle; 206 break; 207 } 208 case ContactsRequest.ACTION_PICK_CONTACT: { 209 titleResId = R.string.contactPickerActivityTitle; 210 break; 211 } 212 case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: { 213 titleResId = R.string.contactPickerActivityTitle; 214 break; 215 } 216 case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: { 217 titleResId = R.string.shortcutActivityTitle; 218 break; 219 } 220 case ContactsRequest.ACTION_PICK_PHONE: { 221 titleResId = R.string.contactPickerActivityTitle; 222 break; 223 } 224 case ContactsRequest.ACTION_PICK_EMAIL: { 225 titleResId = R.string.contactPickerActivityTitle; 226 break; 227 } 228 case ContactsRequest.ACTION_PICK_PHONES: { 229 titleResId = R.string.pickerSelectContactsActivityTitle; 230 break; 231 } 232 case ContactsRequest.ACTION_PICK_EMAILS: { 233 titleResId = R.string.pickerSelectContactsActivityTitle; 234 break; 235 } 236 case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: { 237 titleResId = R.string.shortcutActivityTitle; 238 break; 239 } 240 case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: { 241 titleResId = R.string.shortcutActivityTitle; 242 break; 243 } 244 case ContactsRequest.ACTION_PICK_POSTAL: { 245 titleResId = R.string.contactPickerActivityTitle; 246 break; 247 } 248 case ContactsRequest.ACTION_PICK_JOIN: { 249 titleResId = R.string.titleJoinContactDataWith; 250 break; 251 } 252 case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: { 253 titleResId = R.string.groupMemberPickerActivityTitle; 254 break; 255 } 256 } 257 if (titleResId > 0) { 258 getSupportActionBar().setTitle(titleResId); 259 } 260 } 261 262 /** 263 * Creates the fragment based on the current request. 264 */ configureListFragment()265 public void configureListFragment() { 266 switch (mActionCode) { 267 case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: { 268 ContactPickerFragment fragment = new ContactPickerFragment(); 269 fragment.setEditMode(true); 270 fragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE); 271 fragment.setCreateContactEnabled(!mRequest.isSearchMode()); 272 fragment.setListType(ListEvent.ListType.PICK_CONTACT); 273 mListFragment = fragment; 274 break; 275 } 276 277 case ContactsRequest.ACTION_DEFAULT: 278 case ContactsRequest.ACTION_PICK_CONTACT: { 279 ContactPickerFragment fragment = new ContactPickerFragment(); 280 fragment.setIncludeFavorites(mRequest.shouldIncludeFavorites()); 281 fragment.setListType(ListEvent.ListType.PICK_CONTACT); 282 mListFragment = fragment; 283 break; 284 } 285 286 case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: { 287 ContactPickerFragment fragment = new ContactPickerFragment(); 288 fragment.setCreateContactEnabled(!mRequest.isSearchMode()); 289 fragment.setListType(ListEvent.ListType.PICK_CONTACT); 290 mListFragment = fragment; 291 break; 292 } 293 294 case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: { 295 ContactPickerFragment fragment = new ContactPickerFragment(); 296 fragment.setShortcutRequested(true); 297 fragment.setListType(ListEvent.ListType.PICK_CONTACT_FOR_SHORTCUT); 298 mListFragment = fragment; 299 break; 300 } 301 302 case ContactsRequest.ACTION_PICK_PHONE: { 303 PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest); 304 fragment.setListType(ListEvent.ListType.PICK_PHONE); 305 mListFragment = fragment; 306 break; 307 } 308 309 case ContactsRequest.ACTION_PICK_EMAIL: { 310 mListFragment = new EmailAddressPickerFragment(); 311 mListFragment.setListType(ListEvent.ListType.PICK_EMAIL); 312 break; 313 } 314 315 case ContactsRequest.ACTION_PICK_PHONES: { 316 mListFragment = new MultiSelectPhoneNumbersListFragment(); 317 mListFragment.setArguments(getIntent().getExtras()); 318 break; 319 } 320 321 case ContactsRequest.ACTION_PICK_EMAILS: { 322 mListFragment = new MultiSelectEmailAddressesListFragment(); 323 mListFragment.setArguments(getIntent().getExtras()); 324 break; 325 } 326 case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: { 327 PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest); 328 fragment.setShortcutAction(Intent.ACTION_CALL); 329 fragment.setListType(ListEvent.ListType.PICK_CONTACT_FOR_SHORTCUT); 330 mListFragment = fragment; 331 break; 332 } 333 334 case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: { 335 PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest); 336 fragment.setShortcutAction(Intent.ACTION_SENDTO); 337 fragment.setListType(ListEvent.ListType.PICK_CONTACT_FOR_SHORTCUT); 338 mListFragment = fragment; 339 break; 340 } 341 342 case ContactsRequest.ACTION_PICK_POSTAL: { 343 PostalAddressPickerFragment fragment = new PostalAddressPickerFragment(); 344 fragment.setListType(ListEvent.ListType.PICK_POSTAL); 345 mListFragment = fragment; 346 break; 347 } 348 349 case ContactsRequest.ACTION_PICK_JOIN: { 350 JoinContactListFragment joinFragment = new JoinContactListFragment(); 351 joinFragment.setTargetContactId(getTargetContactId()); 352 joinFragment.setListType(ListEvent.ListType.PICK_JOIN); 353 mListFragment = joinFragment; 354 break; 355 } 356 357 case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: { 358 final String accountName = getIntent().getStringExtra( 359 UiIntentActions.GROUP_ACCOUNT_NAME); 360 final String accountType = getIntent().getStringExtra( 361 UiIntentActions.GROUP_ACCOUNT_TYPE); 362 final String accountDataSet = getIntent().getStringExtra( 363 UiIntentActions.GROUP_ACCOUNT_DATA_SET); 364 final ArrayList<String> contactIds = getIntent().getStringArrayListExtra( 365 UiIntentActions.GROUP_CONTACT_IDS); 366 mListFragment = GroupMemberPickerFragment.newInstance( 367 accountName, accountType, accountDataSet, contactIds); 368 mListFragment.setListType(ListEvent.ListType.PICK_GROUP_MEMBERS); 369 break; 370 } 371 372 default: 373 throw new IllegalStateException("Invalid action code: " + mActionCode); 374 } 375 376 // Setting compatibility is no longer needed for PhoneNumberPickerFragment since that logic 377 // has been separated into LegacyPhoneNumberPickerFragment. But we still need to set 378 // compatibility for other fragments. 379 mListFragment.setLegacyCompatibilityMode(mRequest.isLegacyCompatibilityMode()); 380 mListFragment.setDirectoryResultLimit(DEFAULT_DIRECTORY_RESULT_LIMIT); 381 382 getFragmentManager().beginTransaction() 383 .replace(R.id.list_container, mListFragment) 384 .commitAllowingStateLoss(); 385 } 386 getPhoneNumberPickerFragment(ContactsRequest request)387 private PhoneNumberPickerFragment getPhoneNumberPickerFragment(ContactsRequest request) { 388 if (mRequest.isLegacyCompatibilityMode()) { 389 return new LegacyPhoneNumberPickerFragment(); 390 } else { 391 return new PhoneNumberPickerFragment(); 392 } 393 } 394 setupActionListener()395 public void setupActionListener() { 396 if (mListFragment instanceof ContactPickerFragment) { 397 ((ContactPickerFragment) mListFragment).setOnContactPickerActionListener( 398 new ContactPickerActionListener()); 399 } else if (mListFragment instanceof PhoneNumberPickerFragment) { 400 ((PhoneNumberPickerFragment) mListFragment).setOnPhoneNumberPickerActionListener( 401 new PhoneNumberPickerActionListener()); 402 } else if (mListFragment instanceof PostalAddressPickerFragment) { 403 ((PostalAddressPickerFragment) mListFragment).setOnPostalAddressPickerActionListener( 404 new PostalAddressPickerActionListener()); 405 } else if (mListFragment instanceof EmailAddressPickerFragment) { 406 ((EmailAddressPickerFragment) mListFragment).setOnEmailAddressPickerActionListener( 407 new EmailAddressPickerActionListener()); 408 } else if (mListFragment instanceof MultiSelectEmailAddressesListFragment) { 409 ((MultiSelectEmailAddressesListFragment) mListFragment).setCheckBoxListListener(this); 410 } else if (mListFragment instanceof MultiSelectPhoneNumbersListFragment) { 411 ((MultiSelectPhoneNumbersListFragment) mListFragment).setCheckBoxListListener(this); 412 } else if (mListFragment instanceof JoinContactListFragment) { 413 ((JoinContactListFragment) mListFragment).setOnContactPickerActionListener( 414 new JoinContactActionListener()); 415 } else if (mListFragment instanceof GroupMemberPickerFragment) { 416 ((GroupMemberPickerFragment) mListFragment).setListener( 417 new GroupMemberPickerListener()); 418 getMultiSelectListFragment().setCheckBoxListListener(this); 419 } else { 420 throw new IllegalStateException("Unsupported list fragment type: " + mListFragment); 421 } 422 } 423 getMultiSelectListFragment()424 private MultiSelectContactsListFragment getMultiSelectListFragment() { 425 if (mListFragment instanceof MultiSelectContactsListFragment) { 426 return (MultiSelectContactsListFragment) mListFragment; 427 } 428 return null; 429 } 430 431 @Override onAction(int action)432 public void onAction(int action) { 433 switch (action) { 434 case ActionBarAdapter.Listener.Action.START_SEARCH_MODE: 435 mIsSearchMode = true; 436 configureSearchMode(); 437 break; 438 case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY: 439 final String queryString = mActionBarAdapter.getQueryString(); 440 mListFragment.setQueryString(queryString, /* delaySelection */ false); 441 break; 442 case ActionBarAdapter.Listener.Action.START_SELECTION_MODE: 443 if (getMultiSelectListFragment() != null) { 444 getMultiSelectListFragment().displayCheckBoxes(true); 445 } 446 invalidateOptionsMenu(); 447 break; 448 case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE: 449 mListFragment.setQueryString("", /* delaySelection */ false); 450 mActionBarAdapter.setSearchMode(false); 451 if (getMultiSelectListFragment() != null) { 452 getMultiSelectListFragment().displayCheckBoxes(false); 453 } 454 invalidateOptionsMenu(); 455 break; 456 } 457 } 458 459 @Override onUpButtonPressed()460 public void onUpButtonPressed() { 461 onBackPressed(); 462 } 463 464 @Override onStartDisplayingCheckBoxes()465 public void onStartDisplayingCheckBoxes() { 466 mActionBarAdapter.setSelectionMode(true); 467 } 468 469 @Override onSelectedContactIdsChanged()470 public void onSelectedContactIdsChanged() { 471 if (mListFragment instanceof MultiSelectContactsListFragment) { 472 final int count = getMultiSelectListFragment().getSelectedContactIds().size(); 473 mActionBarAdapter.setSelectionCount(count); 474 updateAddContactsButton(count); 475 476 // Show or hide the multi select "Done" button 477 invalidateOptionsMenu(); 478 } 479 } 480 updateAddContactsButton(int count)481 private void updateAddContactsButton(int count) { 482 final TextView textView = (TextView) mActionBarAdapter.getSelectionContainer() 483 .findViewById(R.id.add_contacts); 484 if (count > 0) { 485 textView.setVisibility(View.VISIBLE); 486 textView.setAllCaps(true); 487 textView.setOnClickListener(new OnClickListener() { 488 @Override 489 public void onClick(View v) { 490 final long[] contactIds = 491 getMultiSelectListFragment().getSelectedContactIdsArray(); 492 returnSelectedContacts(contactIds); 493 } 494 }); 495 } else { 496 textView.setVisibility(View.GONE); 497 } 498 } 499 500 @Override onStopDisplayingCheckBoxes()501 public void onStopDisplayingCheckBoxes() { 502 mActionBarAdapter.setSelectionMode(false); 503 } 504 505 private final class ContactPickerActionListener implements OnContactPickerActionListener { 506 @Override onCreateNewContactAction()507 public void onCreateNewContactAction() { 508 startCreateNewContactActivity(); 509 } 510 511 @Override onEditContactAction(Uri contactLookupUri)512 public void onEditContactAction(Uri contactLookupUri) { 513 startActivityAndForwardResult(EditorIntents.createEditContactIntent( 514 ContactSelectionActivity.this, contactLookupUri, /* materialPalette =*/ null, 515 /* photoId =*/ -1)); 516 } 517 518 @Override onPickContactAction(Uri contactUri)519 public void onPickContactAction(Uri contactUri) { 520 returnPickerResult(contactUri); 521 } 522 523 @Override onShortcutIntentCreated(Intent intent)524 public void onShortcutIntentCreated(Intent intent) { 525 returnPickerResult(intent); 526 } 527 } 528 529 private final class PhoneNumberPickerActionListener implements 530 OnPhoneNumberPickerActionListener { 531 @Override onPickDataUri(Uri dataUri, boolean isVideoCall, int callInitiationType)532 public void onPickDataUri(Uri dataUri, boolean isVideoCall, int callInitiationType) { 533 returnPickerResult(dataUri); 534 } 535 536 @Override onPickPhoneNumber(String phoneNumber, boolean isVideoCall, int callInitiationType)537 public void onPickPhoneNumber(String phoneNumber, boolean isVideoCall, 538 int callInitiationType) { 539 Log.w(TAG, "Unsupported call."); 540 } 541 542 @Override onShortcutIntentCreated(Intent intent)543 public void onShortcutIntentCreated(Intent intent) { 544 returnPickerResult(intent); 545 } 546 547 @Override onHomeInActionBarSelected()548 public void onHomeInActionBarSelected() { 549 ContactSelectionActivity.this.onBackPressed(); 550 } 551 } 552 553 private final class JoinContactActionListener implements OnContactPickerActionListener { 554 @Override onPickContactAction(Uri contactUri)555 public void onPickContactAction(Uri contactUri) { 556 Intent intent = new Intent(null, contactUri); 557 setResult(RESULT_OK, intent); 558 finish(); 559 } 560 561 @Override onShortcutIntentCreated(Intent intent)562 public void onShortcutIntentCreated(Intent intent) { 563 } 564 565 @Override onCreateNewContactAction()566 public void onCreateNewContactAction() { 567 } 568 569 @Override onEditContactAction(Uri contactLookupUri)570 public void onEditContactAction(Uri contactLookupUri) { 571 } 572 } 573 574 private final class GroupMemberPickerListener implements GroupMemberPickerFragment.Listener { 575 576 @Override onGroupMemberClicked(long contactId)577 public void onGroupMemberClicked(long contactId) { 578 final Intent intent = new Intent(); 579 intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, contactId); 580 returnPickerResult(intent); 581 } 582 583 @Override onSelectGroupMembers()584 public void onSelectGroupMembers() { 585 mActionBarAdapter.setSelectionMode(true); 586 } 587 } 588 returnSelectedContacts(long[] contactIds)589 private void returnSelectedContacts(long[] contactIds) { 590 final Intent intent = new Intent(); 591 intent.putExtra(UiIntentActions.TARGET_CONTACT_IDS_EXTRA_KEY, contactIds); 592 returnPickerResult(intent); 593 } 594 595 private final class PostalAddressPickerActionListener implements 596 OnPostalAddressPickerActionListener { 597 @Override onPickPostalAddressAction(Uri dataUri)598 public void onPickPostalAddressAction(Uri dataUri) { 599 returnPickerResult(dataUri); 600 } 601 } 602 603 private final class EmailAddressPickerActionListener implements 604 OnEmailAddressPickerActionListener { 605 @Override onPickEmailAddressAction(Uri dataUri)606 public void onPickEmailAddressAction(Uri dataUri) { 607 returnPickerResult(dataUri); 608 } 609 } 610 startActivityAndForwardResult(final Intent intent)611 public void startActivityAndForwardResult(final Intent intent) { 612 intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); 613 614 // Forward extras to the new activity 615 Bundle extras = getIntent().getExtras(); 616 if (extras != null) { 617 intent.putExtras(extras); 618 } 619 try { 620 ImplicitIntentsUtil.startActivityInApp(ContactSelectionActivity.this, intent); 621 } catch (ActivityNotFoundException e) { 622 Log.e(TAG, "startActivity() failed: " + e); 623 Toast.makeText(ContactSelectionActivity.this, R.string.missing_app, 624 Toast.LENGTH_SHORT).show(); 625 } 626 finish(); 627 } 628 629 @Override onFocusChange(View view, boolean hasFocus)630 public void onFocusChange(View view, boolean hasFocus) { 631 if (view.getId() == R.id.search_view) { 632 if (hasFocus) { 633 mActionBarAdapter.setFocusOnSearchView(); 634 } 635 } 636 } 637 returnPickerResult(Uri data)638 public void returnPickerResult(Uri data) { 639 Intent intent = new Intent(); 640 intent.setData(data); 641 returnPickerResult(intent); 642 } 643 returnPickerResult(Intent intent)644 public void returnPickerResult(Intent intent) { 645 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 646 setResult(RESULT_OK, intent); 647 finish(); 648 } 649 650 @Override onClick(View view)651 public void onClick(View view) { 652 if (view.getId() == R.id.floating_action_button) { 653 startCreateNewContactActivity(); 654 } 655 } 656 getTargetContactId()657 private long getTargetContactId() { 658 Intent intent = getIntent(); 659 final long targetContactId = intent.getLongExtra( 660 UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1); 661 if (targetContactId == -1) { 662 Log.e(TAG, "Intent " + intent.getAction() + " is missing required extra: " 663 + UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY); 664 setResult(RESULT_CANCELED); 665 finish(); 666 return -1; 667 } 668 return targetContactId; 669 } 670 startCreateNewContactActivity()671 private void startCreateNewContactActivity() { 672 Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); 673 intent.putExtra(ContactEditorActivity. 674 INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true); 675 startActivityAndForwardResult(intent); 676 } 677 678 @Override onCreateOptionsMenu(Menu menu)679 public boolean onCreateOptionsMenu(Menu menu) { 680 super.onCreateOptionsMenu(menu); 681 682 final MenuInflater inflater = getMenuInflater(); 683 inflater.inflate(R.menu.search_menu, menu); 684 685 final MenuItem searchItem = menu.findItem(R.id.menu_search); 686 searchItem.setVisible(!mIsSearchMode && mIsSearchSupported); 687 688 final Drawable searchIcon = searchItem.getIcon(); 689 if (searchIcon != null) { 690 searchIcon.mutate().setColorFilter(ContextCompat.getColor(this, 691 R.color.actionbar_icon_color), PorterDuff.Mode.SRC_ATOP); 692 } 693 return true; 694 } 695 696 @Override onBackPressed()697 public void onBackPressed() { 698 if (!isSafeToCommitTransactions()) { 699 return; 700 } 701 702 if (isSelectionMode()) { 703 mActionBarAdapter.setSelectionMode(false); 704 if (getMultiSelectListFragment() != null) { 705 getMultiSelectListFragment().displayCheckBoxes(false); 706 } 707 } else if (mIsSearchMode) { 708 mIsSearchMode = false; 709 configureSearchMode(); 710 } else { 711 super.onBackPressed(); 712 } 713 } 714 } 715