QuickContactActivity.java revision 417309a770568d7b278abc91c46a739020e48157
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; 730319222b43927d4d9ce7e2a9070f3543661b5782Tyler Gunnimport android.telecom.PhoneAccount; 740319222b43927d4d9ce7e2a9070f3543661b5782Tyler Gunnimport android.telecom.TelecomManager; 75c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.BidiFormatter; 76c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.TextDirectionHeuristics; 77edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils; 78edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log; 792a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu; 802a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo; 81d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.Menu; 82d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.MenuInflater; 83eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.view.MenuItem; 84f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chenimport android.view.MotionEvent; 85edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View; 86edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener; 872a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.View.OnCreateContextMenuListener; 8810d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager; 89edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast; 90d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.widget.Toolbar; 91edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 9272b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService; 93d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.ContactsActivity; 942d150da246632b1649999cfabed776133b097775Brian Attwellimport com.android.contacts.NfcHandler; 95e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 96eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.CallUtil; 972a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.common.ClipboardUtils; 98eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.Collapser; 99eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.ContactsUtils; 100d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.editor.SelectAccountDialogFragment; 10170e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chenimport com.android.contacts.common.interactions.TouchPointManager; 10231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable; 103752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder; 104752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener; 1050d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager; 106cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact; 107cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader; 108cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact; 109428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType; 110d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.model.account.AccountWithDataSet; 111cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem; 112428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 113cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem; 114eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.EventDataItem; 115cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem; 116eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NicknameDataItem; 117eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NoteDataItem; 118eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.OrganizationDataItem; 119b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.common.model.dataitem.PhoneDataItem; 120eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.RelationDataItem; 121eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.SipAddressDataItem; 122eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredNameDataItem; 123eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredPostalDataItem; 124eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.WebsiteDataItem; 125eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.util.DateUtils; 126faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils; 127faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette; 128d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwellimport com.android.contacts.common.util.ViewUtil; 129333091ae754ddfc25714c14b9b89534be24379f9Paul Soulosimport com.android.contacts.detail.ContactDisplayUtils; 130f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulosimport com.android.contacts.editor.ContactEditorFragment; 131899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport com.android.contacts.interactions.CalendarInteractionsLoader; 132ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.interactions.CallLogInteractionsLoader; 1338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport com.android.contacts.interactions.ContactDeletionInteraction; 134b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.ContactInteraction; 135b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.SmsInteractionsLoader; 1362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry; 1372a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo; 1382ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryTag; 139e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwellimport com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener; 140e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter; 141eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.PhoneCapabilityTester; 142b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils; 143eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.StructuredPostalUtils; 144b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller; 145b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener; 14602eaf11669d25fd885606b3b0700358323532cddBrian Attwellimport com.android.contacts.widget.QuickContactImageView; 147e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions; 148e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 149e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 1502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList; 151899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport java.util.Arrays; 152eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Calendar; 153b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Collections; 154b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Comparator; 155eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Date; 156edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap; 157edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List; 158b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Map; 159edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 160edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/** 161edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads 162edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around 163edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}. 164edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 165d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellpublic class QuickContactActivity extends ContactsActivity { 1668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell /** 1688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * QuickContacts immediately takes up the full screen. All possible information is shown. 1698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * This value for {@link android.provider.ContactsContract.QuickContact#EXTRA_MODE} 1708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * should only be used by the Contacts app. 1718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell */ 1728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public static final int MODE_FULLY_EXPANDED = 4; 1738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 174edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String TAG = "QuickContact"; 175edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1769b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final String KEY_THEME_COLOR = "theme_color"; 1779b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 1789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150; 1798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1; 1802e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos private static final int DEFAULT_SCRIM_ALPHA = 0xC8; 1812e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos private static final int SCRIM_COLOR = Color.argb(DEFAULT_SCRIM_ALPHA, 0, 0, 0); 182ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos private static final int REQUEST_CODE_CONTACT_SELECTION_ACTIVITY = 2; 183ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms"; 184dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 185752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** This is the Intent action to install a shortcut in the launcher. */ 186752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private static final String ACTION_INSTALL_SHORTCUT = 187752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell "com.android.launcher.action.INSTALL_SHORTCUT"; 188edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 189edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @SuppressWarnings("deprecation") 190edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY; 191edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 192e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String MIMETYPE_GPLUS_PROFILE = 193e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos "vnd.android.cursor.item/vnd.googleplus.profile"; 1946a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String GPLUS_PROFILE_DATA_5_ADD_TO_CIRCLE = "addtocircle"; 1956a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String GPLUS_PROFILE_DATA_5_VIEW_PROFILE = "view"; 196e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String MIMETYPE_HANGOUTS = 197e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos "vnd.android.cursor.item/vnd.googleplus.profile.comm"; 1986a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String HANGOUTS_DATA_5_VIDEO = "hangout"; 1996a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String HANGOUTS_DATA_5_MESSAGE = "conversation"; 20048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private static final String CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY = 20148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos "com.android.contacts.quickcontact.QuickContactActivity"; 202e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 20363176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell /** 20463176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell * The URI used to load the the Contact. Once the contact is loaded, use Contact#getLookupUri() 20563176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell * instead of referencing this URI. 20663176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell */ 207edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private Uri mLookupUri; 208edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private String[] mExcludeMimes; 2098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mExtraMode; 2108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mStatusBarColor; 2118a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private boolean mHasAlreadyBeenOpened; 21297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private boolean mOnlyOnePhoneNumber; 21397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private boolean mOnlyOneEmail; 214edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 21502eaf11669d25fd885606b3b0700358323532cddBrian Attwell private QuickContactImageView mPhotoView; 216eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private ExpandingEntryCardView mContactCard; 2176095369885edcca566a812b551886e29c7ff8039Brian Attwell private ExpandingEntryCardView mNoContactDetailsCard; 218b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private ExpandingEntryCardView mRecentCard; 219eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private ExpandingEntryCardView mAboutCard; 220b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private MultiShrinkScroller mScroller; 221d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private SelectAccountDialogFragmentListener mSelectAccountFragmentListener; 2226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private AsyncTask<Void, Void, Cp2DataCardModel> mEntriesAndActionsTask; 22330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell private AsyncTask<Void, Void, Void> mRecentDataTask; 2246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 2256bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * The last copy of Cp2DataCardModel that was passed to {@link #populateContactAndAboutCard}. 2266bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 2276bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private Cp2DataCardModel mCachedCp2DataCardModel; 228f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell /** 229f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * This scrim's opacity is controlled in two different ways. 1) Before the initial entrance 230f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * animation finishes, the opacity is animated by a value animator. This is designed to 231f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * distract the user from the length of the initial loading time. 2) After the initial 232f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * entrance animation, the opacity is directly related to scroll position. 233f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell */ 2349b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private ColorDrawable mWindowScrim; 235f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell private boolean mIsEntranceAnimationFinished; 236a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell private MaterialColorMapUtils mMaterialColorMapUtils; 2378477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell private boolean mIsExitAnimationInProgress; 2388571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell private boolean mHasComputedThemeColor; 239edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 240a42ef76251778161d27bc07db214b8c81720e476Paul Soulos /** 241a42ef76251778161d27bc07db214b8c81720e476Paul Soulos * Used to stop the ExpandingEntry cards from adjusting between an entry click and the intent 242a42ef76251778161d27bc07db214b8c81720e476Paul Soulos * being launched. 243a42ef76251778161d27bc07db214b8c81720e476Paul Soulos */ 244a42ef76251778161d27bc07db214b8c81720e476Paul Soulos private boolean mHasIntentLaunched; 245a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 2466cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee private Contact mContactData; 2479815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann private ContactLoader mContactLoader; 2489b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private PorterDuffColorFilter mColorFilter; 2499815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann 2509758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter(); 2519758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus 252edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 253cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * {@link #LEADING_MIMETYPES} is used to sort MIME-types. 254edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 255edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog, 256edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * in the order specified here.</p> 257edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 258edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> LEADING_MIMETYPES = Lists.newArrayList( 259cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE, 260405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos StructuredPostal.CONTENT_ITEM_TYPE); 261edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 262a153dba33c2152332c5706178a367f52b0550723Paul Soulos private static final List<String> SORTED_ABOUT_CARD_MIMETYPES = Lists.newArrayList( 263a153dba33c2152332c5706178a367f52b0550723Paul Soulos Nickname.CONTENT_ITEM_TYPE, 264a153dba33c2152332c5706178a367f52b0550723Paul Soulos // Phonetic name is inserted after nickname if it is available. 265a153dba33c2152332c5706178a367f52b0550723Paul Soulos // No mimetype for phonetic name exists. 266a153dba33c2152332c5706178a367f52b0550723Paul Soulos Website.CONTENT_ITEM_TYPE, 267a153dba33c2152332c5706178a367f52b0550723Paul Soulos Organization.CONTENT_ITEM_TYPE, 268a153dba33c2152332c5706178a367f52b0550723Paul Soulos Event.CONTENT_ITEM_TYPE, 269a153dba33c2152332c5706178a367f52b0550723Paul Soulos Relation.CONTENT_ITEM_TYPE, 270a153dba33c2152332c5706178a367f52b0550723Paul Soulos Im.CONTENT_ITEM_TYPE, 271a153dba33c2152332c5706178a367f52b0550723Paul Soulos GroupMembership.CONTENT_ITEM_TYPE, 272a153dba33c2152332c5706178a367f52b0550723Paul Soulos Identity.CONTENT_ITEM_TYPE, 273a153dba33c2152332c5706178a367f52b0550723Paul Soulos Note.CONTENT_ITEM_TYPE); 274eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 275c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell private static final BidiFormatter sBidiFormatter = BidiFormatter.getInstance(); 276c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell 277b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background contact loader */ 278b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_CONTACT_ID = 0; 279b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 280ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_PHONES = 281ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_PHONES"; 282ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 283b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background Sms Loader */ 284b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_SMS_ID = 1; 285b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int MAX_SMS_RETRIEVE = 3; 286ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 287ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the back Calendar Loader */ 288899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int LOADER_CALENDAR_ID = 2; 289ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_EMAILS = 290ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_EMAILS"; 291899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_PAST_CALENDAR_RETRIEVE = 3; 292899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_FUTURE_CALENDAR_RETRIEVE = 3; 293899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 29440d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos 1L * 24L * 60L * 60L * 1000L /* 1 day */; 295899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 29640d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos 7L * 24L * 60L * 60L * 1000L /* 7 days */; 297899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 298ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the background Call Log Loader */ 299ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int LOADER_CALL_LOG_ID = 3; 300ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int MAX_CALL_LOG_RETRIEVE = 3; 3016095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int MIN_NUM_CONTACT_ENTRIES_SHOWN = 3; 3026095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3; 3036095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int CARD_ENTRY_ID_EDIT_CONTACT = -2; 304ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 305ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 306ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int[] mRecentLoaderIds = new int[]{ 307ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_SMS_ID, 308ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALENDAR_ID, 309ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID}; 310a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos private Map<Integer, List<ContactInteraction>> mRecentLoaderResults = new HashMap<>(); 311b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 312d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment"; 3136cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 3142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos final OnClickListener mEntryClickHandler = new OnClickListener() { 3152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 3162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void onClick(View v) { 3172ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final Object entryTagObject = v.getTag(); 3182ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos if (entryTagObject == null || !(entryTagObject instanceof EntryTag)) { 3192ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos Log.w(TAG, "EntryTag was not used correctly"); 3206095369885edcca566a812b551886e29c7ff8039Brian Attwell return; 3216095369885edcca566a812b551886e29c7ff8039Brian Attwell } 3222ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final EntryTag entryTag = (EntryTag) entryTagObject; 3232ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final Intent intent = entryTag.getIntent(); 3242ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final int dataId = entryTag.getId(); 3252ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 3262ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) { 3272ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos editContact(); 3282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return; 3292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 330ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 331ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // Default to USAGE_TYPE_CALL. Usage is summed among all types for sorting each data id 332ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // so the exact usage type is not necessary in all cases 333ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos String usageType = DataUsageFeedback.USAGE_TYPE_CALL; 334ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 33520bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos final Uri intentUri = intent.getData(); 33620bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos if ((intentUri != null && intentUri.getScheme() != null && 3371cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner intentUri.getScheme().equals(ContactsUtils.SCHEME_SMSTO)) || 338ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos (intent.getType() != null && intent.getType().equals(MIMETYPE_SMS))) { 339ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos usageType = DataUsageFeedback.USAGE_TYPE_SHORT_TEXT; 340ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 341ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 342ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // Data IDs start at 1 so anything less is invalid 343ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos if (dataId > 0) { 34420bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos final Uri dataUsageUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 345ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .appendPath(String.valueOf(dataId)) 346ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, usageType) 347ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .build(); 348ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos final boolean successful = getContentResolver().update( 34920bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos dataUsageUri, new ContentValues(), null, null) > 0; 350ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos if (!successful) { 351ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos Log.w(TAG, "DataUsageFeedback increment failed"); 352ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 353ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } else { 354ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos Log.w(TAG, "Invalid Data ID"); 355ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 356ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 35770e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen // Pass the touch point through the intent for use in the InCallUI 35870e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen if (Intent.ACTION_CALL.equals(intent.getAction())) { 3591f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen if (TouchPointManager.getInstance().hasValidPoint()) { 36070e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen Bundle extras = new Bundle(); 3611f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen extras.putParcelable(TouchPointManager.TOUCH_POINT, 3621f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen TouchPointManager.getInstance().getPoint()); 3630319222b43927d4d9ce7e2a9070f3543661b5782Tyler Gunn intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras); 36470e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen } 36570e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen } 36670e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen 367793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 368793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos 3692e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos // Force the window dim amount to the scrim value for app transition animations 3702e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos // The scrim may be removed before the window transitions to the new activity, which 3712e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos // can cause a flicker in the status and navigation bar. Set dim alone does not work 3722e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos // well because the request is passed through IPC which makes it slow to animate. 3732e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, 3742e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos WindowManager.LayoutParams.FLAG_DIM_BEHIND); 3752e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos getWindow().setDimAmount(mWindowScrim.getAlpha() / DEFAULT_SCRIM_ALPHA); 3762e6387f0bef606bb4be3facaedeafd080156d6c6Paul Soulos 377a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 378417309a770568d7b278abc91c46a739020e48157Jay Shrauner try { 379417309a770568d7b278abc91c46a739020e48157Jay Shrauner startActivity(intent); 380417309a770568d7b278abc91c46a739020e48157Jay Shrauner } catch (ActivityNotFoundException ex) { 381417309a770568d7b278abc91c46a739020e48157Jay Shrauner Toast.makeText(QuickContactActivity.this, R.string.missing_app, 382417309a770568d7b278abc91c46a739020e48157Jay Shrauner Toast.LENGTH_SHORT).show(); 383417309a770568d7b278abc91c46a739020e48157Jay Shrauner } 3842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }; 3862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 387e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell final ExpandingEntryCardViewListener mExpandingEntryCardViewListener 388e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell = new ExpandingEntryCardViewListener() { 389e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell @Override 390e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell public void onCollapse(int heightDelta) { 391e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell mScroller.prepareForShrinkingScrollChild(heightDelta); 392e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell } 3930cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 3940cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 3950cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onExpand(int heightDelta) { 3960cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller.prepareForExpandingScrollChild(); 3970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 398e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell }; 399e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell 40097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private interface ContextMenuIds { 40197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int COPY_TEXT = 0; 40297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int CLEAR_DEFAULT = 1; 40397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int SET_DEFAULT = 2; 40497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 40597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 4062a4207fb39330e840436215c896cde911489e111Paul Soulos private final OnCreateContextMenuListener mEntryContextMenuListener = 4072a4207fb39330e840436215c896cde911489e111Paul Soulos new OnCreateContextMenuListener() { 4082a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 4092a4207fb39330e840436215c896cde911489e111Paul Soulos public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 4102a4207fb39330e840436215c896cde911489e111Paul Soulos if (menuInfo == null) { 4112a4207fb39330e840436215c896cde911489e111Paul Soulos return; 4122a4207fb39330e840436215c896cde911489e111Paul Soulos } 41397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo; 4142a4207fb39330e840436215c896cde911489e111Paul Soulos menu.setHeaderTitle(info.getCopyText()); 41597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.COPY_TEXT, 41697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.copy_text)); 41797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 41897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Don't allow setting or clearing of defaults for non-editable contacts 41997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (!isContactEditable()) { 42097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return; 42197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 42297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 42397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final String selectedMimeType = info.getMimeType(); 42497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 42597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Defaults to true will only enable the detail to be copied to the clipboard. 42697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos boolean onlyOneOfMimeType = true; 42797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 42897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Only allow primary support for Phone and Email content types 42997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) { 43097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos onlyOneOfMimeType = mOnlyOnePhoneNumber; 43197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) { 43297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos onlyOneOfMimeType = mOnlyOneEmail; 43397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 43497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 43597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Checking for previously set default 43697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (info.isSuperPrimary()) { 43797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT, 43897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.clear_default)); 43997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } else if (!onlyOneOfMimeType) { 44097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT, 44197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.set_default)); 44297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 4432a4207fb39330e840436215c896cde911489e111Paul Soulos } 4442a4207fb39330e840436215c896cde911489e111Paul Soulos }; 4452a4207fb39330e840436215c896cde911489e111Paul Soulos 4462a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 4472a4207fb39330e840436215c896cde911489e111Paul Soulos public boolean onContextItemSelected(MenuItem item) { 4482a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo menuInfo; 4492a4207fb39330e840436215c896cde911489e111Paul Soulos try { 4502a4207fb39330e840436215c896cde911489e111Paul Soulos menuInfo = (EntryContextMenuInfo) item.getMenuInfo(); 4512a4207fb39330e840436215c896cde911489e111Paul Soulos } catch (ClassCastException e) { 4522a4207fb39330e840436215c896cde911489e111Paul Soulos Log.e(TAG, "bad menuInfo", e); 4532a4207fb39330e840436215c896cde911489e111Paul Soulos return false; 4542a4207fb39330e840436215c896cde911489e111Paul Soulos } 4552a4207fb39330e840436215c896cde911489e111Paul Soulos 45697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos switch (item.getItemId()) { 45797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.COPY_TEXT: 45897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(), 45997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos true); 46097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 46197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.SET_DEFAULT: 46297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final Intent setIntent = ContactSaveService.createSetSuperPrimaryIntent(this, 46397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menuInfo.getId()); 46497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos this.startService(setIntent); 46597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 46697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.CLEAR_DEFAULT: 46797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final Intent clearIntent = ContactSaveService.createClearPrimaryIntent(this, 46897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menuInfo.getId()); 46997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos this.startService(clearIntent); 47097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 47197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos default: 47297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos throw new IllegalArgumentException("Unknown menu option " + item.getItemId()); 47397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 4742a4207fb39330e840436215c896cde911489e111Paul Soulos } 4752a4207fb39330e840436215c896cde911489e111Paul Soulos 476d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 477d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Headless fragment used to handle account selection callbacks invoked from 478d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * {@link DirectoryContactUtil}. 479d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 480d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public static class SelectAccountDialogFragmentListener extends Fragment 481d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell implements SelectAccountDialogFragment.Listener { 482d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 483d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private QuickContactActivity mQuickContactActivity; 484d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 485d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public SelectAccountDialogFragmentListener() {} 486d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 487d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 488d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) { 489d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell DirectoryContactUtil.createCopy(mQuickContactActivity.mContactData.getContentValues(), 490d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell account, mQuickContactActivity); 491d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 492d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 493d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 494d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountSelectorCancelled() {} 495d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 496d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 497d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Set the parent activity. Since rotation can cause this fragment to be used across 498d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * more than one activity instance, we need to explicitly set this value instead 499d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * of making this class non-static. 500d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 501d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void setQuickContactActivity(QuickContactActivity quickContactActivity) { 502d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mQuickContactActivity = quickContactActivity; 503d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 504d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 505d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 506b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final MultiShrinkScrollerListener mMultiShrinkScrollerListener 507b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell = new MultiShrinkScrollerListener() { 508b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 509b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onScrolledOffBottom() { 510f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell finish(); 511b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 5128a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5138a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 5148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onEnterFullscreen() { 5158a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 5168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 5198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onExitFullscreen() { 5208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 5218a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5228477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 5238477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 5248477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell public void onStartScrollOffBottom() { 5258477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsExitAnimationInProgress = true; 5268477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 5278477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 5288477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 529f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void onEntranceAnimationDone() { 530f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = true; 531f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 532f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 533f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell @Override 534f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void onTransparentViewHeightChange(float ratio) { 535f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell if (mIsEntranceAnimationFinished) { 536f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mWindowScrim.setAlpha((int) (0xFF * ratio)); 5378477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 5388477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 539b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell }; 540b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 541eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 542eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 543eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Data items are compared to the same mimetype based off of three qualities: 544eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 1. Super primary 545eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 2. Primary 546eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 3. Times used 547eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 548eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final Comparator<DataItem> mWithinMimeTypeDataItemComparator = 549eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos new Comparator<DataItem>() { 550eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos @Override 551eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public int compare(DataItem lhs, DataItem rhs) { 552eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!lhs.getMimeType().equals(rhs.getMimeType())) { 553eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Log.wtf(TAG, "Comparing DataItems with different mimetypes lhs.getMimeType(): " + 554eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getMimeType() + " rhs.getMimeType(): " + rhs.getMimeType()); 555eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 0; 556eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 557eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 558eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lhs.isSuperPrimary()) { 559eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 560eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (rhs.isSuperPrimary()) { 561eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 562eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (lhs.isPrimary() && !rhs.isPrimary()) { 563eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 564eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (!lhs.isPrimary() && rhs.isPrimary()) { 565eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 566eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 567eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int lhsTimesUsed = 568eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 569eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int rhsTimesUsed = 570eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 571eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 572eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return rhsTimesUsed - lhsTimesUsed; 573eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 574eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 575eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos }; 576eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 577cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos /** 578cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * Sorts among different mimetypes based off: 579cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 1. Times used 580cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 2. Last time used 581cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 3. Statically defined 582cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos */ 583eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final Comparator<List<DataItem>> mAmongstMimeTypeDataItemComparator = 584eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos new Comparator<List<DataItem>> () { 585eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos @Override 586eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public int compare(List<DataItem> lhsList, List<DataItem> rhsList) { 587eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataItem lhs = lhsList.get(0); 588eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataItem rhs = rhsList.get(0); 589eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int lhsTimesUsed = lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 590eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int rhsTimesUsed = rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 591eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int timesUsedDifference = rhsTimesUsed - lhsTimesUsed; 592eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (timesUsedDifference != 0) { 593eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return timesUsedDifference; 594eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 595eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 596eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long lhsLastTimeUsed = 597eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getLastTimeUsed() == null ? 0 : lhs.getLastTimeUsed(); 598eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long rhsLastTimeUsed = 599eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos rhs.getLastTimeUsed() == null ? 0 : rhs.getLastTimeUsed(); 600eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long lastTimeUsedDifference = rhsLastTimeUsed - lhsLastTimeUsed; 601eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lastTimeUsedDifference > 0) { 602eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 603eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (lastTimeUsedDifference < 0) { 604eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 605eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 606eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 607eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Times used and last time used are the same. Resort to statically defined. 608eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String lhsMimeType = lhs.getMimeType(); 609eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String rhsMimeType = rhs.getMimeType(); 610eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (String mimeType : LEADING_MIMETYPES) { 611eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lhsMimeType.equals(mimeType)) { 612eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 613eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (rhsMimeType.equals(mimeType)) { 614eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 615eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 616eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 617eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 0; 618eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 619eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos }; 620eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 621edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @Override 622f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen public boolean dispatchTouchEvent(MotionEvent ev) { 623f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen if (ev.getAction() == MotionEvent.ACTION_DOWN) { 624f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY()); 625f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen } 626f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen return super.dispatchTouchEvent(ev); 627f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen } 628f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen 629f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen @Override 6308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onCreate(Bundle savedInstanceState) { 6318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onCreate()"); 6328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onCreate(savedInstanceState); 633edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getWindow().setStatusBarColor(Color.TRANSPARENT); 6352426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann 636d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(getIntent()); 637dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 63810d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa // Show QuickContact in front of soft input 63910d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 64010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 64110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa 642edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann setContentView(R.layout.quickcontact_activity); 643edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 644a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell mMaterialColorMapUtils = new MaterialColorMapUtils(getResources()); 645a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell 6460cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller); 6470cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 648eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card); 6496095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card); 650b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card); 651eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card); 652edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6536095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setOnClickListener(mEntryClickHandler); 654eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setOnClickListener(mEntryClickHandler); 655eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setExpandButtonText( 65623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos getResources().getString(R.string.expanding_entry_card_view_see_all)); 6572a4207fb39330e840436215c896cde911489e111Paul Soulos mContactCard.setOnCreateContextMenuListener(mEntryContextMenuListener); 658b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 659b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setOnClickListener(mEntryClickHandler); 660b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setTitle(getResources().getString(R.string.recent_card_title)); 661edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 662eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mAboutCard.setOnClickListener(mEntryClickHandler); 6632a4207fb39330e840436215c896cde911489e111Paul Soulos mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener); 664eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 66502eaf11669d25fd885606b3b0700358323532cddBrian Attwell mPhotoView = (QuickContactImageView) findViewById(R.id.photo); 66663176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell final View transparentView = findViewById(R.id.transparent_view); 6670d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell if (mScroller != null) { 66863176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell transparentView.setOnClickListener(new OnClickListener() { 6690d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell @Override 6700d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell public void onClick(View v) { 6710d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell mScroller.scrollOffBottom(); 6720d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 6730d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell }); 6740d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 675edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 676d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell // Allow a shadow to be shown under the toolbar. 677d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources()); 678d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell 679d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 680d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell setActionBar(toolbar); 6819b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getActionBar().setTitle(null); 6829b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // Put a TextView with a known resource id into the ActionBar. This allows us to easily 6839b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // find the correct TextView location & size later. 6849b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell toolbar.addView(getLayoutInflater().inflate(R.layout.quickcontact_title_placeholder, null)); 6856219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee 6868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = savedInstanceState != null; 687f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = mHasAlreadyBeenOpened; 6889b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mWindowScrim = new ColorDrawable(SCRIM_COLOR); 689f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mWindowScrim.setAlpha(0); 6909b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getWindow().setBackgroundDrawable(mWindowScrim); 691edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 692c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell mScroller.initialize(mMultiShrinkScrollerListener, mExtraMode == MODE_FULLY_EXPANDED); 693ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // mScroller needs to perform asynchronous measurements after initalize(), therefore 694ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // we can't mark this as GONE. 695ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.INVISIBLE); 6968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 6979b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell setHeaderNameText(R.string.missing_name); 6989b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 699d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener= (SelectAccountDialogFragmentListener) getFragmentManager() 700d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .findFragmentByTag(FRAGMENT_TAG_SELECT_ACCOUNT); 701d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mSelectAccountFragmentListener == null) { 702d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener = new SelectAccountDialogFragmentListener(); 703d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell getFragmentManager().beginTransaction().add(0, mSelectAccountFragmentListener, 704d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell FRAGMENT_TAG_SELECT_ACCOUNT).commit(); 705d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setRetainInstance(true); 706d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 707d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setQuickContactActivity(this); 70823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 709f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ true, 710f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell new Runnable() { 711f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell @Override 712f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void run() { 713f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell if (!mHasAlreadyBeenOpened) { 714f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell // The initial scrim opacity must match the scrim opacity that would be 715f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell // achieved by scrolling to the starting position. 716f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final float alphaRatio = mExtraMode == MODE_FULLY_EXPANDED ? 717f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 1 : mScroller.getStartingTransparentHeightRatio(); 718f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final int duration = getResources().getInteger( 719f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell android.R.integer.config_shortAnimTime); 720f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final int desiredAlpha = (int) (0xFF * alphaRatio); 721f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell ObjectAnimator o = ObjectAnimator.ofInt(mWindowScrim, "alpha", 0, 722f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell desiredAlpha).setDuration(duration); 723f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 724f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell o.start(); 725f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 726f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 727f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell }); 728f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 7299b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (savedInstanceState != null) { 7309b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell final int color = savedInstanceState.getInt(KEY_THEME_COLOR, 0); 731ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 732ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell new Runnable() { 733ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell @Override 734ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell public void run() { 735ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for the pre draw before setting the initial scroll 736ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // value. Prior to pre draw all scroll values are invalid. 737ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (mHasAlreadyBeenOpened) { 738ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.VISIBLE); 739ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setScroll(mScroller.getScrollNeededToBeFullScreen()); 740ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 741ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for pre draw for setting the theme color. Setting the 742ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // header tint before the MultiShrinkScroller has been measured will 743ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // cause incorrect tinting calculations. 744ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (color != 0) { 745a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell setThemeColor(mMaterialColorMapUtils 746a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell .calculatePrimaryAndSecondaryColor(color)); 7479b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 748ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 749ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell }); 7509b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7519b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 7528a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 7538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 7548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 755405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos @Override 756405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos protected void onActivityResult(int requestCode, int resultCode, Intent data) { 7578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (requestCode == REQUEST_CODE_CONTACT_EDITOR_ACTIVITY && 7588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) { 7598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // The contact that we were showing has been deleted. 7608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell finish(); 761ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } else if (requestCode == REQUEST_CODE_CONTACT_SELECTION_ACTIVITY && 762ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos resultCode != RESULT_CANCELED) { 763ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos processIntent(data); 764b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 7658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 766dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 7678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 7688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onNewIntent(Intent intent) { 7698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onNewIntent(intent); 7708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 771f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = true; 7728571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = false; 773d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(intent); 774d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 775d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 7769b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell @Override 7779b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell public void onSaveInstanceState(Bundle savedInstanceState) { 7789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell super.onSaveInstanceState(savedInstanceState); 7799b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mColorFilter != null) { 7809b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell savedInstanceState.putInt(KEY_THEME_COLOR, mColorFilter.getColor()); 7819b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7829b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7839b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 784d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void processIntent(Intent intent) { 785f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos if (intent == null) { 786f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos finish(); 787f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos return; 788f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos } 789d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell Uri lookupUri = intent.getData(); 790d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 791d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Check to see whether it comes from the old version. 792d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) { 793d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final long rawContactId = ContentUris.parseId(lookupUri); 794d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell lookupUri = RawContacts.getContactLookupUri(getContentResolver(), 795d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId)); 796d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 797d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE, 798d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell QuickContact.MODE_LARGE); 799d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Uri oldLookupUri = mLookupUri; 800d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 801d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri"); 802d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES); 803d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (oldLookupUri == null) { 804d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactLoader = (ContactLoader) getLoaderManager().initLoader( 805d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 806d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (oldLookupUri != mLookupUri) { 807d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // After copying a directory contact, the contact URI changes. Therefore, 808d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // we need to restart the loader and reload the new contact. 80959a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell destroyInteractionLoaders(); 810405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos mContactLoader = (ContactLoader) getLoaderManager().restartLoader( 811405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 81259a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell mCachedCp2DataCardModel = null; 813d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 8142d150da246632b1649999cfabed776133b097775Brian Attwell 8152d150da246632b1649999cfabed776133b097775Brian Attwell NfcHandler.register(this, mLookupUri); 8162426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann } 817edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 81859a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell private void destroyInteractionLoaders() { 81959a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell for (int interactionLoaderId : mRecentLoaderIds) { 82059a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell getLoaderManager().destroyLoader(interactionLoaderId); 82159a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell } 82259a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell } 82359a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell 824b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private void runEntranceAnimation() { 8258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mHasAlreadyBeenOpened) { 8268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 8278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8288a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 829c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell mScroller.scrollUpForEntranceAnimation(mExtraMode != MODE_FULLY_EXPANDED); 830b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 831b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 83281281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 833d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void setHeaderNameText(int resId) { 8349b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 835f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(getText(resId) == null ? null : getText(resId).toString()); 8369b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 83781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 83881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 83981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 840f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell private void setHeaderNameText(String value) { 841d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (!TextUtils.isEmpty(value)) { 8429b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 843f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(value); 8449b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 84581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 84681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 84781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 84881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** 849edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Check if the given MIME-type appears in the list of excluded MIME-types 850edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * that the most-recent caller requested. 851edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 852edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private boolean isMimeExcluded(String mimeType) { 853edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (mExcludeMimes == null) return false; 854edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String excludedMime : mExcludeMimes) { 855edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (TextUtils.equals(excludedMime, mimeType)) { 856edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 857edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 858edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 859edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 860edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 861edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 862edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 863cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann * Handle the result from the ContactLoader 864edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 8658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void bindContactData(final Contact data) { 8668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("bindContactData"); 8676cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee mContactData = data; 868d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell invalidateOptionsMenu(); 869edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 8708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 8718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("Set display photo & name"); 872dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 87302eaf11669d25fd885606b3b0700358323532cddBrian Attwell mPhotoView.setIsBusiness(mContactData.isDisplayNameFromOrganization()); 8746219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee mPhotoSetter.setupContactPhoto(data, mPhotoView); 87531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell extractAndApplyTintFromPhotoViewAsynchronously(); 8764936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell analyzeWhitenessOfPhotoAsynchronously(); 877333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos setHeaderNameText(ContactDisplayUtils.getDisplayName(this, data).toString()); 878edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 8798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 880dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 8816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mEntriesAndActionsTask = new AsyncTask<Void, Void, Cp2DataCardModel>() { 8828a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 8846bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell protected Cp2DataCardModel doInBackground( 885eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Void... params) { 886eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return generateDataModelFromContact(data); 8878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 8906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell protected void onPostExecute(Cp2DataCardModel cardDataModel) { 8916bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell super.onPostExecute(cardDataModel); 8928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Check that original AsyncTask parameters are still valid and the activity 8938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // is still running before binding to UI. A new intent could invalidate 8948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the results, for example. 8958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (data == mContactData && !isCancelled()) { 8966bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell bindDataToCards(cardDataModel); 8978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell showActivity(); 8988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }; 9018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.execute(); 9028a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9038a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void bindDataToCards(Cp2DataCardModel cp2DataCardModel) { 9056bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell startInteractionLoaders(cp2DataCardModel); 9066bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell populateContactAndAboutCard(cp2DataCardModel); 907eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 908eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 9096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void startInteractionLoaders(Cp2DataCardModel cp2DataCardModel) { 9106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Map<String, List<DataItem>> dataItemsMap = cp2DataCardModel.dataItemsMap; 9116bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> phoneDataItems = dataItemsMap.get(Phone.CONTENT_ITEM_TYPE); 91297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (phoneDataItems != null && phoneDataItems.size() == 1) { 91397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mOnlyOnePhoneNumber = true; 91497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 915eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String[] phoneNumbers = null; 916eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (phoneDataItems != null) { 917eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phoneNumbers = new String[phoneDataItems.size()]; 918eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (int i = 0; i < phoneDataItems.size(); ++i) { 919eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phoneNumbers[i] = ((PhoneDataItem) phoneDataItems.get(i)).getNumber(); 920eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 921eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 922ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle phonesExtraBundle = new Bundle(); 923eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phonesExtraBundle.putStringArray(KEY_LOADER_EXTRA_PHONES, phoneNumbers); 924eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 925eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("start sms loader"); 9268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getLoaderManager().initLoader( 9278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell LOADER_SMS_ID, 928ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 929ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos mLoaderInteractionsCallbacks); 930ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.endSection(); 931ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 932ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.beginSection("start call log loader"); 933ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos getLoaderManager().initLoader( 934ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID, 935ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 9368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mLoaderInteractionsCallbacks); 937899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.endSection(); 9388a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 939eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 940899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.beginSection("start calendar loader"); 9416bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> emailDataItems = dataItemsMap.get(Email.CONTENT_ITEM_TYPE); 94297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (emailDataItems != null && emailDataItems.size() == 1) { 94397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mOnlyOneEmail = true; 94497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 945eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String[] emailAddresses = null; 946eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (emailDataItems != null) { 947eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailAddresses = new String[emailDataItems.size()]; 948eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (int i = 0; i < emailDataItems.size(); ++i) { 949eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailAddresses[i] = ((EmailDataItem) emailDataItems.get(i)).getAddress(); 950eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 951eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 952ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle emailsExtraBundle = new Bundle(); 953eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailsExtraBundle.putStringArray(KEY_LOADER_EXTRA_EMAILS, emailAddresses); 954899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos getLoaderManager().initLoader( 955899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos LOADER_CALENDAR_ID, 956ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos emailsExtraBundle, 957899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos mLoaderInteractionsCallbacks); 9588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 9598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void showActivity() { 9628a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller != null) { 9638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mScroller.setVisibility(View.VISIBLE); 9648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 9658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell new Runnable() { 9668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 9678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void run() { 9688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell runEntranceAnimation(); 9698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }); 9718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private List<List<Entry>> buildAboutCardEntries(Map<String, List<DataItem>> dataItemsMap) { 975a153dba33c2152332c5706178a367f52b0550723Paul Soulos final List<List<Entry>> aboutCardEntries = new ArrayList<>(); 976a153dba33c2152332c5706178a367f52b0550723Paul Soulos for (String mimetype : SORTED_ABOUT_CARD_MIMETYPES) { 9776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> mimeTypeItems = dataItemsMap.get(mimetype); 978a153dba33c2152332c5706178a367f52b0550723Paul Soulos if (mimeTypeItems == null) { 979a153dba33c2152332c5706178a367f52b0550723Paul Soulos continue; 980a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 9816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // Set aboutCardTitleOut = null, since SORTED_ABOUT_CARD_MIMETYPES doesn't contain 9826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // the name mimetype. 9836bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<Entry> aboutEntries = dataItemsToEntries(mimeTypeItems, 9846bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /* aboutCardTitleOut = */ null); 985a153dba33c2152332c5706178a367f52b0550723Paul Soulos if (aboutEntries.size() > 0) { 986a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(aboutEntries); 987a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 988a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 989a153dba33c2152332c5706178a367f52b0550723Paul Soulos return aboutCardEntries; 990a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 991a153dba33c2152332c5706178a367f52b0550723Paul Soulos 992a42ef76251778161d27bc07db214b8c81720e476Paul Soulos @Override 993a42ef76251778161d27bc07db214b8c81720e476Paul Soulos protected void onResume() { 994a42ef76251778161d27bc07db214b8c81720e476Paul Soulos super.onResume(); 995a42ef76251778161d27bc07db214b8c81720e476Paul Soulos // If returning from a launched activity, repopulate the contact and about card 996a42ef76251778161d27bc07db214b8c81720e476Paul Soulos if (mHasIntentLaunched) { 997a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = false; 9986bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell populateContactAndAboutCard(mCachedCp2DataCardModel); 999a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 100059a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell 100159a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell // When exiting the activity and resuming, we want to force a full reload of all the 100259a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell // interaction data in case something changed in the background. On screen rotation, 100359a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell // we don't need to do this. And, mCachedCp2DataCardModel will be null, so we won't. 100459a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell if (mCachedCp2DataCardModel != null) { 100559a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell destroyInteractionLoaders(); 100659a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell startInteractionLoaders(mCachedCp2DataCardModel); 100759a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell } 1008a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 1009a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 10106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void populateContactAndAboutCard(Cp2DataCardModel cp2DataCardModel) { 10116bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mCachedCp2DataCardModel = cp2DataCardModel; 10126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (mHasIntentLaunched || cp2DataCardModel == null) { 1013a42ef76251778161d27bc07db214b8c81720e476Paul Soulos return; 1014a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 1015eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("bind contact card"); 1016eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 10176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> contactCardEntries = cp2DataCardModel.contactCardEntries; 10186bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> aboutCardEntries = cp2DataCardModel.aboutCardEntries; 10196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String customAboutCardName = cp2DataCardModel.customAboutCardName; 1020eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1021eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (contactCardEntries.size() > 0) { 1022eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.initialize(contactCardEntries, 1023eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /* numInitialVisibleEntries = */ MIN_NUM_CONTACT_ENTRIES_SHOWN, 1024c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos /* isExpanded = */ mContactCard.isExpanded(), 102589966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos /* isAlwaysExpanded = */ false, 10260cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mExpandingEntryCardViewListener, 10270cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller); 1028eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setVisibility(View.VISIBLE); 1029eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 1030eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setVisibility(View.GONE); 1031eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1032eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 10338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1034eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("bind about card"); 1035c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos // Phonetic name is not a data item, so the entry needs to be created separately 1036c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos final String phoneticName = mContactData.getPhoneticName(); 1037c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos if (!TextUtils.isEmpty(phoneticName)) { 1038c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos Entry phoneticEntry = new Entry(/* viewId = */ -1, 1039c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* icon = */ null, 1040c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos getResources().getString(R.string.name_phonetic), 1041c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos phoneticName, 1042c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* text = */ null, 104323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* primaryContentDescription = */ null, 1044c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* intent = */ null, 1045c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateIcon = */ null, 1046c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateIntent = */ null, 1047c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateContentDescription = */ null, 1048c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* shouldApplyColor = */ false, 10492a4207fb39330e840436215c896cde911489e111Paul Soulos /* isEditable = */ false, 10502a4207fb39330e840436215c896cde911489e111Paul Soulos /* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName, 105197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos getResources().getString(R.string.name_phonetic), 105297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos /* mimeType = */ null, /* id = */ -1, /* isPrimary = */ false), 105348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, 105448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIntent = */ null, 105548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, 105648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* iconResourceId = */ 0); 1057c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos List<Entry> phoneticList = new ArrayList<>(); 1058c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos phoneticList.add(phoneticEntry); 1059a153dba33c2152332c5706178a367f52b0550723Paul Soulos // Phonetic name comes after nickname. Check to see if the first entry type is nickname 1060a0fa4c18dc111ceea9ff47f35ee01fecc1003578Paul Soulos if (aboutCardEntries.size() > 0 && aboutCardEntries.get(0).get(0).getHeader().equals( 1061a153dba33c2152332c5706178a367f52b0550723Paul Soulos getResources().getString(R.string.header_nickname_entry))) { 1062a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(1, phoneticList); 1063a153dba33c2152332c5706178a367f52b0550723Paul Soulos } else { 1064a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(0, phoneticList); 1065a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 1066c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos } 1067c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos 10686bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!TextUtils.isEmpty(customAboutCardName)) { 10696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mAboutCard.setTitle(customAboutCardName); 10706bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 10716bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 1072cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (aboutCardEntries.size() > 0) { 1073cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mAboutCard.initialize(aboutCardEntries, 1074cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* numInitialVisibleEntries = */ 1, 1075cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* isExpanded = */ true, 1076cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* isAlwaysExpanded = */ true, 1077cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mExpandingEntryCardViewListener, 1078cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mScroller); 1079cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } 10806095369885edcca566a812b551886e29c7ff8039Brian Attwell 10816095369885edcca566a812b551886e29c7ff8039Brian Attwell if (contactCardEntries.size() == 0 && aboutCardEntries.size() == 0) { 10826095369885edcca566a812b551886e29c7ff8039Brian Attwell initializeNoContactDetailCard(); 10836095369885edcca566a812b551886e29c7ff8039Brian Attwell } else { 10846095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setVisibility(View.GONE); 10856095369885edcca566a812b551886e29c7ff8039Brian Attwell } 10866095369885edcca566a812b551886e29c7ff8039Brian Attwell 1087a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos // If the Recent card is already initialized (all recent data is loaded), show the About 1088a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos // card if it has entries. Otherwise About card visibility will be set in bindRecentData() 1089a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos if (isAllRecentDataLoaded() && aboutCardEntries.size() > 0) { 1090a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos mAboutCard.setVisibility(View.VISIBLE); 1091a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos } 1092eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 1093eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1094eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1095eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 10966095369885edcca566a812b551886e29c7ff8039Brian Attwell * Create a card that shows "Add email" and "Add phone number" entries in grey. 10976095369885edcca566a812b551886e29c7ff8039Brian Attwell */ 10986095369885edcca566a812b551886e29c7ff8039Brian Attwell private void initializeNoContactDetailCard() { 10996095369885edcca566a812b551886e29c7ff8039Brian Attwell final Drawable phoneIcon = getResources().getDrawable( 11006095369885edcca566a812b551886e29c7ff8039Brian Attwell R.drawable.ic_phone_24dp).mutate(); 11016095369885edcca566a812b551886e29c7ff8039Brian Attwell final Entry phonePromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT, 11026095369885edcca566a812b551886e29c7ff8039Brian Attwell phoneIcon, getString(R.string.quickcontact_add_phone_number), 110323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* subHeader = */ null, /* text = */ null, /* primaryContentDescription = */ null, 110423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos getEditContactIntent(), 1105dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIcon = */ null, /* alternateIntent = */ null, 1106714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos /* alternateContentDescription = */ null, /* shouldApplyColor = */ true, 110748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* isEditable = */ false, /* EntryContextMenuInfo = */ null, 110848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, /* thirdIntent = */ null, 110948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, R.drawable.ic_phone_24dp); 11106095369885edcca566a812b551886e29c7ff8039Brian Attwell 11116095369885edcca566a812b551886e29c7ff8039Brian Attwell final Drawable emailIcon = getResources().getDrawable( 11126095369885edcca566a812b551886e29c7ff8039Brian Attwell R.drawable.ic_email_24dp).mutate(); 11136095369885edcca566a812b551886e29c7ff8039Brian Attwell final Entry emailPromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT, 11146095369885edcca566a812b551886e29c7ff8039Brian Attwell emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null, 111523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* text = */ null, /* primaryContentDescription = */ null, 111623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos getEditContactIntent(), /* alternateIcon = */ null, 1117dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIntent = */ null, /* alternateContentDescription = */ null, 11182a4207fb39330e840436215c896cde911489e111Paul Soulos /* shouldApplyColor = */ true, /* isEditable = */ false, 111948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null, 112048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdIntent = */ null, /* thirdContentDescription = */ null, 112148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos R.drawable.ic_email_24dp); 11226095369885edcca566a812b551886e29c7ff8039Brian Attwell 11236095369885edcca566a812b551886e29c7ff8039Brian Attwell final List<List<Entry>> promptEntries = new ArrayList<>(); 11246095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.add(new ArrayList<Entry>(1)); 11256095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.add(new ArrayList<Entry>(1)); 11266095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.get(0).add(phonePromptEntry); 11276095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.get(1).add(emailPromptEntry); 11286095369885edcca566a812b551886e29c7ff8039Brian Attwell 11296095369885edcca566a812b551886e29c7ff8039Brian Attwell final int subHeaderTextColor = getResources().getColor( 11306095369885edcca566a812b551886e29c7ff8039Brian Attwell R.color.quickcontact_entry_sub_header_text_color); 11316095369885edcca566a812b551886e29c7ff8039Brian Attwell final PorterDuffColorFilter greyColorFilter = 11326095369885edcca566a812b551886e29c7ff8039Brian Attwell new PorterDuffColorFilter(subHeaderTextColor, PorterDuff.Mode.SRC_ATOP); 1133c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos mNoContactDetailsCard.initialize(promptEntries, 2, /* isExpanded = */ true, 11340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos /* isAlwaysExpanded = */ true, mExpandingEntryCardViewListener, mScroller); 11356095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setVisibility(View.VISIBLE); 11366095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setEntryHeaderColor(subHeaderTextColor); 11376095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setColorAndFilter(subHeaderTextColor, greyColorFilter); 11386095369885edcca566a812b551886e29c7ff8039Brian Attwell } 11396095369885edcca566a812b551886e29c7ff8039Brian Attwell 11406095369885edcca566a812b551886e29c7ff8039Brian Attwell /** 1141eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Builds the {@link DataItem}s Map out of the Contact. 1142eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @param data The contact to build the data from. 1143eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @return A pair containing a list of data items sorted within mimetype and sorted 1144eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * amongst mimetype. The map goes from mimetype string to the sorted list of data items within 1145eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * mimetype 1146eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 11476bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private Cp2DataCardModel generateDataModelFromContact( 1148eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Contact data) { 1149eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("Build data items map"); 1150eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1151eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Map<String, List<DataItem>> dataItemsMap = new HashMap<>(); 11528bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell 11538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final ResolveCache cache = ResolveCache.getInstance(this); 1154851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContact rawContact : data.getRawContacts()) { 1155851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (DataItem dataItem : rawContact.getDataItems()) { 1156eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItem.setRawContactId(rawContact.getId()); 1157eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1158851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String mimeType = dataItem.getMimeType(); 1159eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (mimeType == null) continue; 1160eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 116147b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final AccountType accountType = rawContact.getAccountType(this); 116247b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final DataKind dataKind = AccountTypeManager.getInstance(this) 116347b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng .getKindOrFallback(accountType, mimeType); 1164eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataKind == null) continue; 1165cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1166eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItem.setDataKind(dataKind); 1167b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1168eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean hasData = !TextUtils.isEmpty(dataItem.buildDataString(this, 1169eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataKind)); 1170899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 1171eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (isMimeExcluded(mimeType) || !hasData) continue; 1172edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1173eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos List<DataItem> dataItemListByType = dataItemsMap.get(mimeType); 1174eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataItemListByType == null) { 1175eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemListByType = new ArrayList<>(); 1176eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemsMap.put(mimeType, dataItemListByType); 1177edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1178eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemListByType.add(dataItem); 1179edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1180edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 11818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 1182edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1183eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("sort within mimetypes"); 118416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos /* 118516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * Sorting is a multi part step. The end result is to a have a sorted list of the most 1186eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * used data items, one per mimetype. Then, within each mimetype, the list of data items 1187eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * for that type is also sorted, based off of {super primary, primary, times used} in that 1188eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * order. 118916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos */ 1190eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<List<DataItem>> dataItemsList = new ArrayList<>(); 1191eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (List<DataItem> mimeTypeDataItems : dataItemsMap.values()) { 1192eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Remove duplicate data items 1193eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collapser.collapseList(mimeTypeDataItems, this); 1194eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Sort within mimetype 1195eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collections.sort(mimeTypeDataItems, mWithinMimeTypeDataItemComparator); 1196eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Add to the list of data item lists 1197eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemsList.add(mimeTypeDataItems); 1198edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1199eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 1200edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1201eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("sort amongst mimetypes"); 1202eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Sort amongst mimetypes to bubble up the top data items for the contact card 1203eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collections.sort(dataItemsList, mAmongstMimeTypeDataItemComparator); 1204eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 120516339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos 12066bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Trace.beginSection("cp2 data items to entries"); 12076bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12086bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> contactCardEntries = new ArrayList<>(); 12096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> aboutCardEntries = buildAboutCardEntries(dataItemsMap); 12106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final MutableString aboutCardName = new MutableString(); 12116bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell for (int i = 0; i < dataItemsList.size(); ++i) { 12136bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> dataItemsByMimeType = dataItemsList.get(i); 12146bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final DataItem topDataItem = dataItemsByMimeType.get(0); 12156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (SORTED_ABOUT_CARD_MIMETYPES.contains(topDataItem.getMimeType())) { 12166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // About card mimetypes are built in buildAboutCardEntries, skip here 12176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell continue; 12186bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } else { 12196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell List<Entry> contactEntries = dataItemsToEntries(dataItemsList.get(i), 12206bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell aboutCardName); 12216bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (contactEntries.size() > 0) { 12226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell contactCardEntries.add(contactEntries); 12236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12256bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12266bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12276bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Trace.endSection(); 12286bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Cp2DataCardModel dataModel = new Cp2DataCardModel(); 12306bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.customAboutCardName = aboutCardName.value; 12316bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.aboutCardEntries = aboutCardEntries; 12326bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.contactCardEntries = contactCardEntries; 12336bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.dataItemsMap = dataItemsMap; 12346bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell return dataModel; 12356bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12366bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12376bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 12386bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * Class used to hold the About card and Contact cards' data model that gets generated 12396bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * on a background thread. All data is from CP2. 12406bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 12416bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static class Cp2DataCardModel { 12426bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 12436bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * A map between a mimetype string and the corresponding list of data items. The data items 12446bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * are in sorted order using mWithinMimeTypeDataItemComparator. 12456bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 12466bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public Map<String, List<DataItem>> dataItemsMap; 12476bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public List<List<Entry>> aboutCardEntries; 12486bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public List<List<Entry>> contactCardEntries; 12496bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public String customAboutCardName; 12506bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12516bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12526bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static class MutableString { 12536bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public String value; 1254eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1255edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1256eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 1257eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Converts a {@link DataItem} into an {@link ExpandingEntryCardView.Entry} for display. 1258eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * If the {@link ExpandingEntryCardView.Entry} has no visual elements, null is returned. 12596bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * 12606bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * This runs on a background thread. This is set as static to avoid accidentally adding 12616bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * additional dependencies on unsafe things (like the Activity). 12626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * 1263eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @param dataItem The {@link DataItem} to convert. 12646a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * @param secondDataItem A second {@link DataItem} to help build a full entry for some 12656a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * mimetypes 1266eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @return The {@link ExpandingEntryCardView.Entry}, or null if no visual elements are present. 1267eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 12686a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static Entry dataItemToEntry(DataItem dataItem, DataItem secondDataItem, 12696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Context context, Contact contactData, 12706bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final MutableString aboutCardName) { 1271eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable icon = null; 1272eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String header = null; 1273eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String subHeader = null; 1274eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable subHeaderIcon = null; 1275eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String text = null; 1276eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable textIcon = null; 127723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos StringBuilder primaryContentDescription = new StringBuilder(); 1278eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Intent intent = null; 127948ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos boolean shouldApplyColor = true; 1280dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Drawable alternateIcon = null; 1281dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Intent alternateIntent = null; 128223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos StringBuilder alternateContentDescription = new StringBuilder(); 1283eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isEditable = false; 12842a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo entryContextMenuInfo = null; 128548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Drawable thirdIcon = null; 128648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Intent thirdIntent = null; 128748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos String thirdContentDescription = null; 128848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos int iconResourceId = 0; 1289eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 12906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell context = context.getApplicationContext(); 129123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos final Resources res = context.getResources(); 1292eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataKind kind = dataItem.getDataKind(); 1293eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1294eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataItem instanceof ImDataItem) { 1295eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final ImDataItem im = (ImDataItem) dataItem; 12966bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell intent = ContactsUtils.buildImIntent(context, im).first; 1297eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isEmail = im.isCreatedFromEmail(); 12987de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos final int protocol; 12997de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos if (!im.isProtocolValid()) { 13007de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos protocol = Im.PROTOCOL_CUSTOM; 13017de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } else { 13027de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol(); 13037de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } 13047de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos if (protocol == Im.PROTOCOL_CUSTOM) { 13057de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos // If the protocol is custom, display the "IM" entry header as well to distinguish 13067de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos // this entry from other ones 130723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_im_entry); 130823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos subHeader = Im.getProtocolLabel(res, protocol, 13097de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos im.getCustomProtocol()).toString(); 13107de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos text = im.getData(); 13117de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } else { 131223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = Im.getProtocolLabel(res, protocol, 13137de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos im.getCustomProtocol()).toString(); 13147de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos subHeader = im.getData(); 13157de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } 131697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header, 131797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1318eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof OrganizationDataItem) { 1319eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final OrganizationDataItem organization = (OrganizationDataItem) dataItem; 132023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_organization_entry); 1321eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = organization.getCompany(); 132297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 132397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1324eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos text = organization.getTitle(); 1325eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof NicknameDataItem) { 1326eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final NicknameDataItem nickname = (NicknameDataItem) dataItem; 1327eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Build nickname entries 1328eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isNameRawContact = 13296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell (contactData.getNameRawContactId() == dataItem.getRawContactId()); 1330eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1331eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean duplicatesTitle = 1332eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos isNameRawContact 13336bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell && contactData.getDisplayNameSource() == DisplayNameSources.NICKNAME; 1334eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1335eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!duplicatesTitle) { 133623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_nickname_entry); 1337eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = nickname.getName(); 133897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 133997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1340eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1341eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof NoteDataItem) { 1342eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final NoteDataItem note = (NoteDataItem) dataItem; 134323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_note_entry); 1344eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = note.getNote(); 134597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 134697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1347eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof WebsiteDataItem) { 1348eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final WebsiteDataItem website = (WebsiteDataItem) dataItem; 134923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_website_entry); 1350eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = website.getUrl(); 135197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 135297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1353eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos try { 13546bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final WebAddress webAddress = new WebAddress(website.buildDataString(context, 13556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell kind)); 1356eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString())); 1357eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } catch (final ParseException e) { 13586bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Log.e(TAG, "Couldn't parse website: " + website.buildDataString(context, kind)); 1359eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1360eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof EventDataItem) { 1361eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final EventDataItem event = (EventDataItem) dataItem; 13626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String dataString = event.buildDataString(context, kind); 1363eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Calendar cal = DateUtils.parseDate(dataString, false); 1364eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (cal != null) { 1365eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Date nextAnniversary = 1366eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DateUtils.getNextAnnualDate(cal); 1367eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon(); 1368eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos builder.appendPath("time"); 1369eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos ContentUris.appendId(builder, nextAnniversary.getTime()); 1370eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW).setData(builder.build()); 1371eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 137223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_event_entry); 1373f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (event.hasKindTypeColumn(kind)) { 137423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos subHeader = Event.getTypeLabel(res, event.getKindTypeColumn(kind), 13757de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos event.getLabel()).toString(); 1376f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 13776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell text = DateUtils.formatDate(context, dataString); 137897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(text, header, 137997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1380eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof RelationDataItem) { 1381eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final RelationDataItem relation = (RelationDataItem) dataItem; 13826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String dataString = relation.buildDataString(context, kind); 1383eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(dataString)) { 1384eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_SEARCH); 1385eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent.putExtra(SearchManager.QUERY, dataString); 1386eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent.setType(Contacts.CONTENT_TYPE); 1387eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 138823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_relation_entry); 1389eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = relation.getName(); 139097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 139197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1392f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (relation.hasKindTypeColumn(kind)) { 139323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Relation.getTypeLabel(res, 13946bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell relation.getKindTypeColumn(kind), 1395f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos relation.getLabel()).toString(); 1396f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 1397eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof PhoneDataItem) { 1398eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final PhoneDataItem phone = (PhoneDataItem) dataItem; 1399eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(phone.getNumber())) { 140023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.call_other)).append(" "); 1401c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell header = sBidiFormatter.unicodeWrap(phone.buildDataString(context, kind), 1402c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell TextDirectionHeuristics.LTR); 14032a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 140497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(), 140597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1406f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (phone.hasKindTypeColumn(kind)) { 140723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Phone.getTypeLabel(res, phone.getKindTypeColumn(kind), 1408f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos phone.getLabel()).toString(); 140923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1410f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 141123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 141223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_phone_24dp); 141348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_phone_24dp; 14146bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (PhoneCapabilityTester.isPhone(context)) { 1415eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = CallUtil.getCallIntent(phone.getNumber()); 141616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 1417dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIntent = new Intent(Intent.ACTION_SENDTO, 14181cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phone.getNumber(), null)); 141948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 142023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateIcon = res.getDrawable(R.drawable.ic_message_24dp); 142123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(res.getString(R.string.sms_custom, header)); 142248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 142348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // Add video call button if supported 1424f764730a34da560db87206f9a48390d4c8085365Paul Soulos if (CallUtil.isVideoEnabled(context)) { 142523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos thirdIcon = res.getDrawable(R.drawable.ic_videocam); 142648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIntent = CallUtil.getVideoCallIntent(phone.getNumber(), 142748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY); 142848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdContentDescription = 142923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos res.getString(R.string.description_video_call); 143048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 1431eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1432eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof EmailDataItem) { 1433eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final EmailDataItem email = (EmailDataItem) dataItem; 1434eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String address = email.getData(); 1435eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(address)) { 143623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.email_other)).append(" "); 14371cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner final Uri mailUri = Uri.fromParts(ContactsUtils.SCHEME_MAILTO, address, null); 1438eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_SENDTO, mailUri); 1439eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos header = email.getAddress(); 14402a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 144197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.emailLabelsGroup), dataItem.getMimeType(), 144297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1443f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (email.hasKindTypeColumn(kind)) { 144423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Email.getTypeLabel(res, email.getKindTypeColumn(kind), 1445f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos email.getLabel()).toString(); 144623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1447f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 144823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 144923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_email_24dp); 145048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_email_24dp; 1451eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1452eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof StructuredPostalDataItem) { 1453eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos StructuredPostalDataItem postal = (StructuredPostalDataItem) dataItem; 1454eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String postalAddress = postal.getFormattedAddress(); 1455eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(postalAddress)) { 145623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.map_other)).append(" "); 1457eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress); 1458eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos header = postal.getFormattedAddress(); 14592a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 146097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.postalLabelsGroup), dataItem.getMimeType(), 146197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1462f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (postal.hasKindTypeColumn(kind)) { 146323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = StructuredPostal.getTypeLabel(res, 1464f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos postal.getKindTypeColumn(kind), postal.getLabel()).toString(); 146523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1466f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 146723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 14686a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos alternateIntent = 14696a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos StructuredPostalUtils.getViewPostalAddressDirectionsIntent(postalAddress); 147023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateIcon = res.getDrawable(R.drawable.ic_directions_24dp); 147123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(res.getString( 147223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos R.string.content_description_directions)).append(" ").append(header); 147323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_place_24dp); 147448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_place_24dp; 1475eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1476eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof SipAddressDataItem) { 14776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (PhoneCapabilityTester.isSipPhone(context)) { 1478eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final SipAddressDataItem sip = (SipAddressDataItem) dataItem; 1479eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String address = sip.getSipAddress(); 1480eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(address)) { 148123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.call_other)).append( 148223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos " "); 14831cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner final Uri callUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, address, null); 1484eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = CallUtil.getCallIntent(callUri); 14851cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos header = address; 14862a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 148797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(), 148897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 14891cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos if (sip.hasKindTypeColumn(kind)) { 149023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = SipAddress.getTypeLabel(res, 14916bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell sip.getKindTypeColumn(kind), sip.getLabel()).toString(); 149223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 14931cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos } 149423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 149523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_dialer_sip_black_24dp); 149648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_dialer_sip_black_24dp; 149716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 1498edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1499eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof StructuredNameDataItem) { 1500eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String givenName = ((StructuredNameDataItem) dataItem).getGivenName(); 1501eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(givenName)) { 150223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos aboutCardName.value = res.getString(R.string.about_card_title) + 15036bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell " " + givenName; 1504eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 150523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos aboutCardName.value = res.getString(R.string.about_card_title); 1506eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1507eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 1508eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Custom DataItem 15096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell header = dataItem.buildDataStringForDisplay(context, kind); 1510eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos text = kind.typeColumn; 1511eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW); 151260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos final Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, dataItem.getId()); 151360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos intent.setDataAndType(uri, dataItem.getMimeType()); 1514e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 1515e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (intent != null) { 1516e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos final String mimetype = intent.getType(); 1517e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 15186a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Build advanced entry for known 3p types. Otherwise default to ResolveCache icon. 1519e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos switch (mimetype) { 1520e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos case MIMETYPE_GPLUS_PROFILE: 15216a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // If a secondDataItem is available, use it to build an entry with 15226a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // alternate actions 15236a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (secondDataItem != null) { 152423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_google_plus_24dp); 15256a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos alternateIcon = res.getDrawable(R.drawable.ic_add_to_circles_black_24); 15266a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final GPlusOrHangoutsDataItemModel itemModel = 15276a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos new GPlusOrHangoutsDataItemModel(intent, alternateIntent, 15286a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataItem, secondDataItem, alternateContentDescription, 15296a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos header, text, context); 15306a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 153197b1e2d6206ad8f64af6bc935451654204706661Paul Soulos populateGPlusOrHangoutsDataItemModel(itemModel); 153297b1e2d6206ad8f64af6bc935451654204706661Paul Soulos intent = itemModel.intent; 153397b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateIntent = itemModel.alternateIntent; 153497b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateContentDescription = itemModel.alternateContentDescription; 153597b1e2d6206ad8f64af6bc935451654204706661Paul Soulos header = itemModel.header; 153697b1e2d6206ad8f64af6bc935451654204706661Paul Soulos text = itemModel.text; 15376a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15386a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (GPLUS_PROFILE_DATA_5_ADD_TO_CIRCLE.equals( 15396a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos intent.getDataString())) { 15406a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_add_to_circles_black_24); 15416a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15426a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_google_plus_24dp); 15436a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 1544e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1545e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos break; 1546e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos case MIMETYPE_HANGOUTS: 15476a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // If a secondDataItem is available, use it to build an entry with 15486a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // alternate actions 15496a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (secondDataItem != null) { 155023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_hangout_24dp); 15516a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos alternateIcon = res.getDrawable(R.drawable.ic_hangout_video_24dp); 155297b1e2d6206ad8f64af6bc935451654204706661Paul Soulos final GPlusOrHangoutsDataItemModel itemModel = 15536a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos new GPlusOrHangoutsDataItemModel(intent, alternateIntent, 15546a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataItem, secondDataItem, alternateContentDescription, 15556a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos header, text, context); 15566a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 155797b1e2d6206ad8f64af6bc935451654204706661Paul Soulos populateGPlusOrHangoutsDataItemModel(itemModel); 155897b1e2d6206ad8f64af6bc935451654204706661Paul Soulos intent = itemModel.intent; 155997b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateIntent = itemModel.alternateIntent; 156097b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateContentDescription = itemModel.alternateContentDescription; 156197b1e2d6206ad8f64af6bc935451654204706661Paul Soulos header = itemModel.header; 156297b1e2d6206ad8f64af6bc935451654204706661Paul Soulos text = itemModel.text; 15636a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15646a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (HANGOUTS_DATA_5_VIDEO.equals(intent.getDataString())) { 15656a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_hangout_video_24dp); 15666a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15676a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_hangout_24dp); 15686a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 1569e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1570e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos break; 1571e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos default: 157297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype, 157397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), 157497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.isSuperPrimary()); 15756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell icon = ResolveCache.getInstance(context).getIcon( 1576e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos dataItem.getMimeType(), intent); 1577e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos // Call mutate to create a new Drawable.ConstantState for color filtering 1578e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (icon != null) { 1579e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos icon.mutate(); 1580e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 158148ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos shouldApplyColor = false; 1582e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1583e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1584eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1585b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1586eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (intent != null) { 1587eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Do not set the intent is there are no resolves 15886bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!PhoneCapabilityTester.isIntentRegistered(context, intent)) { 1589eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = null; 1590eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1591eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1592eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1593dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (alternateIntent != null) { 1594dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos // Do not set the alternate intent is there are no resolves 15956bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!PhoneCapabilityTester.isIntentRegistered(context, alternateIntent)) { 1596dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIntent = null; 1597f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner } else if (TextUtils.isEmpty(alternateContentDescription)) { 1598f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner // Attempt to use package manager to find a suitable content description if needed 159923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(getIntentResolveLabel(alternateIntent, context)); 1600dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1601dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1602dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1603eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // If the Entry has no visual elements, return null 1604eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (icon == null && TextUtils.isEmpty(header) && TextUtils.isEmpty(subHeader) && 1605eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeaderIcon == null && TextUtils.isEmpty(text) && textIcon == null) { 1606eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return null; 1607eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1608eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1609fa238949855fba3b28a57fad3d585b13e80362bbBrian Attwell // Ignore dataIds from the Me profile. 1610ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos final int dataId = dataItem.getId() > Integer.MAX_VALUE ? 1611ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos -1 : (int) dataItem.getId(); 1612ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 161323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, 161423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.toString(), intent, alternateIcon, alternateIntent, 161523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.toString(), shouldApplyColor, isEditable, 161648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription, 161748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId); 1618eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1619eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 16206bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private List<Entry> dataItemsToEntries(List<DataItem> dataItems, 16216bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell MutableString aboutCardTitleOut) { 16226a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Hangouts and G+ use two data items to create one entry. 16236a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (dataItems.get(0).getMimeType().equals(MIMETYPE_GPLUS_PROFILE) || 16246a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataItems.get(0).getMimeType().equals(MIMETYPE_HANGOUTS)) { 16256a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos return gPlusOrHangoutsDataItemsToEntries(dataItems); 16266a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 16276a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final List<Entry> entries = new ArrayList<>(); 16286a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos for (DataItem dataItem : dataItems) { 16296a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Entry entry = dataItemToEntry(dataItem, /* secondDataItem = */ null, 16306a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this, mContactData, aboutCardTitleOut); 16316a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (entry != null) { 16326a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos entries.add(entry); 16336a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16346a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16356a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos return entries; 16366a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16376a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16386a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 16396a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /** 16406a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * G+ and Hangout entries are unique in that a single ExpandingEntryCardView.Entry consists 16416a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * of two data items. This method attempts to build each entry using the two data items if 16426a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * they are available. If there are more or less than two data items, a fall back is used 16436a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * and each data item gets its own entry. 16446a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos */ 16456a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private List<Entry> gPlusOrHangoutsDataItemsToEntries(List<DataItem> dataItems) { 1646eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<Entry> entries = new ArrayList<>(); 16476a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Map<Long, List<DataItem>> buckets = new HashMap<>(); 16486a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Put the data items into buckets based on the raw contact id 1649eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (DataItem dataItem : dataItems) { 16506a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos List<DataItem> bucket = buckets.get(dataItem.getRawContactId()); 16516a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (bucket == null) { 16526a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos bucket = new ArrayList<>(); 16536a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos buckets.put(dataItem.getRawContactId(), bucket); 16546a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16556a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos bucket.add(dataItem); 16566a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16576a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 16586a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Use the buckets to build entries. If a bucket contains two data items, build the special 16596a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // entry, otherwise fall back to the normal entry. 16606a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos for (List<DataItem> bucket : buckets.values()) { 16616a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (bucket.size() == 2) { 16626a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Use the pair to build an entry 16636a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Entry entry = dataItemToEntry(bucket.get(0), 16646a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /* secondDataItem = */ bucket.get(1), this, mContactData, 16656a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /* aboutCardName = */ null); 16666a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (entry != null) { 16676a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos entries.add(entry); 16686a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16696a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 16706a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos for (DataItem dataItem : bucket) { 16716a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Entry entry = dataItemToEntry(dataItem, /* secondDataItem = */ null, 16726a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this, mContactData, /* aboutCardName = */ null); 16736a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (entry != null) { 16746a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos entries.add(entry); 16756a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16766a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 1677eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1678eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1679eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return entries; 1680edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1681edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 16826a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /** 16836a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * Used for statically passing around G+ or Hangouts data items and entry fields to 16846a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * populateGPlusOrHangoutsDataItemModel. 16856a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos */ 16866a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final class GPlusOrHangoutsDataItemModel { 16876a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public Intent intent; 16886a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public Intent alternateIntent; 16896a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public DataItem dataItem; 16906a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public DataItem secondDataItem; 16916a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public StringBuilder alternateContentDescription; 16926a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public String header; 16936a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public String text; 16946a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public Context context; 16956a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 16966a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public GPlusOrHangoutsDataItemModel(Intent intent, Intent alternateIntent, DataItem dataItem, 16976a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos DataItem secondDataItem, StringBuilder alternateContentDescription, String header, 16986a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos String text, Context context) { 16996a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.intent = intent; 17006a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.alternateIntent = alternateIntent; 17016a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.dataItem = dataItem; 17026a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.secondDataItem = secondDataItem; 17036a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.alternateContentDescription = alternateContentDescription; 17046a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.header = header; 17056a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.text = text; 17066a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.context = context; 17076a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17086a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17096a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 17106a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static void populateGPlusOrHangoutsDataItemModel( 17116a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos GPlusOrHangoutsDataItemModel dataModel) { 17126a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Intent secondIntent = new Intent(Intent.ACTION_VIEW); 17136a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos secondIntent.setDataAndType(ContentUris.withAppendedId(Data.CONTENT_URI, 17146a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.getId()), dataModel.secondDataItem.getMimeType()); 17156a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // There is no guarantee the order the data items come in. Second 17166a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // data item does not necessarily mean it's the alternate. 17176a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Hangouts video and Add to circles should be alternate. Swap if needed 17186a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (HANGOUTS_DATA_5_VIDEO.equals( 17196a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5)) || 17206a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos GPLUS_PROFILE_DATA_5_ADD_TO_CIRCLE.equals( 17216a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5))) { 17226a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateIntent = dataModel.intent; 17236a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateContentDescription = new StringBuilder(dataModel.header); 17246a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 17256a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.intent = secondIntent; 17266a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.header = dataModel.secondDataItem.buildDataStringForDisplay(dataModel.context, 17276a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.getDataKind()); 17286a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.text = dataModel.secondDataItem.getDataKind().typeColumn; 17296a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else if (HANGOUTS_DATA_5_MESSAGE.equals( 17306a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5)) || 17316a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos GPLUS_PROFILE_DATA_5_VIEW_PROFILE.equals( 17326a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5))) { 17336a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateIntent = secondIntent; 17346a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateContentDescription = new StringBuilder( 17356a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.buildDataStringForDisplay(dataModel.context, 17366a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.getDataKind())); 17376a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17386a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17396a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 17406bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static String getIntentResolveLabel(Intent intent, Context context) { 17416bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<ResolveInfo> matches = context.getPackageManager().queryIntentActivities(intent, 1742dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos PackageManager.MATCH_DEFAULT_ONLY); 1743dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1744dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos // Pick first match, otherwise best found 1745dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos ResolveInfo bestResolve = null; 1746dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final int size = matches.size(); 1747dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (size == 1) { 1748dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos bestResolve = matches.get(0); 1749dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } else if (size > 1) { 17506bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell bestResolve = ResolveCache.getInstance(context).getBestResolve(intent, matches); 1751dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1752dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1753dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (bestResolve == null) { 1754dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos return null; 1755dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1756dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 17576bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell return String.valueOf(bestResolve.loadLabel(context.getPackageManager())); 1758dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1759dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1760edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 176131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * Asynchronously extract the most vibrant color from the PhotoView. Once extracted, 176231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms 176331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * on a Nexus 5. 176431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell */ 176531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell private void extractAndApplyTintFromPhotoViewAsynchronously() { 176631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (mScroller == null) { 176731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return; 176831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 176931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 1770faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell new AsyncTask<Void, Void, MaterialPalette>() { 177131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 1772faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell protected MaterialPalette doInBackground(Void... params) { 1773faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell 177495c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell if (imageViewDrawable instanceof BitmapDrawable 177595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell && mContactData.getThumbnailPhotoBinaryData() != null 177695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell && mContactData.getThumbnailPhotoBinaryData().length > 0) { 177795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // Perform the color analysis on the thumbnail instead of the full sized 177895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // image, so that our results will be as similar as possible to the Bugle 177995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // app. 178095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell final Bitmap bitmap = BitmapFactory.decodeByteArray( 178195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell mContactData.getThumbnailPhotoBinaryData(), 0, 178295c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell mContactData.getThumbnailPhotoBinaryData().length); 178395c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell try { 178495c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell final int primaryColor = colorFromBitmap(bitmap); 178595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell if (primaryColor != 0) { 178695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor( 178795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell primaryColor); 178895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell } 178995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell } finally { 179095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell bitmap.recycle(); 1791faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell } 17928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 17938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (imageViewDrawable instanceof LetterTileDrawable) { 1794faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell final int primaryColor = ((LetterTileDrawable) imageViewDrawable).getColor(); 1795a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(primaryColor); 179631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 1797a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell return MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors(getResources()); 179831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 179931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 180031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 1801faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell protected void onPostExecute(MaterialPalette palette) { 1802faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell super.onPostExecute(palette); 18038571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (mHasComputedThemeColor) { 18048571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // If we had previously computed a theme color from the contact photo, 18058571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // then do not update the theme color. Changing the theme color several 18068571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // seconds after QC has started, as a result of an updated/upgraded photo, 18078571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // is a jarring experience. On the other hand, changing the theme color after 18088571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // a rotation or onNewIntent() is perfectly fine. 18098571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell return; 18108571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell } 18118571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // Check that the Photo has not changed. If it has changed, the new tint 18128571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // color needs to be extracted 18138571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (imageViewDrawable == mPhotoView.getDrawable()) { 18148571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = true; 1815faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell setThemeColor(palette); 181631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 181731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 181831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell }.execute(); 181931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 182031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 18214936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell /** 18224936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * Examine how many white pixels are in the bitmap in order to determine whether or not 18234936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * we need gradient overlays on top of the image. 18244936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell */ 18254936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell private void analyzeWhitenessOfPhotoAsynchronously() { 18264936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 18274936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell new AsyncTask<Void, Void, Boolean>() { 18284936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 18294936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected Boolean doInBackground(Void... params) { 18304936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell if (imageViewDrawable instanceof BitmapDrawable) { 18314936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap(); 18324936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return WhitenessUtils.isBitmapWhiteAtTopOrBottom(bitmap); 18334936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18344936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return !(imageViewDrawable instanceof LetterTileDrawable); 18354936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18364936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 18374936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 18384936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected void onPostExecute(Boolean isWhite) { 18394936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell super.onPostExecute(isWhite); 18404936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell mScroller.setUseGradient(isWhite); 18414936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18424936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell }.execute(); 18434936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18444936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 1845faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell private void setThemeColor(MaterialPalette palette) { 18469b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // If the color is invalid, use the predefined default 1847faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell final int primaryColor = palette.mPrimaryColor; 1848faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mScroller.setHeaderTintColor(primaryColor); 1849faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mStatusBarColor = palette.mSecondaryColor; 18509b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell updateStatusBarColor(); 18518571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell 18529b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mColorFilter = 1853faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell new PorterDuffColorFilter(primaryColor, PorterDuff.Mode.SRC_ATOP); 1854faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mContactCard.setColorAndFilter(primaryColor, mColorFilter); 1855faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mRecentCard.setColorAndFilter(primaryColor, mColorFilter); 1856faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mAboutCard.setColorAndFilter(primaryColor, mColorFilter); 18579b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 18589b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 18598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void updateStatusBarColor() { 18608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller == null) { 18618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 18628a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int desiredStatusBarColor; 18648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Only use a custom status bar color if QuickContacts touches the top of the viewport. 18658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller.getScrollNeededToBeFullScreen() <= 0) { 18668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = mStatusBarColor; 18678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } else { 18688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = Color.TRANSPARENT; 18698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Animate to the new color. 1871847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell final ObjectAnimator animation = ObjectAnimator.ofInt(getWindow(), "statusBarColor", 1872847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell getWindow().getStatusBarColor(), desiredStatusBarColor); 1873847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.setDuration(ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION); 1874847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.setEvaluator(new ArgbEvaluator()); 1875847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.start(); 18768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18778a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 18788a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int colorFromBitmap(Bitmap bitmap) { 18798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Author of Palette recommends using 24 colors when analyzing profile photos. 18808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int NUMBER_OF_PALETTE_COLORS = 24; 18818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS); 1882a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell if (palette != null && palette.getVibrantSwatch() != null) { 1883a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell return palette.getVibrantSwatch().getRgb(); 18848a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return 0; 18868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1888b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private List<Entry> contactInteractionsToEntries(List<ContactInteraction> interactions) { 1889eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<Entry> entries = new ArrayList<>(); 1890b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos for (ContactInteraction interaction : interactions) { 1891ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos entries.add(new Entry(/* id = */ -1, 1892ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos interaction.getIcon(this), 1893b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewHeader(this), 1894b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewBody(this), 1895b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getBodyIcon(this), 1896b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewFooter(this), 1897b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getFooterIcon(this), 189823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos interaction.getContentDescription(this), 1899b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getIntent(), 1900dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIcon = */ null, 1901dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIntent = */ null, 1902dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateContentDescription = */ null, 190348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos /* shouldApplyColor = */ true, 19042a4207fb39330e840436215c896cde911489e111Paul Soulos /* isEditable = */ false, 190548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* EntryContextMenuInfo = */ null, 190648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, 190748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIntent = */ null, 190848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, 190948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos interaction.getIconResourceId())); 1910b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1911b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return entries; 1912b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1913b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1914eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final LoaderCallbacks<Contact> mLoaderContactCallbacks = 1915851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 1916cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1917851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 1918405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos mContactData = null; 1919cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1920cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1921cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1922851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 19238a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onLoadFinished()"); 1924930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell try { 19258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1926930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell if (isFinishing()) { 1927930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell return; 1928930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } 1929930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell if (data.isError()) { 1930930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell // This shouldn't ever happen, so throw an exception. The {@link ContactLoader} 1931930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell // should log the actual exception. 1932930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell throw new IllegalStateException("Failed to load contact", data.getException()); 1933930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } 1934930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell if (data.isNotFound()) { 19358a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri()); 19368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage, 19378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.LENGTH_LONG).show(); 1938930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell finish(); 1939930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell return; 19408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 1941cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1942930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell bindContactData(data); 1943cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1944930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } finally { 1945930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell Trace.endSection(); 1946930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } 1947cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1948cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1949cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1950851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 1951cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (mLookupUri == null) { 1952cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early"); 1953cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1954d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Load all contact data. We need loadGroupMetaData=true to determine whether the 1955d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // contact is invisible. If it is, we need to display an "Add to Contacts" MenuItem. 1956b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee return new ContactLoader(getApplicationContext(), mLookupUri, 1957d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell true /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/, 19588571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell true /*postViewNotification*/, true /*computeFormattedPhoneNumber*/); 1959cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1960cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann }; 1961b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1962b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 1963b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onBackPressed() { 1964b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 19658477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell if (!mIsExitAnimationInProgress) { 19668477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mScroller.scrollOffBottom(); 19678477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 1968b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } else { 1969b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell super.onBackPressed(); 1970b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1971b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1972b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 19738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 19748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void finish() { 19758a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.finish(); 19768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 19778a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // override transitions to skip the standard window animations 19788a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell overridePendingTransition(0, 0); 19798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 19808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1981eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final LoaderCallbacks<List<ContactInteraction>> mLoaderInteractionsCallbacks = 1982b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos new LoaderCallbacks<List<ContactInteraction>>() { 1983b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1984b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1985b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public Loader<List<ContactInteraction>> onCreateLoader(int id, Bundle args) { 1986b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Loader<List<ContactInteraction>> loader = null; 1987b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos switch (id) { 1988b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos case LOADER_SMS_ID: 1989b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos loader = new SmsInteractionsLoader( 1990b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos QuickContactActivity.this, 1991ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 1992b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos MAX_SMS_RETRIEVE); 1993b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos break; 1994899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos case LOADER_CALENDAR_ID: 1995ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos final String[] emailsArray = args.getStringArray(KEY_LOADER_EXTRA_EMAILS); 1996ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos List<String> emailsList = null; 1997ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos if (emailsArray != null) { 1998ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos emailsList = Arrays.asList(args.getStringArray(KEY_LOADER_EXTRA_EMAILS)); 1999ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos } 2000899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos loader = new CalendarInteractionsLoader( 2001899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos QuickContactActivity.this, 2002ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos emailsList, 2003899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_FUTURE_CALENDAR_RETRIEVE, 2004899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_PAST_CALENDAR_RETRIEVE, 2005899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR, 2006899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR); 2007899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos break; 2008ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case LOADER_CALL_LOG_ID: 2009ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos loader = new CallLogInteractionsLoader( 2010ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.this, 2011ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 2012ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos MAX_CALL_LOG_RETRIEVE); 2013b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2014b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return loader; 2015b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2016b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2017b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 2018b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoadFinished(Loader<List<ContactInteraction>> loader, 2019b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos List<ContactInteraction> data) { 2020b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.put(loader.getId(), data); 2021b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2022b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (isAllRecentDataLoaded()) { 2023b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos bindRecentData(); 2024b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2025b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2026b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2027b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 2028b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoaderReset(Loader<List<ContactInteraction>> loader) { 2029b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.remove(loader.getId()); 2030b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2031b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos }; 2032b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2033b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private boolean isAllRecentDataLoaded() { 2034b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return mRecentLoaderResults.size() == mRecentLoaderIds.length; 2035b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2036b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2037b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private void bindRecentData() { 2038eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<ContactInteraction> allInteractions = new ArrayList<>(); 203930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell final List<List<Entry>> interactionsWrapper = new ArrayList<>(); 2040b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 204130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask = new AsyncTask<Void, Void, Void>() { 2042b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 204330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell protected Void doInBackground(Void... params) { 204430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("sort recent loader results"); 204530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 204630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) { 204730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell allInteractions.addAll(loaderInteractions); 204830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 204930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 205030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // Sort the interactions by most recent 205130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Collections.sort(allInteractions, new Comparator<ContactInteraction>() { 205230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell @Override 205330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell public int compare(ContactInteraction a, ContactInteraction b) { 205430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1; 205530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 205630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell }); 205730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 205830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 205930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("contactInteractionsToEntries"); 206030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 206130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // Wrap each interaction in its own list so that an icon is displayed for each entry 206230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell for (Entry contactInteraction : contactInteractionsToEntries(allInteractions)) { 206330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell List<Entry> entryListWrapper = new ArrayList<>(1); 206430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell entryListWrapper.add(contactInteraction); 206530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell interactionsWrapper.add(entryListWrapper); 206630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 206730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 206830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 206930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell return null; 2070b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 207130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 207230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell @Override 207330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell protected void onPostExecute(Void aVoid) { 207430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell super.onPostExecute(aVoid); 207530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("initialize recents card"); 207630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 207730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (allInteractions.size() > 0) { 207830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentCard.initialize(interactionsWrapper, 2079b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN, 2080c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos /* isExpanded = */ mRecentCard.isExpanded(), /* isAlwaysExpanded = */ false, 208130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mExpandingEntryCardViewListener, mScroller); 208230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentCard.setVisibility(View.VISIBLE); 208330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 2084eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 208530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 208630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 208730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // About card is initialized along with the contact card, but since it appears after 208830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // the recent card in the UI, we hold off until making it visible until the recent 208930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // card is also ready to avoid stuttering. 209030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (mAboutCard.shouldShow()) { 209130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mAboutCard.setVisibility(View.VISIBLE); 209230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } else { 209330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mAboutCard.setVisibility(View.GONE); 209430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 209530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask = null; 209630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 209730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell }; 209830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask.execute(); 2099b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 21008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 21018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 21028a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onStop() { 21038a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onStop(); 21048a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 21058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mEntriesAndActionsTask != null) { 21068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Once the activity is stopped, we will no longer want to bind mEntriesAndActionsTask's 21078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // results on the UI thread. In some circumstances Activities are killed without 21088a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // onStop() being called. This is not a problem, because in these circumstances 21098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the entire process will be killed. 21108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.cancel(/* mayInterruptIfRunning = */ false); 21118a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 211230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (mRecentDataTask != null) { 211330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask.cancel(/* mayInterruptIfRunning = */ false); 211430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 21158a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 211623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 211723889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos /** 2118d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Returns true if it is possible to edit the current contact. 2119d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 2120d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private boolean isContactEditable() { 2121d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 2122d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2123d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2124a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell /** 2125a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell * Returns true if it is possible to share the current contact. 2126a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell */ 2127a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell private boolean isContactShareable() { 2128a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 2129a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell } 2130a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 21316095369885edcca566a812b551886e29c7ff8039Brian Attwell private Intent getEditContactIntent() { 213263176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell final Intent intent = new Intent(Intent.ACTION_EDIT, mContactData.getLookupUri()); 2133d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 21346095369885edcca566a812b551886e29c7ff8039Brian Attwell return intent; 21356095369885edcca566a812b551886e29c7ff8039Brian Attwell } 21366095369885edcca566a812b551886e29c7ff8039Brian Attwell 21376095369885edcca566a812b551886e29c7ff8039Brian Attwell private void editContact() { 2138a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 2139c00a0b5370f0714f6af1ea9b3e29b10f25e91af0Zheng Fu mContactLoader.cacheResult(); 21406095369885edcca566a812b551886e29c7ff8039Brian Attwell startActivityForResult(getEditContactIntent(), REQUEST_CODE_CONTACT_EDITOR_ACTIVITY); 2141d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2142d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2143d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void toggleStar(MenuItem starredMenuItem) { 2144d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Make sure there is a contact 214563176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell if (mContactData != null) { 2146d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Read the current starred value from the UI instead of using the last 2147d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // loaded state. This allows rapid tapping without writing the same 2148d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // value several times 2149d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final boolean isStarred = starredMenuItem.isChecked(); 2150d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2151d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // To improve responsiveness, swap out the picture (and tag) in the UI already 2152333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos ContactDisplayUtils.configureStarredMenuItem(starredMenuItem, 2153d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 2154d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell !isStarred); 2155d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2156d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Now perform the real save 2157eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Intent intent = ContactSaveService.createSetStarredIntent( 215863176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell QuickContactActivity.this, mContactData.getLookupUri(), !isStarred); 2159d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell startService(intent); 216035ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell 216135ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell final CharSequence accessibilityText = !isStarred 216235ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell ? getResources().getText(R.string.description_action_menu_add_star) 216335ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell : getResources().getText(R.string.description_action_menu_remove_star); 216435ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell // Accessibility actions need to have an associated view. We can't access the MenuItem's 216535ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell // underlying view, so put this accessibility action on the root view. 216635ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell mScroller.announceForAccessibility(accessibilityText); 2167d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2168d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2169d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2170752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 2171752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Calls into the contacts provider to get a pre-authorized version of the given URI. 2172752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 2173752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private Uri getPreAuthorizedUri(Uri uri) { 2174752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle uriBundle = new Bundle(); 2175752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); 2176752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle authResponse = getContentResolver().call( 2177752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.AUTHORITY_URI, 2178752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.AUTHORIZATION_METHOD, 2179752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell null, 2180752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle); 2181752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (authResponse != null) { 2182752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return (Uri) authResponse.getParcelable( 2183752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.KEY_AUTHORIZED_URI); 2184752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } else { 2185752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return uri; 2186752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2187752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 21882d150da246632b1649999cfabed776133b097775Brian Attwell 2189752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void shareContact() { 2190752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final String lookupKey = mContactData.getLookupKey(); 2191752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey); 2192752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (mContactData.isUserProfile()) { 2193752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // User is sharing the profile. We don't want to force the receiver to have 2194752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // the highly-privileged READ_PROFILE permission, so we need to request a 2195752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // pre-authorized URI from the provider. 2196752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareUri = getPreAuthorizedUri(shareUri); 2197752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2198752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2199752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent intent = new Intent(Intent.ACTION_SEND); 2200752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.setType(Contacts.CONTENT_VCARD_TYPE); 2201752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.putExtra(Intent.EXTRA_STREAM, shareUri); 2202752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2203752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Launch chooser to share contact via 2204752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final CharSequence chooseTitle = getText(R.string.share_via); 2205752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent chooseIntent = Intent.createChooser(intent, chooseTitle); 2206752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2207752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell try { 2208a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 2209752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell this.startActivity(chooseIntent); 2210eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } catch (final ActivityNotFoundException ex) { 2211752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(this, R.string.share_error, Toast.LENGTH_SHORT).show(); 2212752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2213752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2214752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2215752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 2216752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Creates a launcher shortcut with the current contact. 2217752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 2218752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void createLauncherShortcutWithContact() { 2219752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final ShortcutIntentBuilder builder = new ShortcutIntentBuilder(this, 2220752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell new OnShortcutIntentCreatedListener() { 2221752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2222752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell @Override 2223752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) { 2224752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Broadcast the shortcutIntent to the launcher to create a 2225752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // shortcut to this contact 2226752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 2227752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell QuickContactActivity.this.sendBroadcast(shortcutIntent); 2228752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2229752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Send a toast to give feedback to the user that a shortcut to this 2230752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // contact was added to the launcher. 2231752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(QuickContactActivity.this, 2232752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell R.string.createContactShortcutSuccessful, 2233752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.LENGTH_SHORT).show(); 2234752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2235752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2236752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell }); 223763176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell builder.createContactShortcutIntent(mContactData.getLookupUri()); 2238752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2239752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 224066965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell private boolean isShortcutCreatable() { 224166965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final Intent createShortcutIntent = new Intent(); 224266965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell createShortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 224366965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final List<ResolveInfo> receivers = getPackageManager() 224466965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell .queryBroadcastReceivers(createShortcutIntent, 0); 224566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell return receivers != null && receivers.size() > 0; 224666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell } 224766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell 2248d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2249d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onCreateOptionsMenu(Menu menu) { 2250eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final MenuInflater inflater = getMenuInflater(); 2251d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell inflater.inflate(R.menu.quickcontact, menu); 2252d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2253d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2254d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2255d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2256d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onPrepareOptionsMenu(Menu menu) { 2257d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mContactData != null) { 2258d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem starredMenuItem = menu.findItem(R.id.menu_star); 2259333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos ContactDisplayUtils.configureStarredMenuItem(starredMenuItem, 2260d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 2261d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.getStarred()); 2262a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 2263d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Configure edit MenuItem 2264d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem editMenuItem = menu.findItem(R.id.menu_edit); 2265d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(true); 2266d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData) || InvisibleContactUtil 2267d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .isInvisibleAndAddable(mContactData, this)) { 226830cfd121ad8c8adb83cf417ff1d40a8ba1e3761dBrian Attwell editMenuItem.setIcon(R.drawable.ic_person_add_tinted_24dp); 22692e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell editMenuItem.setTitle(R.string.menu_add_contact); 2270d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 2271d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setIcon(R.drawable.ic_create_24dp); 22722e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell editMenuItem.setTitle(R.string.menu_editContact); 2273d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else { 2274d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(false); 2275d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2276a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 2277a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell final MenuItem shareMenuItem = menu.findItem(R.id.menu_share); 2278a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell shareMenuItem.setVisible(isContactShareable()); 2279a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 228066965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final MenuItem shortcutMenuItem = menu.findItem(R.id.menu_create_contact_shortcut); 228166965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell shortcutMenuItem.setVisible(isShortcutCreatable()); 228266965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell 22838a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return true; 2284d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 22858a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return false; 2286d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2287d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2288d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2289d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onOptionsItemSelected(MenuItem item) { 2290d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell switch (item.getItemId()) { 2291d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_star: 2292d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell toggleStar(item); 2293d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2294d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_edit: 2295d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData)) { 2296ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // This action is used to launch the contact selector, with the option of 2297ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // creating a new contact. Creating a new contact is an INSERT, while selecting 2298ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // an exisiting one is an edit. The fields in the edit screen will be 2299ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // prepopulated with data. 2300ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2301ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 2302ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.setType(Contacts.CONTENT_ITEM_TYPE); 2303ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2304fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell ArrayList<ContentValues> values = mContactData.getContentValues(); 2305fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell 2306fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // Only pre-fill the name field if the provided display name is an nickname 2307fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // or better (e.g. structured name, nickname) 2308fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell if (mContactData.getDisplayNameSource() >= DisplayNameSources.NICKNAME) { 2309ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.NAME, mContactData.getDisplayName()); 2310fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell } else if (mContactData.getDisplayNameSource() 2311fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell == DisplayNameSources.ORGANIZATION) { 2312fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // This is probably an organization. Instead of copying the organization 2313fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // name into a name entry, copy it into the organization entry. This 2314fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // way we will still consider the contact an organization. 2315fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell final ContentValues organization = new ContentValues(); 2316fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell organization.put(Organization.COMPANY, mContactData.getDisplayName()); 2317fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell organization.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 2318fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell values.add(organization); 2319ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2320fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell 2321ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Last time used and times used are aggregated values from the usage stat 2322ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // table. They need to be removed from data values so the SQL table can insert 2323ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // properly 2324ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos for (ContentValues value : values) { 2325ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos value.remove(Data.LAST_TIME_USED); 2326ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos value.remove(Data.TIMES_USED); 2327ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2328ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.DATA, values); 2329ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2330ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // If the contact can only export to the same account, add it to the intent. 2331ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Otherwise the ContactEditorFragment will show a dialog for selecting an 2332ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // account. 2333ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos if (mContactData.getDirectoryExportSupport() == 2334ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY) { 2335ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.ACCOUNT, 2336ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos new Account(mContactData.getDirectoryAccountName(), 2337ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos mContactData.getDirectoryAccountType())); 2338ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.DATA_SET, 2339ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos mContactData.getRawContacts().get(0).getDataSet()); 2340ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2341ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2342f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos // Add this flag to disable the delete menu option on directory contact joins 2343f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos // with local contacts. The delete option is ambiguous when joining contacts. 2344f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos intent.putExtra(ContactEditorFragment.INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION, 2345f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos true); 2346f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos 2347ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos startActivityForResult(intent, REQUEST_CODE_CONTACT_SELECTION_ACTIVITY); 2348d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (InvisibleContactUtil.isInvisibleAndAddable(mContactData, this)) { 2349d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell InvisibleContactUtil.addToDefaultGroup(mContactData, this); 2350d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 2351d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editContact(); 2352d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2353d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2354752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_share: 2355752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareContact(); 2356752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 2357752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_create_contact_shortcut: 2358752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell createLauncherShortcutWithContact(); 2359752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 2360d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell default: 2361d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return super.onOptionsItemSelected(item); 2362d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 236323889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos } 2364edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann} 2365