QuickContactActivity.java revision 793e73c859ed839c28cc37d80d62bde0a361c78a
1edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/* 2edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Copyright (C) 2009 The Android Open Source Project 3edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 4edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * you may not use this file except in compliance with the License. 6edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * You may obtain a copy of the License at 7edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 8edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 10edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Unless required by applicable law or agreed to in writing, software 11edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * See the License for the specific language governing permissions and 14edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * limitations under the License. 15edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 16edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 17edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannpackage com.android.contacts.quickcontact; 18edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 19ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulosimport android.accounts.Account; 208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.animation.ArgbEvaluator; 21b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport android.animation.ObjectAnimator; 22edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.app.Activity; 23d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.app.Fragment; 24cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 25eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.app.SearchManager; 26752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.content.ActivityNotFoundException; 27edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.ContentUris; 28ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulosimport android.content.ContentValues; 296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwellimport android.content.Context; 30edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Intent; 31cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.content.Loader; 32dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.content.pm.PackageManager; 33dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.content.pm.ResolveInfo; 3423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulosimport android.content.res.Resources; 3531b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Bitmap; 3695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwellimport android.graphics.BitmapFactory; 378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.graphics.Color; 38eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.graphics.PorterDuff; 39eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.graphics.PorterDuffColorFilter; 4031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.BitmapDrawable; 418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.graphics.drawable.ColorDrawable; 4231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.Drawable; 43eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.net.ParseException; 44edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.net.Uri; 45eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.net.WebAddress; 4631b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.os.AsyncTask; 47edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.os.Bundle; 488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.os.Trace; 49eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.CalendarContract; 50752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.provider.ContactsContract; 51edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 52eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Event; 53eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 54eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Identity; 55eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Im; 56eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Nickname; 57eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Note; 58eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Organization; 59edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 60eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Relation; 61edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 62edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 63edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Website; 64752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.provider.ContactsContract.Contacts; 6560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulosimport android.provider.ContactsContract.Data; 66ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulosimport android.provider.ContactsContract.Directory; 67eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.DisplayNameSources; 68ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulosimport android.provider.ContactsContract.DataUsageFeedback; 69ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulosimport android.provider.ContactsContract.Intents; 70edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.QuickContact; 71edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.RawContacts; 7231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.support.v7.graphics.Palette; 731cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shraunerimport android.telecomm.PhoneAccount; 7470e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chenimport android.telecomm.TelecommManager; 75edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils; 76edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log; 772a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu; 782a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo; 79d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.Menu; 80d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.MenuInflater; 81eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.view.MenuItem; 82f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chenimport android.view.MotionEvent; 83edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View; 84edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener; 852a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.View.OnCreateContextMenuListener; 8610d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager; 87edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast; 88d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.widget.Toolbar; 89edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 9072b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService; 91d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.ContactsActivity; 922d150da246632b1649999cfabed776133b097775Brian Attwellimport com.android.contacts.NfcHandler; 93e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 94eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.CallUtil; 952a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.common.ClipboardUtils; 96eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.Collapser; 97eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.ContactsUtils; 98d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.editor.SelectAccountDialogFragment; 9970e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chenimport com.android.contacts.common.interactions.TouchPointManager; 10031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable; 101752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder; 102752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener; 1030d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager; 104cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact; 105cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader; 106cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact; 107428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType; 108d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.model.account.AccountWithDataSet; 109cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem; 110428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 111cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem; 112eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.EventDataItem; 113cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem; 114eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NicknameDataItem; 115eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NoteDataItem; 116eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.OrganizationDataItem; 117b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.common.model.dataitem.PhoneDataItem; 118eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.RelationDataItem; 119eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.SipAddressDataItem; 120eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredNameDataItem; 121eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredPostalDataItem; 122eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.WebsiteDataItem; 123eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.util.DateUtils; 124faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils; 125faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette; 126d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwellimport com.android.contacts.common.util.ViewUtil; 127333091ae754ddfc25714c14b9b89534be24379f9Paul Soulosimport com.android.contacts.detail.ContactDisplayUtils; 128899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport com.android.contacts.interactions.CalendarInteractionsLoader; 129ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.interactions.CallLogInteractionsLoader; 1308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport com.android.contacts.interactions.ContactDeletionInteraction; 131b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.ContactInteraction; 132b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.SmsInteractionsLoader; 1332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry; 1342a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo; 1352ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryTag; 136e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwellimport com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener; 137e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter; 138eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.PhoneCapabilityTester; 139b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils; 140eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.StructuredPostalUtils; 141b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller; 142b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener; 14302eaf11669d25fd885606b3b0700358323532cddBrian Attwellimport com.android.contacts.widget.QuickContactImageView; 14402eaf11669d25fd885606b3b0700358323532cddBrian Attwell 145e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions; 146e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 147e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 1482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList; 149899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport java.util.Arrays; 150eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Calendar; 151b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Collections; 152b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Comparator; 153eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Date; 154edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap; 155edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List; 156b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Map; 157edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 158edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/** 159edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads 160edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around 161edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}. 162edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 163d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellpublic class QuickContactActivity extends ContactsActivity { 1648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell /** 1668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * QuickContacts immediately takes up the full screen. All possible information is shown. 1678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * This value for {@link android.provider.ContactsContract.QuickContact#EXTRA_MODE} 1688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * should only be used by the Contacts app. 1698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell */ 1708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public static final int MODE_FULLY_EXPANDED = 4; 1718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 172edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String TAG = "QuickContact"; 173edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1749b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final String KEY_THEME_COLOR = "theme_color"; 1759b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 1769b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150; 1778a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1; 178bfa9442453c1d86e11e56702f9b8ef0e8e0da0b1Brian Attwell private static final int SCRIM_COLOR = Color.argb(0xC8, 0, 0, 0); 179ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos private static final int REQUEST_CODE_CONTACT_SELECTION_ACTIVITY = 2; 180ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms"; 181dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 182752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** This is the Intent action to install a shortcut in the launcher. */ 183752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private static final String ACTION_INSTALL_SHORTCUT = 184752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell "com.android.launcher.action.INSTALL_SHORTCUT"; 185edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 186edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @SuppressWarnings("deprecation") 187edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY; 188edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 189e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String MIMETYPE_GPLUS_PROFILE = 190e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos "vnd.android.cursor.item/vnd.googleplus.profile"; 191e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String INTENT_DATA_GPLUS_PROFILE_ADD_TO_CIRCLE = "Add to circle"; 192e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String MIMETYPE_HANGOUTS = 193e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos "vnd.android.cursor.item/vnd.googleplus.profile.comm"; 194e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String INTENT_DATA_HANGOUTS_VIDEO = "Start video call"; 19548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private static final String CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY = 19648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos "com.android.contacts.quickcontact.QuickContactActivity"; 197e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 19863176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell /** 19963176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell * The URI used to load the the Contact. Once the contact is loaded, use Contact#getLookupUri() 20063176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell * instead of referencing this URI. 20163176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell */ 202edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private Uri mLookupUri; 203edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private String[] mExcludeMimes; 2048a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mExtraMode; 2058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mStatusBarColor; 2068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private boolean mHasAlreadyBeenOpened; 20797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private boolean mOnlyOnePhoneNumber; 20897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private boolean mOnlyOneEmail; 209edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 21002eaf11669d25fd885606b3b0700358323532cddBrian Attwell private QuickContactImageView mPhotoView; 211eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private ExpandingEntryCardView mContactCard; 2126095369885edcca566a812b551886e29c7ff8039Brian Attwell private ExpandingEntryCardView mNoContactDetailsCard; 213b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private ExpandingEntryCardView mRecentCard; 214eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private ExpandingEntryCardView mAboutCard; 215b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private MultiShrinkScroller mScroller; 216d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private SelectAccountDialogFragmentListener mSelectAccountFragmentListener; 2176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private AsyncTask<Void, Void, Cp2DataCardModel> mEntriesAndActionsTask; 21830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell private AsyncTask<Void, Void, Void> mRecentDataTask; 2196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 2206bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * The last copy of Cp2DataCardModel that was passed to {@link #populateContactAndAboutCard}. 2216bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 2226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private Cp2DataCardModel mCachedCp2DataCardModel; 223f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell /** 224f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * This scrim's opacity is controlled in two different ways. 1) Before the initial entrance 225f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * animation finishes, the opacity is animated by a value animator. This is designed to 226f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * distract the user from the length of the initial loading time. 2) After the initial 227f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * entrance animation, the opacity is directly related to scroll position. 228f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell */ 2299b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private ColorDrawable mWindowScrim; 230f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell private boolean mIsEntranceAnimationFinished; 231a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell private MaterialColorMapUtils mMaterialColorMapUtils; 2328477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell private boolean mIsExitAnimationInProgress; 2338571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell private boolean mHasComputedThemeColor; 234edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 235a42ef76251778161d27bc07db214b8c81720e476Paul Soulos /** 236a42ef76251778161d27bc07db214b8c81720e476Paul Soulos * Used to stop the ExpandingEntry cards from adjusting between an entry click and the intent 237a42ef76251778161d27bc07db214b8c81720e476Paul Soulos * being launched. 238a42ef76251778161d27bc07db214b8c81720e476Paul Soulos */ 239a42ef76251778161d27bc07db214b8c81720e476Paul Soulos private boolean mHasIntentLaunched; 240a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 2416cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee private Contact mContactData; 2429815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann private ContactLoader mContactLoader; 2439b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private PorterDuffColorFilter mColorFilter; 2449815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann 2459758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter(); 2469758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus 247edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 248cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * {@link #LEADING_MIMETYPES} is used to sort MIME-types. 249edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 250edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog, 251edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * in the order specified here.</p> 252edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 253edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> LEADING_MIMETYPES = Lists.newArrayList( 254cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE, 255405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos StructuredPostal.CONTENT_ITEM_TYPE); 256edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 257a153dba33c2152332c5706178a367f52b0550723Paul Soulos private static final List<String> SORTED_ABOUT_CARD_MIMETYPES = Lists.newArrayList( 258a153dba33c2152332c5706178a367f52b0550723Paul Soulos Nickname.CONTENT_ITEM_TYPE, 259a153dba33c2152332c5706178a367f52b0550723Paul Soulos // Phonetic name is inserted after nickname if it is available. 260a153dba33c2152332c5706178a367f52b0550723Paul Soulos // No mimetype for phonetic name exists. 261a153dba33c2152332c5706178a367f52b0550723Paul Soulos Website.CONTENT_ITEM_TYPE, 262a153dba33c2152332c5706178a367f52b0550723Paul Soulos Organization.CONTENT_ITEM_TYPE, 263a153dba33c2152332c5706178a367f52b0550723Paul Soulos Event.CONTENT_ITEM_TYPE, 264a153dba33c2152332c5706178a367f52b0550723Paul Soulos Relation.CONTENT_ITEM_TYPE, 265a153dba33c2152332c5706178a367f52b0550723Paul Soulos Im.CONTENT_ITEM_TYPE, 266a153dba33c2152332c5706178a367f52b0550723Paul Soulos GroupMembership.CONTENT_ITEM_TYPE, 267a153dba33c2152332c5706178a367f52b0550723Paul Soulos Identity.CONTENT_ITEM_TYPE, 268a153dba33c2152332c5706178a367f52b0550723Paul Soulos Note.CONTENT_ITEM_TYPE); 269eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 270b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background contact loader */ 271b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_CONTACT_ID = 0; 272b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 273ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_PHONES = 274ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_PHONES"; 275ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 276b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background Sms Loader */ 277b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_SMS_ID = 1; 278b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int MAX_SMS_RETRIEVE = 3; 279ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 280ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the back Calendar Loader */ 281899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int LOADER_CALENDAR_ID = 2; 282ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_EMAILS = 283ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_EMAILS"; 284899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_PAST_CALENDAR_RETRIEVE = 3; 285899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_FUTURE_CALENDAR_RETRIEVE = 3; 286899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 28740d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos 1L * 24L * 60L * 60L * 1000L /* 1 day */; 288899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 28940d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos 7L * 24L * 60L * 60L * 1000L /* 7 days */; 290899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 291ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the background Call Log Loader */ 292ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int LOADER_CALL_LOG_ID = 3; 293ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int MAX_CALL_LOG_RETRIEVE = 3; 2946095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int MIN_NUM_CONTACT_ENTRIES_SHOWN = 3; 2956095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3; 2966095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int CARD_ENTRY_ID_EDIT_CONTACT = -2; 297ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 298ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 299ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int[] mRecentLoaderIds = new int[]{ 300ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_SMS_ID, 301ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALENDAR_ID, 302ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID}; 303a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos private Map<Integer, List<ContactInteraction>> mRecentLoaderResults = new HashMap<>(); 304b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 305d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment"; 3066cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 3072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos final OnClickListener mEntryClickHandler = new OnClickListener() { 3082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 3092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void onClick(View v) { 3102ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final Object entryTagObject = v.getTag(); 3112ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos if (entryTagObject == null || !(entryTagObject instanceof EntryTag)) { 3122ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos Log.w(TAG, "EntryTag was not used correctly"); 3136095369885edcca566a812b551886e29c7ff8039Brian Attwell return; 3146095369885edcca566a812b551886e29c7ff8039Brian Attwell } 3152ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final EntryTag entryTag = (EntryTag) entryTagObject; 3162ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final Intent intent = entryTag.getIntent(); 3172ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final int dataId = entryTag.getId(); 3182ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 3192ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) { 3202ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos editContact(); 3212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return; 3222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 323ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 324ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // Default to USAGE_TYPE_CALL. Usage is summed among all types for sorting each data id 325ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // so the exact usage type is not necessary in all cases 326ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos String usageType = DataUsageFeedback.USAGE_TYPE_CALL; 327ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 32820bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos final Uri intentUri = intent.getData(); 32920bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos if ((intentUri != null && intentUri.getScheme() != null && 3301cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner intentUri.getScheme().equals(ContactsUtils.SCHEME_SMSTO)) || 331ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos (intent.getType() != null && intent.getType().equals(MIMETYPE_SMS))) { 332ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos usageType = DataUsageFeedback.USAGE_TYPE_SHORT_TEXT; 333ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 334ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 335ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // Data IDs start at 1 so anything less is invalid 336ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos if (dataId > 0) { 33720bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos final Uri dataUsageUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 338ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .appendPath(String.valueOf(dataId)) 339ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, usageType) 340ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .build(); 341ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos final boolean successful = getContentResolver().update( 34220bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos dataUsageUri, new ContentValues(), null, null) > 0; 343ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos if (!successful) { 344ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos Log.w(TAG, "DataUsageFeedback increment failed"); 345ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 346ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } else { 347ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos Log.w(TAG, "Invalid Data ID"); 348ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 349ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 35070e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen // Pass the touch point through the intent for use in the InCallUI 35170e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen if (Intent.ACTION_CALL.equals(intent.getAction())) { 3521f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen if (TouchPointManager.getInstance().hasValidPoint()) { 35370e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen Bundle extras = new Bundle(); 3541f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen extras.putParcelable(TouchPointManager.TOUCH_POINT, 3551f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen TouchPointManager.getInstance().getPoint()); 35670e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen intent.putExtra(TelecommManager.EXTRA_OUTGOING_CALL_EXTRAS, extras); 35770e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen } 35870e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen } 35970e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen 360793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 361793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos 362a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 363ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos startActivity(intent); 3642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }; 3662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 367e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell final ExpandingEntryCardViewListener mExpandingEntryCardViewListener 368e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell = new ExpandingEntryCardViewListener() { 369e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell @Override 370e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell public void onCollapse(int heightDelta) { 371e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell mScroller.prepareForShrinkingScrollChild(heightDelta); 372e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell } 3730cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 3740cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 3750cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onExpand(int heightDelta) { 3760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller.prepareForExpandingScrollChild(); 3770cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 378e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell }; 379e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell 38097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private interface ContextMenuIds { 38197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int COPY_TEXT = 0; 38297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int CLEAR_DEFAULT = 1; 38397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int SET_DEFAULT = 2; 38497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 38597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 3862a4207fb39330e840436215c896cde911489e111Paul Soulos private final OnCreateContextMenuListener mEntryContextMenuListener = 3872a4207fb39330e840436215c896cde911489e111Paul Soulos new OnCreateContextMenuListener() { 3882a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 3892a4207fb39330e840436215c896cde911489e111Paul Soulos public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 3902a4207fb39330e840436215c896cde911489e111Paul Soulos if (menuInfo == null) { 3912a4207fb39330e840436215c896cde911489e111Paul Soulos return; 3922a4207fb39330e840436215c896cde911489e111Paul Soulos } 39397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo; 3942a4207fb39330e840436215c896cde911489e111Paul Soulos menu.setHeaderTitle(info.getCopyText()); 39597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.COPY_TEXT, 39697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.copy_text)); 39797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 39897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Don't allow setting or clearing of defaults for non-editable contacts 39997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (!isContactEditable()) { 40097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return; 40197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 40297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 40397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final String selectedMimeType = info.getMimeType(); 40497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 40597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Defaults to true will only enable the detail to be copied to the clipboard. 40697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos boolean onlyOneOfMimeType = true; 40797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 40897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Only allow primary support for Phone and Email content types 40997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) { 41097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos onlyOneOfMimeType = mOnlyOnePhoneNumber; 41197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) { 41297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos onlyOneOfMimeType = mOnlyOneEmail; 41397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 41497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 41597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Checking for previously set default 41697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (info.isSuperPrimary()) { 41797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT, 41897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.clear_default)); 41997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } else if (!onlyOneOfMimeType) { 42097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT, 42197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.set_default)); 42297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 4232a4207fb39330e840436215c896cde911489e111Paul Soulos } 4242a4207fb39330e840436215c896cde911489e111Paul Soulos }; 4252a4207fb39330e840436215c896cde911489e111Paul Soulos 4262a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 4272a4207fb39330e840436215c896cde911489e111Paul Soulos public boolean onContextItemSelected(MenuItem item) { 4282a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo menuInfo; 4292a4207fb39330e840436215c896cde911489e111Paul Soulos try { 4302a4207fb39330e840436215c896cde911489e111Paul Soulos menuInfo = (EntryContextMenuInfo) item.getMenuInfo(); 4312a4207fb39330e840436215c896cde911489e111Paul Soulos } catch (ClassCastException e) { 4322a4207fb39330e840436215c896cde911489e111Paul Soulos Log.e(TAG, "bad menuInfo", e); 4332a4207fb39330e840436215c896cde911489e111Paul Soulos return false; 4342a4207fb39330e840436215c896cde911489e111Paul Soulos } 4352a4207fb39330e840436215c896cde911489e111Paul Soulos 43697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos switch (item.getItemId()) { 43797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.COPY_TEXT: 43897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(), 43997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos true); 44097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 44197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.SET_DEFAULT: 44297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final Intent setIntent = ContactSaveService.createSetSuperPrimaryIntent(this, 44397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menuInfo.getId()); 44497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos this.startService(setIntent); 44597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 44697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.CLEAR_DEFAULT: 44797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final Intent clearIntent = ContactSaveService.createClearPrimaryIntent(this, 44897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menuInfo.getId()); 44997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos this.startService(clearIntent); 45097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 45197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos default: 45297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos throw new IllegalArgumentException("Unknown menu option " + item.getItemId()); 45397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 4542a4207fb39330e840436215c896cde911489e111Paul Soulos } 4552a4207fb39330e840436215c896cde911489e111Paul Soulos 456d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 457d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Headless fragment used to handle account selection callbacks invoked from 458d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * {@link DirectoryContactUtil}. 459d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 460d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public static class SelectAccountDialogFragmentListener extends Fragment 461d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell implements SelectAccountDialogFragment.Listener { 462d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 463d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private QuickContactActivity mQuickContactActivity; 464d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 465d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public SelectAccountDialogFragmentListener() {} 466d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 467d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 468d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) { 469d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell DirectoryContactUtil.createCopy(mQuickContactActivity.mContactData.getContentValues(), 470d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell account, mQuickContactActivity); 471d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 472d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 473d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 474d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountSelectorCancelled() {} 475d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 476d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 477d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Set the parent activity. Since rotation can cause this fragment to be used across 478d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * more than one activity instance, we need to explicitly set this value instead 479d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * of making this class non-static. 480d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 481d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void setQuickContactActivity(QuickContactActivity quickContactActivity) { 482d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mQuickContactActivity = quickContactActivity; 483d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 484d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 485d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 486b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final MultiShrinkScrollerListener mMultiShrinkScrollerListener 487b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell = new MultiShrinkScrollerListener() { 488b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 489b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onScrolledOffBottom() { 490f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell finish(); 491b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 4928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 4938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 4948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onEnterFullscreen() { 4958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 4968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 4978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 4988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 4998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onExitFullscreen() { 5008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 5018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5028477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 5038477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 5048477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell public void onStartScrollOffBottom() { 5058477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsExitAnimationInProgress = true; 5068477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 5078477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 5088477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 509f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void onEntranceAnimationDone() { 510f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = true; 511f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 512f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 513f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell @Override 514f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void onTransparentViewHeightChange(float ratio) { 515f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell if (mIsEntranceAnimationFinished) { 516f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mWindowScrim.setAlpha((int) (0xFF * ratio)); 5178477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 5188477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 519b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell }; 520b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 521eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 522eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 523eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Data items are compared to the same mimetype based off of three qualities: 524eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 1. Super primary 525eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 2. Primary 526eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 3. Times used 527eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 528eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final Comparator<DataItem> mWithinMimeTypeDataItemComparator = 529eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos new Comparator<DataItem>() { 530eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos @Override 531eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public int compare(DataItem lhs, DataItem rhs) { 532eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!lhs.getMimeType().equals(rhs.getMimeType())) { 533eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Log.wtf(TAG, "Comparing DataItems with different mimetypes lhs.getMimeType(): " + 534eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getMimeType() + " rhs.getMimeType(): " + rhs.getMimeType()); 535eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 0; 536eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 537eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 538eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lhs.isSuperPrimary()) { 539eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 540eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (rhs.isSuperPrimary()) { 541eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 542eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (lhs.isPrimary() && !rhs.isPrimary()) { 543eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 544eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (!lhs.isPrimary() && rhs.isPrimary()) { 545eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 546eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 547eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int lhsTimesUsed = 548eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 549eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int rhsTimesUsed = 550eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 551eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 552eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return rhsTimesUsed - lhsTimesUsed; 553eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 554eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 555eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos }; 556eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 557cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos /** 558cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * Sorts among different mimetypes based off: 559cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 1. Times used 560cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 2. Last time used 561cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 3. Statically defined 562cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos */ 563eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final Comparator<List<DataItem>> mAmongstMimeTypeDataItemComparator = 564eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos new Comparator<List<DataItem>> () { 565eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos @Override 566eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public int compare(List<DataItem> lhsList, List<DataItem> rhsList) { 567eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataItem lhs = lhsList.get(0); 568eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataItem rhs = rhsList.get(0); 569eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int lhsTimesUsed = lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 570eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int rhsTimesUsed = rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 571eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int timesUsedDifference = rhsTimesUsed - lhsTimesUsed; 572eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (timesUsedDifference != 0) { 573eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return timesUsedDifference; 574eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 575eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 576eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long lhsLastTimeUsed = 577eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getLastTimeUsed() == null ? 0 : lhs.getLastTimeUsed(); 578eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long rhsLastTimeUsed = 579eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos rhs.getLastTimeUsed() == null ? 0 : rhs.getLastTimeUsed(); 580eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long lastTimeUsedDifference = rhsLastTimeUsed - lhsLastTimeUsed; 581eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lastTimeUsedDifference > 0) { 582eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 583eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (lastTimeUsedDifference < 0) { 584eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 585eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 586eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 587eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Times used and last time used are the same. Resort to statically defined. 588eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String lhsMimeType = lhs.getMimeType(); 589eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String rhsMimeType = rhs.getMimeType(); 590eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (String mimeType : LEADING_MIMETYPES) { 591eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lhsMimeType.equals(mimeType)) { 592eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 593eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (rhsMimeType.equals(mimeType)) { 594eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 595eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 596eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 597eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 0; 598eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 599eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos }; 600eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 601edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @Override 602f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen public boolean dispatchTouchEvent(MotionEvent ev) { 603f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen if (ev.getAction() == MotionEvent.ACTION_DOWN) { 604f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY()); 605f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen } 606f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen return super.dispatchTouchEvent(ev); 607f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen } 608f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen 609f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen @Override 6108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onCreate(Bundle savedInstanceState) { 6118a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onCreate()"); 6128a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onCreate(savedInstanceState); 613edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getWindow().setStatusBarColor(Color.TRANSPARENT); 6152426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann 616d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(getIntent()); 617dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 61810d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa // Show QuickContact in front of soft input 61910d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 62010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 62110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa 622edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann setContentView(R.layout.quickcontact_activity); 623edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 624a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell mMaterialColorMapUtils = new MaterialColorMapUtils(getResources()); 625a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell 6260cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller); 6270cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 628eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card); 6296095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card); 630b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card); 631eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card); 632edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6336095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setOnClickListener(mEntryClickHandler); 634eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setOnClickListener(mEntryClickHandler); 635eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setExpandButtonText( 63623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos getResources().getString(R.string.expanding_entry_card_view_see_all)); 6372a4207fb39330e840436215c896cde911489e111Paul Soulos mContactCard.setOnCreateContextMenuListener(mEntryContextMenuListener); 638b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 639b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setOnClickListener(mEntryClickHandler); 640b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setTitle(getResources().getString(R.string.recent_card_title)); 641edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 642eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mAboutCard.setOnClickListener(mEntryClickHandler); 6432a4207fb39330e840436215c896cde911489e111Paul Soulos mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener); 644eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 64502eaf11669d25fd885606b3b0700358323532cddBrian Attwell mPhotoView = (QuickContactImageView) findViewById(R.id.photo); 64663176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell final View transparentView = findViewById(R.id.transparent_view); 6470d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell if (mScroller != null) { 64863176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell transparentView.setOnClickListener(new OnClickListener() { 6490d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell @Override 6500d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell public void onClick(View v) { 6510d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell mScroller.scrollOffBottom(); 6520d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 6530d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell }); 6540d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 655edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 656d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell // Allow a shadow to be shown under the toolbar. 657d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources()); 658d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell 659d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 660d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell setActionBar(toolbar); 6619b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getActionBar().setTitle(null); 6629b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // Put a TextView with a known resource id into the ActionBar. This allows us to easily 6639b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // find the correct TextView location & size later. 6649b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell toolbar.addView(getLayoutInflater().inflate(R.layout.quickcontact_title_placeholder, null)); 6656219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee 6668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = savedInstanceState != null; 667f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = mHasAlreadyBeenOpened; 6689b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mWindowScrim = new ColorDrawable(SCRIM_COLOR); 669f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mWindowScrim.setAlpha(0); 6709b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getWindow().setBackgroundDrawable(mWindowScrim); 671edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 672c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell mScroller.initialize(mMultiShrinkScrollerListener, mExtraMode == MODE_FULLY_EXPANDED); 673ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // mScroller needs to perform asynchronous measurements after initalize(), therefore 674ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // we can't mark this as GONE. 675ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.INVISIBLE); 6768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 6779b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell setHeaderNameText(R.string.missing_name); 6789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 679d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener= (SelectAccountDialogFragmentListener) getFragmentManager() 680d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .findFragmentByTag(FRAGMENT_TAG_SELECT_ACCOUNT); 681d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mSelectAccountFragmentListener == null) { 682d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener = new SelectAccountDialogFragmentListener(); 683d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell getFragmentManager().beginTransaction().add(0, mSelectAccountFragmentListener, 684d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell FRAGMENT_TAG_SELECT_ACCOUNT).commit(); 685d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setRetainInstance(true); 686d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 687d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setQuickContactActivity(this); 68823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 689f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ true, 690f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell new Runnable() { 691f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell @Override 692f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void run() { 693f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell if (!mHasAlreadyBeenOpened) { 694f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell // The initial scrim opacity must match the scrim opacity that would be 695f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell // achieved by scrolling to the starting position. 696f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final float alphaRatio = mExtraMode == MODE_FULLY_EXPANDED ? 697f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 1 : mScroller.getStartingTransparentHeightRatio(); 698f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final int duration = getResources().getInteger( 699f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell android.R.integer.config_shortAnimTime); 700f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final int desiredAlpha = (int) (0xFF * alphaRatio); 701f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell ObjectAnimator o = ObjectAnimator.ofInt(mWindowScrim, "alpha", 0, 702f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell desiredAlpha).setDuration(duration); 703f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 704f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell o.start(); 705f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 706f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 707f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell }); 708f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 7099b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (savedInstanceState != null) { 7109b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell final int color = savedInstanceState.getInt(KEY_THEME_COLOR, 0); 711ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 712ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell new Runnable() { 713ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell @Override 714ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell public void run() { 715ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for the pre draw before setting the initial scroll 716ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // value. Prior to pre draw all scroll values are invalid. 717ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (mHasAlreadyBeenOpened) { 718ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.VISIBLE); 719ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setScroll(mScroller.getScrollNeededToBeFullScreen()); 720ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 721ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for pre draw for setting the theme color. Setting the 722ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // header tint before the MultiShrinkScroller has been measured will 723ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // cause incorrect tinting calculations. 724ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (color != 0) { 725a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell setThemeColor(mMaterialColorMapUtils 726a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell .calculatePrimaryAndSecondaryColor(color)); 7279b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 728ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 729ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell }); 7309b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7319b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 7328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 7338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 7348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 735405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos @Override 736405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos protected void onActivityResult(int requestCode, int resultCode, Intent data) { 7378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (requestCode == REQUEST_CODE_CONTACT_EDITOR_ACTIVITY && 7388a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) { 7398a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // The contact that we were showing has been deleted. 7408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell finish(); 741ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } else if (requestCode == REQUEST_CODE_CONTACT_SELECTION_ACTIVITY && 742ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos resultCode != RESULT_CANCELED) { 743ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos processIntent(data); 744b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 7458a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 746dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 7478a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 7488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onNewIntent(Intent intent) { 7498a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onNewIntent(intent); 7508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 751f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = true; 7528571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = false; 753d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(intent); 754d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 755d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 7569b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell @Override 7579b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell public void onSaveInstanceState(Bundle savedInstanceState) { 7589b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell super.onSaveInstanceState(savedInstanceState); 7599b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mColorFilter != null) { 7609b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell savedInstanceState.putInt(KEY_THEME_COLOR, mColorFilter.getColor()); 7619b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7629b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7639b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 764d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void processIntent(Intent intent) { 765d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell Uri lookupUri = intent.getData(); 766d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 767d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Check to see whether it comes from the old version. 768d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) { 769d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final long rawContactId = ContentUris.parseId(lookupUri); 770d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell lookupUri = RawContacts.getContactLookupUri(getContentResolver(), 771d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId)); 772d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 773d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE, 774d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell QuickContact.MODE_LARGE); 775d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Uri oldLookupUri = mLookupUri; 776d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 777d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri"); 778d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES); 779d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (oldLookupUri == null) { 780d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactLoader = (ContactLoader) getLoaderManager().initLoader( 781d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 782d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (oldLookupUri != mLookupUri) { 783d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // After copying a directory contact, the contact URI changes. Therefore, 784d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // we need to restart the loader and reload the new contact. 785899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos for (int interactionLoaderId : mRecentLoaderIds) { 786899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos getLoaderManager().destroyLoader(interactionLoaderId); 787899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos } 788405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos mContactLoader = (ContactLoader) getLoaderManager().restartLoader( 789405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 790d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 7912d150da246632b1649999cfabed776133b097775Brian Attwell 7922d150da246632b1649999cfabed776133b097775Brian Attwell NfcHandler.register(this, mLookupUri); 7932426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann } 794edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 795b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private void runEntranceAnimation() { 7968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mHasAlreadyBeenOpened) { 7978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 7988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 7998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 800c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell mScroller.scrollUpForEntranceAnimation(mExtraMode != MODE_FULLY_EXPANDED); 801b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 802b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 80381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 804d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void setHeaderNameText(int resId) { 8059b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 806f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(getText(resId) == null ? null : getText(resId).toString()); 8079b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 80881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 80981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 81081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 811f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell private void setHeaderNameText(String value) { 812d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (!TextUtils.isEmpty(value)) { 8139b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 814f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(value); 8159b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 81681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 81781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 81881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 81981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** 820edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Check if the given MIME-type appears in the list of excluded MIME-types 821edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * that the most-recent caller requested. 822edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 823edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private boolean isMimeExcluded(String mimeType) { 824edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (mExcludeMimes == null) return false; 825edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String excludedMime : mExcludeMimes) { 826edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (TextUtils.equals(excludedMime, mimeType)) { 827edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 828edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 829edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 830edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 831edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 832edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 833edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 834cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann * Handle the result from the ContactLoader 835edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 8368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void bindContactData(final Contact data) { 8378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("bindContactData"); 8386cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee mContactData = data; 839d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell invalidateOptionsMenu(); 840edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 8418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 8428a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("Set display photo & name"); 843dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 84402eaf11669d25fd885606b3b0700358323532cddBrian Attwell mPhotoView.setIsBusiness(mContactData.isDisplayNameFromOrganization()); 8456219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee mPhotoSetter.setupContactPhoto(data, mPhotoView); 84631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell extractAndApplyTintFromPhotoViewAsynchronously(); 8474936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell analyzeWhitenessOfPhotoAsynchronously(); 848333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos setHeaderNameText(ContactDisplayUtils.getDisplayName(this, data).toString()); 849edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 8508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 851dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 8526bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mEntriesAndActionsTask = new AsyncTask<Void, Void, Cp2DataCardModel>() { 8538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 8556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell protected Cp2DataCardModel doInBackground( 856eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Void... params) { 857eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return generateDataModelFromContact(data); 8588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 8616bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell protected void onPostExecute(Cp2DataCardModel cardDataModel) { 8626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell super.onPostExecute(cardDataModel); 8638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Check that original AsyncTask parameters are still valid and the activity 8648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // is still running before binding to UI. A new intent could invalidate 8658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the results, for example. 8668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (data == mContactData && !isCancelled()) { 8676bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell bindDataToCards(cardDataModel); 8688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell showActivity(); 8698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }; 8728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.execute(); 8738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void bindDataToCards(Cp2DataCardModel cp2DataCardModel) { 8766bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell startInteractionLoaders(cp2DataCardModel); 8776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell populateContactAndAboutCard(cp2DataCardModel); 878eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 879eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 8806bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void startInteractionLoaders(Cp2DataCardModel cp2DataCardModel) { 8816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Map<String, List<DataItem>> dataItemsMap = cp2DataCardModel.dataItemsMap; 8826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> phoneDataItems = dataItemsMap.get(Phone.CONTENT_ITEM_TYPE); 88397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (phoneDataItems != null && phoneDataItems.size() == 1) { 88497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mOnlyOnePhoneNumber = true; 88597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 886eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String[] phoneNumbers = null; 887eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (phoneDataItems != null) { 888eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phoneNumbers = new String[phoneDataItems.size()]; 889eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (int i = 0; i < phoneDataItems.size(); ++i) { 890eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phoneNumbers[i] = ((PhoneDataItem) phoneDataItems.get(i)).getNumber(); 891eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 892eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 893ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle phonesExtraBundle = new Bundle(); 894eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phonesExtraBundle.putStringArray(KEY_LOADER_EXTRA_PHONES, phoneNumbers); 895eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 896eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("start sms loader"); 8978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getLoaderManager().initLoader( 8988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell LOADER_SMS_ID, 899ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 900ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos mLoaderInteractionsCallbacks); 901ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.endSection(); 902ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 903ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.beginSection("start call log loader"); 904ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos getLoaderManager().initLoader( 905ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID, 906ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 9078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mLoaderInteractionsCallbacks); 908899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.endSection(); 9098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 910eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 911899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.beginSection("start calendar loader"); 9126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> emailDataItems = dataItemsMap.get(Email.CONTENT_ITEM_TYPE); 91397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (emailDataItems != null && emailDataItems.size() == 1) { 91497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mOnlyOneEmail = true; 91597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 916eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String[] emailAddresses = null; 917eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (emailDataItems != null) { 918eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailAddresses = new String[emailDataItems.size()]; 919eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (int i = 0; i < emailDataItems.size(); ++i) { 920eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailAddresses[i] = ((EmailDataItem) emailDataItems.get(i)).getAddress(); 921eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 922eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 923ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle emailsExtraBundle = new Bundle(); 924eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailsExtraBundle.putStringArray(KEY_LOADER_EXTRA_EMAILS, emailAddresses); 925899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos getLoaderManager().initLoader( 926899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos LOADER_CALENDAR_ID, 927ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos emailsExtraBundle, 928899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos mLoaderInteractionsCallbacks); 9298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 9308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void showActivity() { 9338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller != null) { 9348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mScroller.setVisibility(View.VISIBLE); 9358a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 9368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell new Runnable() { 9378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 9388a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void run() { 9398a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell runEntranceAnimation(); 9408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }); 9428a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9438a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9456bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private List<List<Entry>> buildAboutCardEntries(Map<String, List<DataItem>> dataItemsMap) { 946a153dba33c2152332c5706178a367f52b0550723Paul Soulos final List<List<Entry>> aboutCardEntries = new ArrayList<>(); 947a153dba33c2152332c5706178a367f52b0550723Paul Soulos for (String mimetype : SORTED_ABOUT_CARD_MIMETYPES) { 9486bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> mimeTypeItems = dataItemsMap.get(mimetype); 949a153dba33c2152332c5706178a367f52b0550723Paul Soulos if (mimeTypeItems == null) { 950a153dba33c2152332c5706178a367f52b0550723Paul Soulos continue; 951a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 9526bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // Set aboutCardTitleOut = null, since SORTED_ABOUT_CARD_MIMETYPES doesn't contain 9536bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // the name mimetype. 9546bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<Entry> aboutEntries = dataItemsToEntries(mimeTypeItems, 9556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /* aboutCardTitleOut = */ null); 956a153dba33c2152332c5706178a367f52b0550723Paul Soulos if (aboutEntries.size() > 0) { 957a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(aboutEntries); 958a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 959a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 960a153dba33c2152332c5706178a367f52b0550723Paul Soulos return aboutCardEntries; 961a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 962a153dba33c2152332c5706178a367f52b0550723Paul Soulos 963a42ef76251778161d27bc07db214b8c81720e476Paul Soulos @Override 964a42ef76251778161d27bc07db214b8c81720e476Paul Soulos protected void onResume() { 965a42ef76251778161d27bc07db214b8c81720e476Paul Soulos super.onResume(); 966a42ef76251778161d27bc07db214b8c81720e476Paul Soulos // If returning from a launched activity, repopulate the contact and about card 967a42ef76251778161d27bc07db214b8c81720e476Paul Soulos if (mHasIntentLaunched) { 968a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = false; 9696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell populateContactAndAboutCard(mCachedCp2DataCardModel); 970a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 971a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 972a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 9736bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void populateContactAndAboutCard(Cp2DataCardModel cp2DataCardModel) { 9746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mCachedCp2DataCardModel = cp2DataCardModel; 9756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (mHasIntentLaunched || cp2DataCardModel == null) { 976a42ef76251778161d27bc07db214b8c81720e476Paul Soulos return; 977a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 978eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("bind contact card"); 979eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 9806bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> contactCardEntries = cp2DataCardModel.contactCardEntries; 9816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> aboutCardEntries = cp2DataCardModel.aboutCardEntries; 9826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String customAboutCardName = cp2DataCardModel.customAboutCardName; 983eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 984eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (contactCardEntries.size() > 0) { 985eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.initialize(contactCardEntries, 986eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /* numInitialVisibleEntries = */ MIN_NUM_CONTACT_ENTRIES_SHOWN, 987c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos /* isExpanded = */ mContactCard.isExpanded(), 98889966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos /* isAlwaysExpanded = */ false, 9890cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mExpandingEntryCardViewListener, 9900cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller); 991eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setVisibility(View.VISIBLE); 992eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 993eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setVisibility(View.GONE); 994eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 995eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 9968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 997eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("bind about card"); 998c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos // Phonetic name is not a data item, so the entry needs to be created separately 999c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos final String phoneticName = mContactData.getPhoneticName(); 1000c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos if (!TextUtils.isEmpty(phoneticName)) { 1001c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos Entry phoneticEntry = new Entry(/* viewId = */ -1, 1002c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* icon = */ null, 1003c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos getResources().getString(R.string.name_phonetic), 1004c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos phoneticName, 1005c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* text = */ null, 100623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* primaryContentDescription = */ null, 1007c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* intent = */ null, 1008c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateIcon = */ null, 1009c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateIntent = */ null, 1010c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateContentDescription = */ null, 1011c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* shouldApplyColor = */ false, 10122a4207fb39330e840436215c896cde911489e111Paul Soulos /* isEditable = */ false, 10132a4207fb39330e840436215c896cde911489e111Paul Soulos /* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName, 101497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos getResources().getString(R.string.name_phonetic), 101597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos /* mimeType = */ null, /* id = */ -1, /* isPrimary = */ false), 101648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, 101748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIntent = */ null, 101848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, 101948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* iconResourceId = */ 0); 1020c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos List<Entry> phoneticList = new ArrayList<>(); 1021c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos phoneticList.add(phoneticEntry); 1022a153dba33c2152332c5706178a367f52b0550723Paul Soulos // Phonetic name comes after nickname. Check to see if the first entry type is nickname 1023a0fa4c18dc111ceea9ff47f35ee01fecc1003578Paul Soulos if (aboutCardEntries.size() > 0 && aboutCardEntries.get(0).get(0).getHeader().equals( 1024a153dba33c2152332c5706178a367f52b0550723Paul Soulos getResources().getString(R.string.header_nickname_entry))) { 1025a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(1, phoneticList); 1026a153dba33c2152332c5706178a367f52b0550723Paul Soulos } else { 1027a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(0, phoneticList); 1028a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 1029c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos } 1030c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos 10316bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!TextUtils.isEmpty(customAboutCardName)) { 10326bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mAboutCard.setTitle(customAboutCardName); 10336bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 10346bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 1035cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (aboutCardEntries.size() > 0) { 1036cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mAboutCard.initialize(aboutCardEntries, 1037cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* numInitialVisibleEntries = */ 1, 1038cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* isExpanded = */ true, 1039cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* isAlwaysExpanded = */ true, 1040cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mExpandingEntryCardViewListener, 1041cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mScroller); 1042cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } 10436095369885edcca566a812b551886e29c7ff8039Brian Attwell 10446095369885edcca566a812b551886e29c7ff8039Brian Attwell if (contactCardEntries.size() == 0 && aboutCardEntries.size() == 0) { 10456095369885edcca566a812b551886e29c7ff8039Brian Attwell initializeNoContactDetailCard(); 10466095369885edcca566a812b551886e29c7ff8039Brian Attwell } else { 10476095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setVisibility(View.GONE); 10486095369885edcca566a812b551886e29c7ff8039Brian Attwell } 10496095369885edcca566a812b551886e29c7ff8039Brian Attwell 1050a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos // If the Recent card is already initialized (all recent data is loaded), show the About 1051a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos // card if it has entries. Otherwise About card visibility will be set in bindRecentData() 1052a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos if (isAllRecentDataLoaded() && aboutCardEntries.size() > 0) { 1053a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos mAboutCard.setVisibility(View.VISIBLE); 1054a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos } 1055eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 1056eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1057eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1058eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 10596095369885edcca566a812b551886e29c7ff8039Brian Attwell * Create a card that shows "Add email" and "Add phone number" entries in grey. 10606095369885edcca566a812b551886e29c7ff8039Brian Attwell */ 10616095369885edcca566a812b551886e29c7ff8039Brian Attwell private void initializeNoContactDetailCard() { 10626095369885edcca566a812b551886e29c7ff8039Brian Attwell final Drawable phoneIcon = getResources().getDrawable( 10636095369885edcca566a812b551886e29c7ff8039Brian Attwell R.drawable.ic_phone_24dp).mutate(); 10646095369885edcca566a812b551886e29c7ff8039Brian Attwell final Entry phonePromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT, 10656095369885edcca566a812b551886e29c7ff8039Brian Attwell phoneIcon, getString(R.string.quickcontact_add_phone_number), 106623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* subHeader = */ null, /* text = */ null, /* primaryContentDescription = */ null, 106723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos getEditContactIntent(), 1068dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIcon = */ null, /* alternateIntent = */ null, 1069714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos /* alternateContentDescription = */ null, /* shouldApplyColor = */ true, 107048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* isEditable = */ false, /* EntryContextMenuInfo = */ null, 107148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, /* thirdIntent = */ null, 107248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, R.drawable.ic_phone_24dp); 10736095369885edcca566a812b551886e29c7ff8039Brian Attwell 10746095369885edcca566a812b551886e29c7ff8039Brian Attwell final Drawable emailIcon = getResources().getDrawable( 10756095369885edcca566a812b551886e29c7ff8039Brian Attwell R.drawable.ic_email_24dp).mutate(); 10766095369885edcca566a812b551886e29c7ff8039Brian Attwell final Entry emailPromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT, 10776095369885edcca566a812b551886e29c7ff8039Brian Attwell emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null, 107823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* text = */ null, /* primaryContentDescription = */ null, 107923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos getEditContactIntent(), /* alternateIcon = */ null, 1080dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIntent = */ null, /* alternateContentDescription = */ null, 10812a4207fb39330e840436215c896cde911489e111Paul Soulos /* shouldApplyColor = */ true, /* isEditable = */ false, 108248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null, 108348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdIntent = */ null, /* thirdContentDescription = */ null, 108448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos R.drawable.ic_email_24dp); 10856095369885edcca566a812b551886e29c7ff8039Brian Attwell 10866095369885edcca566a812b551886e29c7ff8039Brian Attwell final List<List<Entry>> promptEntries = new ArrayList<>(); 10876095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.add(new ArrayList<Entry>(1)); 10886095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.add(new ArrayList<Entry>(1)); 10896095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.get(0).add(phonePromptEntry); 10906095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.get(1).add(emailPromptEntry); 10916095369885edcca566a812b551886e29c7ff8039Brian Attwell 10926095369885edcca566a812b551886e29c7ff8039Brian Attwell final int subHeaderTextColor = getResources().getColor( 10936095369885edcca566a812b551886e29c7ff8039Brian Attwell R.color.quickcontact_entry_sub_header_text_color); 10946095369885edcca566a812b551886e29c7ff8039Brian Attwell final PorterDuffColorFilter greyColorFilter = 10956095369885edcca566a812b551886e29c7ff8039Brian Attwell new PorterDuffColorFilter(subHeaderTextColor, PorterDuff.Mode.SRC_ATOP); 1096c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos mNoContactDetailsCard.initialize(promptEntries, 2, /* isExpanded = */ true, 10970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos /* isAlwaysExpanded = */ true, mExpandingEntryCardViewListener, mScroller); 10986095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setVisibility(View.VISIBLE); 10996095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setEntryHeaderColor(subHeaderTextColor); 11006095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setColorAndFilter(subHeaderTextColor, greyColorFilter); 11016095369885edcca566a812b551886e29c7ff8039Brian Attwell } 11026095369885edcca566a812b551886e29c7ff8039Brian Attwell 11036095369885edcca566a812b551886e29c7ff8039Brian Attwell /** 1104eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Builds the {@link DataItem}s Map out of the Contact. 1105eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @param data The contact to build the data from. 1106eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @return A pair containing a list of data items sorted within mimetype and sorted 1107eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * amongst mimetype. The map goes from mimetype string to the sorted list of data items within 1108eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * mimetype 1109eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 11106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private Cp2DataCardModel generateDataModelFromContact( 1111eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Contact data) { 1112eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("Build data items map"); 1113eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1114eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Map<String, List<DataItem>> dataItemsMap = new HashMap<>(); 11158bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell 11168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final ResolveCache cache = ResolveCache.getInstance(this); 1117851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContact rawContact : data.getRawContacts()) { 1118851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (DataItem dataItem : rawContact.getDataItems()) { 1119eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItem.setRawContactId(rawContact.getId()); 1120eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1121851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String mimeType = dataItem.getMimeType(); 1122eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (mimeType == null) continue; 1123eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 112447b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final AccountType accountType = rawContact.getAccountType(this); 112547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final DataKind dataKind = AccountTypeManager.getInstance(this) 112647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng .getKindOrFallback(accountType, mimeType); 1127eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataKind == null) continue; 1128cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1129eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItem.setDataKind(dataKind); 1130b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1131eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean hasData = !TextUtils.isEmpty(dataItem.buildDataString(this, 1132eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataKind)); 1133899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 1134eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (isMimeExcluded(mimeType) || !hasData) continue; 1135edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1136eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos List<DataItem> dataItemListByType = dataItemsMap.get(mimeType); 1137eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataItemListByType == null) { 1138eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemListByType = new ArrayList<>(); 1139eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemsMap.put(mimeType, dataItemListByType); 1140edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1141eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemListByType.add(dataItem); 1142edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1143edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 11448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 1145edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1146eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("sort within mimetypes"); 114716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos /* 114816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * Sorting is a multi part step. The end result is to a have a sorted list of the most 1149eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * used data items, one per mimetype. Then, within each mimetype, the list of data items 1150eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * for that type is also sorted, based off of {super primary, primary, times used} in that 1151eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * order. 115216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos */ 1153eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<List<DataItem>> dataItemsList = new ArrayList<>(); 1154eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (List<DataItem> mimeTypeDataItems : dataItemsMap.values()) { 1155eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Remove duplicate data items 1156eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collapser.collapseList(mimeTypeDataItems, this); 1157eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Sort within mimetype 1158eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collections.sort(mimeTypeDataItems, mWithinMimeTypeDataItemComparator); 1159eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Add to the list of data item lists 1160eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemsList.add(mimeTypeDataItems); 1161edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1162eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 1163edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1164eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("sort amongst mimetypes"); 1165eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Sort amongst mimetypes to bubble up the top data items for the contact card 1166eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collections.sort(dataItemsList, mAmongstMimeTypeDataItemComparator); 1167eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 116816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos 11696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Trace.beginSection("cp2 data items to entries"); 11706bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 11716bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> contactCardEntries = new ArrayList<>(); 11726bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> aboutCardEntries = buildAboutCardEntries(dataItemsMap); 11736bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final MutableString aboutCardName = new MutableString(); 11746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 11756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell for (int i = 0; i < dataItemsList.size(); ++i) { 11766bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> dataItemsByMimeType = dataItemsList.get(i); 11776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final DataItem topDataItem = dataItemsByMimeType.get(0); 11786bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (SORTED_ABOUT_CARD_MIMETYPES.contains(topDataItem.getMimeType())) { 11796bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // About card mimetypes are built in buildAboutCardEntries, skip here 11806bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell continue; 11816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } else { 11826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell List<Entry> contactEntries = dataItemsToEntries(dataItemsList.get(i), 11836bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell aboutCardName); 11846bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (contactEntries.size() > 0) { 11856bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell contactCardEntries.add(contactEntries); 11866bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 11876bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 11886bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 11896bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 11906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Trace.endSection(); 11916bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 11926bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Cp2DataCardModel dataModel = new Cp2DataCardModel(); 11936bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.customAboutCardName = aboutCardName.value; 11946bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.aboutCardEntries = aboutCardEntries; 11956bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.contactCardEntries = contactCardEntries; 11966bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.dataItemsMap = dataItemsMap; 11976bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell return dataModel; 11986bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 11996bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12006bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 12016bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * Class used to hold the About card and Contact cards' data model that gets generated 12026bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * on a background thread. All data is from CP2. 12036bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 12046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static class Cp2DataCardModel { 12056bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 12066bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * A map between a mimetype string and the corresponding list of data items. The data items 12076bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * are in sorted order using mWithinMimeTypeDataItemComparator. 12086bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 12096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public Map<String, List<DataItem>> dataItemsMap; 12106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public List<List<Entry>> aboutCardEntries; 12116bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public List<List<Entry>> contactCardEntries; 12126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public String customAboutCardName; 12136bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12146bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static class MutableString { 12166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public String value; 1217eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1218edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1219eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 1220eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Converts a {@link DataItem} into an {@link ExpandingEntryCardView.Entry} for display. 1221eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * If the {@link ExpandingEntryCardView.Entry} has no visual elements, null is returned. 12226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * 12236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * This runs on a background thread. This is set as static to avoid accidentally adding 12246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * additional dependencies on unsafe things (like the Activity). 12256bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * 1226eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @param dataItem The {@link DataItem} to convert. 1227eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @return The {@link ExpandingEntryCardView.Entry}, or null if no visual elements are present. 1228eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 12296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static Entry dataItemToEntry(DataItem dataItem, 12306bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Context context, Contact contactData, 12316bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final MutableString aboutCardName) { 1232eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable icon = null; 1233eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String header = null; 1234eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String subHeader = null; 1235eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable subHeaderIcon = null; 1236eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String text = null; 1237eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable textIcon = null; 123823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos StringBuilder primaryContentDescription = new StringBuilder(); 1239eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Intent intent = null; 124048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos boolean shouldApplyColor = true; 1241dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Drawable alternateIcon = null; 1242dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Intent alternateIntent = null; 124323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos StringBuilder alternateContentDescription = new StringBuilder(); 1244eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isEditable = false; 12452a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo entryContextMenuInfo = null; 124648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Drawable thirdIcon = null; 124748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Intent thirdIntent = null; 124848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos String thirdContentDescription = null; 124948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos int iconResourceId = 0; 1250eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 12516bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell context = context.getApplicationContext(); 125223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos final Resources res = context.getResources(); 1253eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataKind kind = dataItem.getDataKind(); 1254eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1255eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataItem instanceof ImDataItem) { 1256eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final ImDataItem im = (ImDataItem) dataItem; 12576bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell intent = ContactsUtils.buildImIntent(context, im).first; 1258eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isEmail = im.isCreatedFromEmail(); 12597de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos final int protocol; 12607de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos if (!im.isProtocolValid()) { 12617de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos protocol = Im.PROTOCOL_CUSTOM; 12627de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } else { 12637de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol(); 12647de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } 12657de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos if (protocol == Im.PROTOCOL_CUSTOM) { 12667de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos // If the protocol is custom, display the "IM" entry header as well to distinguish 12677de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos // this entry from other ones 126823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_im_entry); 126923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos subHeader = Im.getProtocolLabel(res, protocol, 12707de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos im.getCustomProtocol()).toString(); 12717de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos text = im.getData(); 12727de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } else { 127323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = Im.getProtocolLabel(res, protocol, 12747de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos im.getCustomProtocol()).toString(); 12757de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos subHeader = im.getData(); 12767de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } 127797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header, 127897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1279eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof OrganizationDataItem) { 1280eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final OrganizationDataItem organization = (OrganizationDataItem) dataItem; 128123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_organization_entry); 1282eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = organization.getCompany(); 128397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 128497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1285eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos text = organization.getTitle(); 1286eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof NicknameDataItem) { 1287eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final NicknameDataItem nickname = (NicknameDataItem) dataItem; 1288eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Build nickname entries 1289eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isNameRawContact = 12906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell (contactData.getNameRawContactId() == dataItem.getRawContactId()); 1291eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1292eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean duplicatesTitle = 1293eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos isNameRawContact 12946bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell && contactData.getDisplayNameSource() == DisplayNameSources.NICKNAME; 1295eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1296eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!duplicatesTitle) { 129723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_nickname_entry); 1298eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = nickname.getName(); 129997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 130097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1301eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1302eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof NoteDataItem) { 1303eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final NoteDataItem note = (NoteDataItem) dataItem; 130423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_note_entry); 1305eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = note.getNote(); 130697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 130797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1308eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof WebsiteDataItem) { 1309eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final WebsiteDataItem website = (WebsiteDataItem) dataItem; 131023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_website_entry); 1311eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = website.getUrl(); 131297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 131397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1314eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos try { 13156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final WebAddress webAddress = new WebAddress(website.buildDataString(context, 13166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell kind)); 1317eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString())); 1318eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } catch (final ParseException e) { 13196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Log.e(TAG, "Couldn't parse website: " + website.buildDataString(context, kind)); 1320eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1321eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof EventDataItem) { 1322eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final EventDataItem event = (EventDataItem) dataItem; 13236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String dataString = event.buildDataString(context, kind); 1324eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Calendar cal = DateUtils.parseDate(dataString, false); 1325eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (cal != null) { 1326eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Date nextAnniversary = 1327eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DateUtils.getNextAnnualDate(cal); 1328eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon(); 1329eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos builder.appendPath("time"); 1330eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos ContentUris.appendId(builder, nextAnniversary.getTime()); 1331eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW).setData(builder.build()); 1332eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 133323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_event_entry); 1334f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (event.hasKindTypeColumn(kind)) { 133523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos subHeader = Event.getTypeLabel(res, event.getKindTypeColumn(kind), 13367de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos event.getLabel()).toString(); 1337f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 13386bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell text = DateUtils.formatDate(context, dataString); 133997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(text, header, 134097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1341eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof RelationDataItem) { 1342eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final RelationDataItem relation = (RelationDataItem) dataItem; 13436bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String dataString = relation.buildDataString(context, kind); 1344eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(dataString)) { 1345eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_SEARCH); 1346eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent.putExtra(SearchManager.QUERY, dataString); 1347eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent.setType(Contacts.CONTENT_TYPE); 1348eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 134923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_relation_entry); 1350eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = relation.getName(); 135197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 135297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1353f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (relation.hasKindTypeColumn(kind)) { 135423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Relation.getTypeLabel(res, 13556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell relation.getKindTypeColumn(kind), 1356f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos relation.getLabel()).toString(); 1357f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 1358eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof PhoneDataItem) { 1359eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final PhoneDataItem phone = (PhoneDataItem) dataItem; 1360eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(phone.getNumber())) { 136123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.call_other)).append(" "); 13626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell header = phone.buildDataString(context, kind); 13632a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 136497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(), 136597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1366f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (phone.hasKindTypeColumn(kind)) { 136723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Phone.getTypeLabel(res, phone.getKindTypeColumn(kind), 1368f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos phone.getLabel()).toString(); 136923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1370f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 137123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 137223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_phone_24dp); 137348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_phone_24dp; 13746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (PhoneCapabilityTester.isPhone(context)) { 1375eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = CallUtil.getCallIntent(phone.getNumber()); 137616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 1377dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIntent = new Intent(Intent.ACTION_SENDTO, 13781cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phone.getNumber(), null)); 137948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 138023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateIcon = res.getDrawable(R.drawable.ic_message_24dp); 138123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(res.getString(R.string.sms_custom, header)); 138248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 138348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // Add video call button if supported 1384f764730a34da560db87206f9a48390d4c8085365Paul Soulos if (CallUtil.isVideoEnabled(context)) { 138523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos thirdIcon = res.getDrawable(R.drawable.ic_videocam); 138648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIntent = CallUtil.getVideoCallIntent(phone.getNumber(), 138748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY); 138848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdContentDescription = 138923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos res.getString(R.string.description_video_call); 139048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 1391eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1392eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof EmailDataItem) { 1393eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final EmailDataItem email = (EmailDataItem) dataItem; 1394eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String address = email.getData(); 1395eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(address)) { 139623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.email_other)).append(" "); 13971cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner final Uri mailUri = Uri.fromParts(ContactsUtils.SCHEME_MAILTO, address, null); 1398eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_SENDTO, mailUri); 1399eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos header = email.getAddress(); 14002a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 140197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.emailLabelsGroup), dataItem.getMimeType(), 140297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1403f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (email.hasKindTypeColumn(kind)) { 140423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Email.getTypeLabel(res, email.getKindTypeColumn(kind), 1405f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos email.getLabel()).toString(); 140623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1407f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 140823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 140923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_email_24dp); 141048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_email_24dp; 1411eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1412eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof StructuredPostalDataItem) { 1413eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos StructuredPostalDataItem postal = (StructuredPostalDataItem) dataItem; 1414eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String postalAddress = postal.getFormattedAddress(); 1415eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(postalAddress)) { 141623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.map_other)).append(" "); 1417eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress); 1418eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos header = postal.getFormattedAddress(); 14192a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 142097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.postalLabelsGroup), dataItem.getMimeType(), 142197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1422f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (postal.hasKindTypeColumn(kind)) { 142323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = StructuredPostal.getTypeLabel(res, 1424f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos postal.getKindTypeColumn(kind), postal.getLabel()).toString(); 142523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1426f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 142723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 14286a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos alternateIntent = 14296a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos StructuredPostalUtils.getViewPostalAddressDirectionsIntent(postalAddress); 143023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateIcon = res.getDrawable(R.drawable.ic_directions_24dp); 143123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(res.getString( 143223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos R.string.content_description_directions)).append(" ").append(header); 143323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_place_24dp); 143448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_place_24dp; 1435eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1436eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof SipAddressDataItem) { 14376bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (PhoneCapabilityTester.isSipPhone(context)) { 1438eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final SipAddressDataItem sip = (SipAddressDataItem) dataItem; 1439eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String address = sip.getSipAddress(); 1440eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(address)) { 144123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.call_other)).append( 144223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos " "); 14431cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner final Uri callUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, address, null); 1444eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = CallUtil.getCallIntent(callUri); 14451cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos header = address; 14462a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 144797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(), 144897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 14491cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos if (sip.hasKindTypeColumn(kind)) { 145023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = SipAddress.getTypeLabel(res, 14516bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell sip.getKindTypeColumn(kind), sip.getLabel()).toString(); 145223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 14531cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos } 145423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 145523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_dialer_sip_black_24dp); 145648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_dialer_sip_black_24dp; 145716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 1458edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1459eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof StructuredNameDataItem) { 1460eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String givenName = ((StructuredNameDataItem) dataItem).getGivenName(); 1461eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(givenName)) { 146223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos aboutCardName.value = res.getString(R.string.about_card_title) + 14636bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell " " + givenName; 1464eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 146523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos aboutCardName.value = res.getString(R.string.about_card_title); 1466eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1467eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 1468eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Custom DataItem 14696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell header = dataItem.buildDataStringForDisplay(context, kind); 1470eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos text = kind.typeColumn; 1471eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW); 147260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos final Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, dataItem.getId()); 147360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos intent.setDataAndType(uri, dataItem.getMimeType()); 1474e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 1475e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (intent != null) { 1476e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos final String mimetype = intent.getType(); 1477e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 1478e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos // Attempt to use known icons for known 3p types. Otherwise default to ResolveCache 1479e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos switch (mimetype) { 1480e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos case MIMETYPE_GPLUS_PROFILE: 1481e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (INTENT_DATA_GPLUS_PROFILE_ADD_TO_CIRCLE.equals( 1482e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos intent.getDataString())) { 148323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable( 1484e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos R.drawable.ic_add_to_circles_black_24); 148548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_add_to_circles_black_24; 1486e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } else { 148723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_google_plus_24dp); 148848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_google_plus_24dp; 1489e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1490e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos break; 1491e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos case MIMETYPE_HANGOUTS: 1492e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (INTENT_DATA_HANGOUTS_VIDEO.equals(intent.getDataString())) { 149323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_hangout_video_24dp); 149448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_hangout_video_24dp; 1495e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } else { 149623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_hangout_24dp); 149748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_hangout_24dp; 1498e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1499e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos break; 1500e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos default: 150197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype, 150297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), 150397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.isSuperPrimary()); 15046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell icon = ResolveCache.getInstance(context).getIcon( 1505e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos dataItem.getMimeType(), intent); 1506e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos // Call mutate to create a new Drawable.ConstantState for color filtering 1507e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (icon != null) { 1508e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos icon.mutate(); 1509e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 151048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos shouldApplyColor = false; 1511e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1512e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1513eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1514b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1515eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (intent != null) { 1516eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Do not set the intent is there are no resolves 15176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!PhoneCapabilityTester.isIntentRegistered(context, intent)) { 1518eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = null; 1519eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1520eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1521eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1522dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (alternateIntent != null) { 1523dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos // Do not set the alternate intent is there are no resolves 15246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!PhoneCapabilityTester.isIntentRegistered(context, alternateIntent)) { 1525dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIntent = null; 1526f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner } else if (TextUtils.isEmpty(alternateContentDescription)) { 1527f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner // Attempt to use package manager to find a suitable content description if needed 152823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(getIntentResolveLabel(alternateIntent, context)); 1529dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1530dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1531dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1532eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // If the Entry has no visual elements, return null 1533eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (icon == null && TextUtils.isEmpty(header) && TextUtils.isEmpty(subHeader) && 1534eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeaderIcon == null && TextUtils.isEmpty(text) && textIcon == null) { 1535eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return null; 1536eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1537eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1538fa238949855fba3b28a57fad3d585b13e80362bbBrian Attwell // Ignore dataIds from the Me profile. 1539ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos final int dataId = dataItem.getId() > Integer.MAX_VALUE ? 1540ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos -1 : (int) dataItem.getId(); 1541ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 154223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, 154323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.toString(), intent, alternateIcon, alternateIntent, 154423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.toString(), shouldApplyColor, isEditable, 154548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription, 154648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId); 1547eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1548eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 15496bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private List<Entry> dataItemsToEntries(List<DataItem> dataItems, 15506bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell MutableString aboutCardTitleOut) { 1551eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<Entry> entries = new ArrayList<>(); 1552eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (DataItem dataItem : dataItems) { 15536bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Entry entry = dataItemToEntry(dataItem, this, mContactData, aboutCardTitleOut); 1554eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (entry != null) { 1555eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos entries.add(entry); 1556eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1557eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1558eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return entries; 1559edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1560edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 15616bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static String getIntentResolveLabel(Intent intent, Context context) { 15626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<ResolveInfo> matches = context.getPackageManager().queryIntentActivities(intent, 1563dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos PackageManager.MATCH_DEFAULT_ONLY); 1564dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1565dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos // Pick first match, otherwise best found 1566dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos ResolveInfo bestResolve = null; 1567dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final int size = matches.size(); 1568dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (size == 1) { 1569dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos bestResolve = matches.get(0); 1570dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } else if (size > 1) { 15716bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell bestResolve = ResolveCache.getInstance(context).getBestResolve(intent, matches); 1572dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1573dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1574dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (bestResolve == null) { 1575dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos return null; 1576dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1577dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 15786bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell return String.valueOf(bestResolve.loadLabel(context.getPackageManager())); 1579dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1580dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1581edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 158231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * Asynchronously extract the most vibrant color from the PhotoView. Once extracted, 158331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms 158431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * on a Nexus 5. 158531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell */ 158631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell private void extractAndApplyTintFromPhotoViewAsynchronously() { 158731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (mScroller == null) { 158831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return; 158931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 159031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 1591faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell new AsyncTask<Void, Void, MaterialPalette>() { 159231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 1593faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell protected MaterialPalette doInBackground(Void... params) { 1594faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell 159595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell if (imageViewDrawable instanceof BitmapDrawable 159695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell && mContactData.getThumbnailPhotoBinaryData() != null 159795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell && mContactData.getThumbnailPhotoBinaryData().length > 0) { 159895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // Perform the color analysis on the thumbnail instead of the full sized 159995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // image, so that our results will be as similar as possible to the Bugle 160095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // app. 160195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell final Bitmap bitmap = BitmapFactory.decodeByteArray( 160295c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell mContactData.getThumbnailPhotoBinaryData(), 0, 160395c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell mContactData.getThumbnailPhotoBinaryData().length); 160495c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell try { 160595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell final int primaryColor = colorFromBitmap(bitmap); 160695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell if (primaryColor != 0) { 160795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor( 160895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell primaryColor); 160995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell } 161095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell } finally { 161195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell bitmap.recycle(); 1612faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell } 16138a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 16148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (imageViewDrawable instanceof LetterTileDrawable) { 1615faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell final int primaryColor = ((LetterTileDrawable) imageViewDrawable).getColor(); 1616a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(primaryColor); 161731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 1618a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell return MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors(getResources()); 161931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 162031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 162131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 1622faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell protected void onPostExecute(MaterialPalette palette) { 1623faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell super.onPostExecute(palette); 16248571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (mHasComputedThemeColor) { 16258571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // If we had previously computed a theme color from the contact photo, 16268571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // then do not update the theme color. Changing the theme color several 16278571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // seconds after QC has started, as a result of an updated/upgraded photo, 16288571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // is a jarring experience. On the other hand, changing the theme color after 16298571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // a rotation or onNewIntent() is perfectly fine. 16308571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell return; 16318571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell } 16328571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // Check that the Photo has not changed. If it has changed, the new tint 16338571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // color needs to be extracted 16348571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (imageViewDrawable == mPhotoView.getDrawable()) { 16358571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = true; 1636faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell setThemeColor(palette); 163731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 163831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 163931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell }.execute(); 164031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 164131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 16424936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell /** 16434936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * Examine how many white pixels are in the bitmap in order to determine whether or not 16444936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * we need gradient overlays on top of the image. 16454936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell */ 16464936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell private void analyzeWhitenessOfPhotoAsynchronously() { 16474936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 16484936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell new AsyncTask<Void, Void, Boolean>() { 16494936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 16504936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected Boolean doInBackground(Void... params) { 16514936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell if (imageViewDrawable instanceof BitmapDrawable) { 16524936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap(); 16534936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return WhitenessUtils.isBitmapWhiteAtTopOrBottom(bitmap); 16544936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 16554936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return !(imageViewDrawable instanceof LetterTileDrawable); 16564936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 16574936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 16584936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 16594936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected void onPostExecute(Boolean isWhite) { 16604936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell super.onPostExecute(isWhite); 16614936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell mScroller.setUseGradient(isWhite); 16624936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 16634936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell }.execute(); 16644936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 16654936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 1666faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell private void setThemeColor(MaterialPalette palette) { 16679b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // If the color is invalid, use the predefined default 1668faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell final int primaryColor = palette.mPrimaryColor; 1669faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mScroller.setHeaderTintColor(primaryColor); 1670faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mStatusBarColor = palette.mSecondaryColor; 16719b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell updateStatusBarColor(); 16728571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell 16739b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mColorFilter = 1674faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell new PorterDuffColorFilter(primaryColor, PorterDuff.Mode.SRC_ATOP); 1675faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mContactCard.setColorAndFilter(primaryColor, mColorFilter); 1676faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mRecentCard.setColorAndFilter(primaryColor, mColorFilter); 1677faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mAboutCard.setColorAndFilter(primaryColor, mColorFilter); 16789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 16799b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 16808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void updateStatusBarColor() { 16818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller == null) { 16828a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 16838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 16848a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int desiredStatusBarColor; 16858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Only use a custom status bar color if QuickContacts touches the top of the viewport. 16868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller.getScrollNeededToBeFullScreen() <= 0) { 16878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = mStatusBarColor; 16888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } else { 16898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = Color.TRANSPARENT; 16908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 16918a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Animate to the new color. 1692847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell final ObjectAnimator animation = ObjectAnimator.ofInt(getWindow(), "statusBarColor", 1693847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell getWindow().getStatusBarColor(), desiredStatusBarColor); 1694847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.setDuration(ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION); 1695847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.setEvaluator(new ArgbEvaluator()); 1696847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.start(); 16978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 16988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 16998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int colorFromBitmap(Bitmap bitmap) { 17008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Author of Palette recommends using 24 colors when analyzing profile photos. 17018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int NUMBER_OF_PALETTE_COLORS = 24; 17028a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS); 1703a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell if (palette != null && palette.getVibrantSwatch() != null) { 1704a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell return palette.getVibrantSwatch().getRgb(); 17058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 17068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return 0; 17078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 17088a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1709b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private List<Entry> contactInteractionsToEntries(List<ContactInteraction> interactions) { 1710eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<Entry> entries = new ArrayList<>(); 1711b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos for (ContactInteraction interaction : interactions) { 1712ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos entries.add(new Entry(/* id = */ -1, 1713ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos interaction.getIcon(this), 1714b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewHeader(this), 1715b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewBody(this), 1716b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getBodyIcon(this), 1717b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewFooter(this), 1718b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getFooterIcon(this), 171923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos interaction.getContentDescription(this), 1720b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getIntent(), 1721dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIcon = */ null, 1722dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIntent = */ null, 1723dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateContentDescription = */ null, 172448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos /* shouldApplyColor = */ true, 17252a4207fb39330e840436215c896cde911489e111Paul Soulos /* isEditable = */ false, 172648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* EntryContextMenuInfo = */ null, 172748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, 172848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIntent = */ null, 172948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, 173048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos interaction.getIconResourceId())); 1731b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1732b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return entries; 1733b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1734b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1735eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final LoaderCallbacks<Contact> mLoaderContactCallbacks = 1736851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 1737cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1738851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 1739405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos mContactData = null; 1740cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1741cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1742cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1743851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 17448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onLoadFinished()"); 17458a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1746cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isFinishing()) { 1747cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann return; 1748cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1749cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (data.isError()) { 1750cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // This shouldn't ever happen, so throw an exception. The {@link ContactLoader} 1751cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // should log the actual exception. 1752cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann throw new IllegalStateException("Failed to load contact", data.getException()); 1753cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1754cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (data.isNotFound()) { 17558a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mHasAlreadyBeenOpened) { 17568a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell finish(); 17578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } else { 17588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri()); 17598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage, 17608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.LENGTH_LONG).show(); 17618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 1762cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann return; 1763cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1764cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1765b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos bindContactData(data); 1766cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 17678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 1768cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1769cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1770cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1771851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 1772cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (mLookupUri == null) { 1773cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early"); 1774cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1775d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Load all contact data. We need loadGroupMetaData=true to determine whether the 1776d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // contact is invisible. If it is, we need to display an "Add to Contacts" MenuItem. 1777b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee return new ContactLoader(getApplicationContext(), mLookupUri, 1778d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell true /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/, 17798571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell true /*postViewNotification*/, true /*computeFormattedPhoneNumber*/); 1780cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1781cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann }; 1782b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1783b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 1784b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onBackPressed() { 1785b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 17868477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell if (!mIsExitAnimationInProgress) { 17878477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mScroller.scrollOffBottom(); 17888477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 1789b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } else { 1790b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell super.onBackPressed(); 1791b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1792b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1793b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 17948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 17958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void finish() { 17968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.finish(); 17978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 17988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // override transitions to skip the standard window animations 17998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell overridePendingTransition(0, 0); 18008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1802eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final LoaderCallbacks<List<ContactInteraction>> mLoaderInteractionsCallbacks = 1803b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos new LoaderCallbacks<List<ContactInteraction>>() { 1804b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1805b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1806b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public Loader<List<ContactInteraction>> onCreateLoader(int id, Bundle args) { 1807b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Log.v(TAG, "onCreateLoader"); 1808b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Loader<List<ContactInteraction>> loader = null; 1809b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos switch (id) { 1810b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos case LOADER_SMS_ID: 1811b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Log.v(TAG, "LOADER_SMS_ID"); 1812b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos loader = new SmsInteractionsLoader( 1813b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos QuickContactActivity.this, 1814ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 1815b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos MAX_SMS_RETRIEVE); 1816b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos break; 1817899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos case LOADER_CALENDAR_ID: 1818899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Log.v(TAG, "LOADER_CALENDAR_ID"); 1819ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos final String[] emailsArray = args.getStringArray(KEY_LOADER_EXTRA_EMAILS); 1820ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos List<String> emailsList = null; 1821ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos if (emailsArray != null) { 1822ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos emailsList = Arrays.asList(args.getStringArray(KEY_LOADER_EXTRA_EMAILS)); 1823ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos } 1824899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos loader = new CalendarInteractionsLoader( 1825899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos QuickContactActivity.this, 1826ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos emailsList, 1827899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_FUTURE_CALENDAR_RETRIEVE, 1828899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_PAST_CALENDAR_RETRIEVE, 1829899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR, 1830899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR); 1831899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos break; 1832ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case LOADER_CALL_LOG_ID: 1833ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Log.v(TAG, "LOADER_CALL_LOG_ID"); 1834ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos loader = new CallLogInteractionsLoader( 1835ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.this, 1836ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 1837ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos MAX_CALL_LOG_RETRIEVE); 1838b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1839b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return loader; 1840b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1841b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1842b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1843b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoadFinished(Loader<List<ContactInteraction>> loader, 1844b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos List<ContactInteraction> data) { 1845b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.put(loader.getId(), data); 1846b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1847b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (isAllRecentDataLoaded()) { 1848b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos bindRecentData(); 1849b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1850b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1851b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1852b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1853b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoaderReset(Loader<List<ContactInteraction>> loader) { 1854b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.remove(loader.getId()); 1855b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1856b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos }; 1857b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1858b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private boolean isAllRecentDataLoaded() { 1859b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return mRecentLoaderResults.size() == mRecentLoaderIds.length; 1860b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1861b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1862b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private void bindRecentData() { 1863eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<ContactInteraction> allInteractions = new ArrayList<>(); 186430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell final List<List<Entry>> interactionsWrapper = new ArrayList<>(); 1865b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 186630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask = new AsyncTask<Void, Void, Void>() { 1867b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 186830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell protected Void doInBackground(Void... params) { 186930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("sort recent loader results"); 187030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 187130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) { 187230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell allInteractions.addAll(loaderInteractions); 187330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 187430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 187530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // Sort the interactions by most recent 187630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Collections.sort(allInteractions, new Comparator<ContactInteraction>() { 187730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell @Override 187830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell public int compare(ContactInteraction a, ContactInteraction b) { 187930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1; 188030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 188130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell }); 188230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 188330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 188430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("contactInteractionsToEntries"); 188530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 188630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // Wrap each interaction in its own list so that an icon is displayed for each entry 188730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell for (Entry contactInteraction : contactInteractionsToEntries(allInteractions)) { 188830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell List<Entry> entryListWrapper = new ArrayList<>(1); 188930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell entryListWrapper.add(contactInteraction); 189030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell interactionsWrapper.add(entryListWrapper); 189130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 189230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 189330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 189430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell return null; 1895b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 189630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 189730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell @Override 189830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell protected void onPostExecute(Void aVoid) { 189930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell super.onPostExecute(aVoid); 190030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("initialize recents card"); 190130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 190230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (allInteractions.size() > 0) { 190330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentCard.initialize(interactionsWrapper, 1904b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN, 1905c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos /* isExpanded = */ mRecentCard.isExpanded(), /* isAlwaysExpanded = */ false, 190630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mExpandingEntryCardViewListener, mScroller); 190730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentCard.setVisibility(View.VISIBLE); 190830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 1909eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 191030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 191130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 191230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // About card is initialized along with the contact card, but since it appears after 191330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // the recent card in the UI, we hold off until making it visible until the recent 191430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // card is also ready to avoid stuttering. 191530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (mAboutCard.shouldShow()) { 191630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mAboutCard.setVisibility(View.VISIBLE); 191730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } else { 191830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mAboutCard.setVisibility(View.GONE); 191930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 192030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask = null; 192130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 192230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell }; 192330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask.execute(); 1924b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 19258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 19268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 19278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onStop() { 19288a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onStop(); 19298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 19308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mEntriesAndActionsTask != null) { 19318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Once the activity is stopped, we will no longer want to bind mEntriesAndActionsTask's 19328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // results on the UI thread. In some circumstances Activities are killed without 19338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // onStop() being called. This is not a problem, because in these circumstances 19348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the entire process will be killed. 19358a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.cancel(/* mayInterruptIfRunning = */ false); 19368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 193730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (mRecentDataTask != null) { 193830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask.cancel(/* mayInterruptIfRunning = */ false); 193930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 19408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 194123889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 194223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos /** 1943d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Returns true if it is possible to edit the current contact. 1944d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 1945d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private boolean isContactEditable() { 1946d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 1947d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1948d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1949a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell /** 1950a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell * Returns true if it is possible to share the current contact. 1951a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell */ 1952a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell private boolean isContactShareable() { 1953a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 1954a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell } 1955a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 19566095369885edcca566a812b551886e29c7ff8039Brian Attwell private Intent getEditContactIntent() { 195763176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell final Intent intent = new Intent(Intent.ACTION_EDIT, mContactData.getLookupUri()); 1958d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 19596095369885edcca566a812b551886e29c7ff8039Brian Attwell return intent; 19606095369885edcca566a812b551886e29c7ff8039Brian Attwell } 19616095369885edcca566a812b551886e29c7ff8039Brian Attwell 19626095369885edcca566a812b551886e29c7ff8039Brian Attwell private void editContact() { 1963a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 1964c00a0b5370f0714f6af1ea9b3e29b10f25e91af0Zheng Fu mContactLoader.cacheResult(); 19656095369885edcca566a812b551886e29c7ff8039Brian Attwell startActivityForResult(getEditContactIntent(), REQUEST_CODE_CONTACT_EDITOR_ACTIVITY); 1966d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1967d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1968d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void toggleStar(MenuItem starredMenuItem) { 1969d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Make sure there is a contact 197063176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell if (mContactData != null) { 1971d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Read the current starred value from the UI instead of using the last 1972d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // loaded state. This allows rapid tapping without writing the same 1973d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // value several times 1974d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final boolean isStarred = starredMenuItem.isChecked(); 1975d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1976d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // To improve responsiveness, swap out the picture (and tag) in the UI already 1977333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos ContactDisplayUtils.configureStarredMenuItem(starredMenuItem, 1978d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 1979d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell !isStarred); 1980d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1981d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Now perform the real save 1982eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Intent intent = ContactSaveService.createSetStarredIntent( 198363176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell QuickContactActivity.this, mContactData.getLookupUri(), !isStarred); 1984d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell startService(intent); 198535ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell 198635ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell final CharSequence accessibilityText = !isStarred 198735ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell ? getResources().getText(R.string.description_action_menu_add_star) 198835ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell : getResources().getText(R.string.description_action_menu_remove_star); 198935ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell // Accessibility actions need to have an associated view. We can't access the MenuItem's 199035ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell // underlying view, so put this accessibility action on the root view. 199135ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell mScroller.announceForAccessibility(accessibilityText); 1992d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1993d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 1994d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 1995752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 1996752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Calls into the contacts provider to get a pre-authorized version of the given URI. 1997752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 1998752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private Uri getPreAuthorizedUri(Uri uri) { 1999752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle uriBundle = new Bundle(); 2000752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); 2001752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle authResponse = getContentResolver().call( 2002752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.AUTHORITY_URI, 2003752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.AUTHORIZATION_METHOD, 2004752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell null, 2005752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle); 2006752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (authResponse != null) { 2007752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return (Uri) authResponse.getParcelable( 2008752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.KEY_AUTHORIZED_URI); 2009752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } else { 2010752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return uri; 2011752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2012752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 20132d150da246632b1649999cfabed776133b097775Brian Attwell 2014752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void shareContact() { 2015752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final String lookupKey = mContactData.getLookupKey(); 2016752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey); 2017752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (mContactData.isUserProfile()) { 2018752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // User is sharing the profile. We don't want to force the receiver to have 2019752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // the highly-privileged READ_PROFILE permission, so we need to request a 2020752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // pre-authorized URI from the provider. 2021752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareUri = getPreAuthorizedUri(shareUri); 2022752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2023752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2024752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent intent = new Intent(Intent.ACTION_SEND); 2025752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.setType(Contacts.CONTENT_VCARD_TYPE); 2026752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.putExtra(Intent.EXTRA_STREAM, shareUri); 2027752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2028752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Launch chooser to share contact via 2029752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final CharSequence chooseTitle = getText(R.string.share_via); 2030752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent chooseIntent = Intent.createChooser(intent, chooseTitle); 2031752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2032752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell try { 2033a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 2034752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell this.startActivity(chooseIntent); 2035eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } catch (final ActivityNotFoundException ex) { 2036752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(this, R.string.share_error, Toast.LENGTH_SHORT).show(); 2037752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2038752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2039752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2040752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 2041752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Creates a launcher shortcut with the current contact. 2042752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 2043752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void createLauncherShortcutWithContact() { 2044752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final ShortcutIntentBuilder builder = new ShortcutIntentBuilder(this, 2045752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell new OnShortcutIntentCreatedListener() { 2046752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2047752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell @Override 2048752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) { 2049752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Broadcast the shortcutIntent to the launcher to create a 2050752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // shortcut to this contact 2051752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 2052752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell QuickContactActivity.this.sendBroadcast(shortcutIntent); 2053752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2054752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Send a toast to give feedback to the user that a shortcut to this 2055752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // contact was added to the launcher. 2056752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(QuickContactActivity.this, 2057752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell R.string.createContactShortcutSuccessful, 2058752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.LENGTH_SHORT).show(); 2059752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2060752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2061752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell }); 206263176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell builder.createContactShortcutIntent(mContactData.getLookupUri()); 2063752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2064752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 206566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell private boolean isShortcutCreatable() { 206666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final Intent createShortcutIntent = new Intent(); 206766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell createShortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 206866965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final List<ResolveInfo> receivers = getPackageManager() 206966965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell .queryBroadcastReceivers(createShortcutIntent, 0); 207066965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell return receivers != null && receivers.size() > 0; 207166965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell } 207266965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell 2073d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2074d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onCreateOptionsMenu(Menu menu) { 2075eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final MenuInflater inflater = getMenuInflater(); 2076d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell inflater.inflate(R.menu.quickcontact, menu); 2077d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2078d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2079d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2080d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2081d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onPrepareOptionsMenu(Menu menu) { 2082d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mContactData != null) { 2083d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem starredMenuItem = menu.findItem(R.id.menu_star); 2084333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos ContactDisplayUtils.configureStarredMenuItem(starredMenuItem, 2085d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 2086d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.getStarred()); 2087a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 2088d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Configure edit MenuItem 2089d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem editMenuItem = menu.findItem(R.id.menu_edit); 2090d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(true); 2091d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData) || InvisibleContactUtil 2092d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .isInvisibleAndAddable(mContactData, this)) { 209330cfd121ad8c8adb83cf417ff1d40a8ba1e3761dBrian Attwell editMenuItem.setIcon(R.drawable.ic_person_add_tinted_24dp); 20942e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell editMenuItem.setTitle(R.string.menu_add_contact); 2095d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 2096d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setIcon(R.drawable.ic_create_24dp); 20972e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell editMenuItem.setTitle(R.string.menu_editContact); 2098d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else { 2099d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(false); 2100d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2101a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 2102a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell final MenuItem shareMenuItem = menu.findItem(R.id.menu_share); 2103a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell shareMenuItem.setVisible(isContactShareable()); 2104a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 210566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final MenuItem shortcutMenuItem = menu.findItem(R.id.menu_create_contact_shortcut); 210666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell shortcutMenuItem.setVisible(isShortcutCreatable()); 210766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell 21088a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return true; 2109d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 21108a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return false; 2111d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2112d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2113d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2114d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onOptionsItemSelected(MenuItem item) { 2115d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell switch (item.getItemId()) { 2116d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_star: 2117d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell toggleStar(item); 2118d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2119d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_edit: 2120d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData)) { 2121ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // This action is used to launch the contact selector, with the option of 2122ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // creating a new contact. Creating a new contact is an INSERT, while selecting 2123ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // an exisiting one is an edit. The fields in the edit screen will be 2124ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // prepopulated with data. 2125ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2126ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 2127ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.setType(Contacts.CONTENT_ITEM_TYPE); 2128ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2129ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Only pre-fill the name field if the provided display name is an organization 2130ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // name or better (e.g. structured name, nickname) 2131ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos if (mContactData.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) { 2132ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.NAME, mContactData.getDisplayName()); 2133ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2134ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos ArrayList<ContentValues> values = mContactData.getContentValues(); 2135ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Last time used and times used are aggregated values from the usage stat 2136ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // table. They need to be removed from data values so the SQL table can insert 2137ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // properly 2138ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos for (ContentValues value : values) { 2139ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos value.remove(Data.LAST_TIME_USED); 2140ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos value.remove(Data.TIMES_USED); 2141ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2142ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.DATA, values); 2143ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2144ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // If the contact can only export to the same account, add it to the intent. 2145ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Otherwise the ContactEditorFragment will show a dialog for selecting an 2146ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // account. 2147ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos if (mContactData.getDirectoryExportSupport() == 2148ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY) { 2149ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.ACCOUNT, 2150ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos new Account(mContactData.getDirectoryAccountName(), 2151ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos mContactData.getDirectoryAccountType())); 2152ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.DATA_SET, 2153ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos mContactData.getRawContacts().get(0).getDataSet()); 2154ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2155ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2156ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos startActivityForResult(intent, REQUEST_CODE_CONTACT_SELECTION_ACTIVITY); 2157d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (InvisibleContactUtil.isInvisibleAndAddable(mContactData, this)) { 2158d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell InvisibleContactUtil.addToDefaultGroup(mContactData, this); 2159d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 2160d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editContact(); 2161d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2162d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2163752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_share: 2164752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareContact(); 2165752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 2166752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_create_contact_shortcut: 2167752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell createLauncherShortcutWithContact(); 2168752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 2169d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell default: 2170d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return super.onOptionsItemSelected(item); 2171d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 217223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos } 2173edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann} 2174