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