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