QuickContactActivity.java revision 31b2d42fb0889e61515d27314aa5a245147100da
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 19b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport android.animation.ObjectAnimator; 20edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.app.Activity; 21cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 22edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.ContentUris; 23edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Context; 24edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Intent; 25cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.content.Loader; 26edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.pm.PackageManager; 2731b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Bitmap; 2831b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Canvas; 2931b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.BitmapDrawable; 3031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.Drawable; 31edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.net.Uri; 3231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.os.AsyncTask; 33edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.os.Bundle; 34edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 35edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 36edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 37edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 38edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Website; 39edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.Contacts; 406cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Leeimport android.provider.ContactsContract.DisplayNameSources; 416cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Leeimport android.provider.ContactsContract.Intents.Insert; 426cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Leeimport android.provider.ContactsContract.Directory; 43edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.QuickContact; 44edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.RawContacts; 4531b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.support.v7.graphics.Palette; 46edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils; 47edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log; 48edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View; 49edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener; 5010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager; 51edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.ImageView; 52edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.TextView; 53edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast; 54edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 5572b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService; 56d7ca03e23948c3b2d5f97ec5598d8b50e3fc0b25Chiao Chengimport com.android.contacts.common.Collapser; 57e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 5831b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable; 590d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager; 60cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact; 61cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader; 62cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact; 63428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType; 64cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem; 65428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 66cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem; 67cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem; 68d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Chengimport com.android.contacts.common.util.Constants; 69cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.util.DataStatus; 702e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Leeimport com.android.contacts.common.util.UriUtils; 712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry; 72e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter; 739f2a5e78c9604d9c407f1464c7cb72ec5f2bb04dChiao Chengimport com.android.contacts.common.util.StopWatch; 74b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils; 75b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller; 76b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener; 772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 78e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions; 79e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 80e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList; 82edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap; 83edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashSet; 84edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List; 85edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.Set; 86edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 87edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/** 88edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads 89edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around 90edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}. 91edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 92edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannpublic class QuickContactActivity extends Activity { 93edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String TAG = "QuickContact"; 94edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 95edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final boolean TRACE_LAUNCH = false; 96edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String TRACE_TAG = "quickcontact"; 97b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private static final int ANIMATION_DURATION = 250; 98dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki private static final boolean ENABLE_STOPWATCH = false; 99dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 100edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 101edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @SuppressWarnings("deprecation") 102edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY; 103edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 104edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private Uri mLookupUri; 105edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private String[] mExcludeMimes; 106edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private List<String> mSortedActionMimeTypes = Lists.newArrayList(); 107edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 108edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private View mPhotoContainer; 109edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1106219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee private ImageView mPhotoView; 1115ec23fdf243596717197a0c45495f24492cf0641Paul Soulos private ImageView mEditOrAddContactImage; 11272b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen private ImageView mStarImage; 1132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private ExpandingEntryCardView mCommunicationCard; 114b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private MultiShrinkScroller mScroller; 115edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1166cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee private Contact mContactData; 1179815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann private ContactLoader mContactLoader; 1189815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann 1199758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter(); 1209758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus 121edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 122edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Keeps the default action per mimetype. Empty if no default actions are set 123edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 124edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>(); 125edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 126edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 127edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Set of {@link Action} that are associated with the aggregate currently 128edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * displayed by this dialog, represented as a map from {@link String} 129edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * MIME-type to a list of {@link Action}. 130edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 131edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private ActionMultiMap mActions = new ActionMultiMap(); 132edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 133edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 134edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link #LEADING_MIMETYPES} and {@link #TRAILING_MIMETYPES} are used to sort MIME-types. 135edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 136edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog, 137edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * in the order specified here.</p> 138edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 139edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The ones in {@link #TRAILING_MIMETYPES} appear in the end of the dialog, in the order 140edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * specified here.</p> 141edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 142edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The rest go between them, in the order in the array.</p> 143edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 144edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> LEADING_MIMETYPES = Lists.newArrayList( 145edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE); 146edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 147edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** See {@link #LEADING_MIMETYPES}. */ 148edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> TRAILING_MIMETYPES = Lists.newArrayList( 149edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann StructuredPostal.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE); 150edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 151cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann /** Id for the background loader */ 152cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann private static final int LOADER_ID = 0; 153edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 154dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki private StopWatch mStopWatch = ENABLE_STOPWATCH 155dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki ? StopWatch.start("QuickContact") : StopWatch.getNullStopWatch(); 156dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 1575ec23fdf243596717197a0c45495f24492cf0641Paul Soulos final OnClickListener mEditContactClickHandler = new OnClickListener() { 1586cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee @Override 1596cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee public void onClick(View v) { 1605ec23fdf243596717197a0c45495f24492cf0641Paul Soulos final Intent intent = new Intent(Intent.ACTION_EDIT, mLookupUri); 1616cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee mContactLoader.cacheResult(); 1626cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 1636cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee startActivity(intent); 1646cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee } 1656cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee }; 1666cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 1676cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee final OnClickListener mAddToContactsClickHandler = new OnClickListener() { 1686cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee @Override 1696cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee public void onClick(View v) { 1706cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee if (mContactData == null) { 1716cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee Log.e(TAG, "Empty contact data when trying to add to contact"); 1726cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee return; 1736cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee } 1746cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 1756cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee intent.setType(Contacts.CONTENT_ITEM_TYPE); 1766cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 1776cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee // Only pre-fill the name field if the provided display name is an organization 1786cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee // name or better (e.g. structured name, nickname) 1796cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee if (mContactData.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) { 1806cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee intent.putExtra(Insert.NAME, mContactData.getDisplayName()); 1816cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee } 1826cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee intent.putExtra(Insert.DATA, mContactData.getContentValues()); 1836cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee startActivity(intent); 1846cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee } 1856cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee }; 1866cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 1872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos final OnClickListener mEntryClickHandler = new OnClickListener() { 1882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 1892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void onClick(View v) { 1902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Log.i(TAG, "mEntryClickHandler onClick"); 1912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Object intent = v.getTag(); 1922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (intent == null || !(intent instanceof Intent)) { 1932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return; 1942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos startActivity((Intent) intent); 1962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }; 1982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 199b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final MultiShrinkScrollerListener mMultiShrinkScrollerListener 200b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell = new MultiShrinkScrollerListener() { 201b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 202b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onScrolledOffBottom() { 203b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell onBackPressed(); 204b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 205b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell }; 206b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 207edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @Override 208edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann protected void onCreate(Bundle icicle) { 209dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("c"); // create start 210edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann super.onCreate(icicle); 211edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 212dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("sc"); // super.onCreate 213dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 2142426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann if (TRACE_LAUNCH) android.os.Debug.startMethodTracing(TRACE_TAG); 2152426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann 216dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki // Parse intent 217dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki final Intent intent = getIntent(); 218dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 219dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki Uri lookupUri = intent.getData(); 220dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 221dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki // Check to see whether it comes from the old version. 222dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) { 223dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki final long rawContactId = ContentUris.parseId(lookupUri); 224dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki lookupUri = RawContacts.getContactLookupUri(getContentResolver(), 225dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId)); 226dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki } 227dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 228dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri"); 229dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 230dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES); 231dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 232dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("i"); // intent parsed 233dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 234dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mContactLoader = (ContactLoader) getLoaderManager().initLoader( 235dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki LOADER_ID, null, mLoaderCallbacks); 236dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 237dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("ld"); // loader started 238dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 23910d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa // Show QuickContact in front of soft input 24010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 24110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 24210d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa 243edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann setContentView(R.layout.quickcontact_activity); 244edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 245dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("l"); // layout inflated 246dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 2475ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mEditOrAddContactImage = (ImageView) findViewById(R.id.contact_edit_image); 24872b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen mStarImage = (ImageView) findViewById(R.id.quickcontact_star_button); 2492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCommunicationCard = (ExpandingEntryCardView) findViewById(R.id.communication_card); 250b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller); 2512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCommunicationCard.setTitle(getResources().getString(R.string.communication_card_title)); 252edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 253b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 254b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell mScroller.initialize(mMultiShrinkScrollerListener); 255b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 256b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 2575ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mEditOrAddContactImage.setOnClickListener(mEditContactClickHandler); 2582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCommunicationCard.setOnClickListener(mEntryClickHandler); 259edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 260edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann // find and prepare correct header view 261edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mPhotoContainer = findViewById(R.id.photo_container); 2626219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee 26381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan setHeaderNameText(R.id.name, R.string.missing_name); 264edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 2656219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee mPhotoView = (ImageView) mPhotoContainer.findViewById(R.id.photo); 2665ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mPhotoView.setOnClickListener(mEditContactClickHandler); 2676219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee 268dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("v"); // view initialized 269edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 270b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 271b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell mScroller.setVisibility(View.GONE); 272b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 273dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 274dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("cf"); // onCreate finished 2752426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann } 276edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 277b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private void runEntranceAnimation() { 278b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final int bottomScroll = mScroller.getScrollUntilOffBottom() - 1; 279b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final ObjectAnimator scrollAnimation 280b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell = ObjectAnimator.ofInt(mScroller, "scroll", -bottomScroll, 0); 281b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell scrollAnimation.setDuration(ANIMATION_DURATION); 282b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell scrollAnimation.start(); 283b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 284b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 28581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 28681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan private void setHeaderNameText(int id, int resId) { 28781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan setHeaderNameText(id, getText(resId)); 28881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 28981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 29081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 29181281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan private void setHeaderNameText(int id, CharSequence value) { 29281281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan final View view = mPhotoContainer.findViewById(id); 29381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan if (view instanceof TextView) { 29481281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan if (!TextUtils.isEmpty(value)) { 29581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan ((TextView)view).setText(value); 29681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 29781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 29881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 29981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 30081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** 301edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Check if the given MIME-type appears in the list of excluded MIME-types 302edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * that the most-recent caller requested. 303edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 304edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private boolean isMimeExcluded(String mimeType) { 305edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (mExcludeMimes == null) return false; 306edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String excludedMime : mExcludeMimes) { 307edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (TextUtils.equals(excludedMime, mimeType)) { 308edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 309edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 310edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 311edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 312edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 313edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 314edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 315cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann * Handle the result from the ContactLoader 316edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 317851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private void bindData(Contact data) { 3186cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee mContactData = data; 319edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann final ResolveCache cache = ResolveCache.getInstance(this); 320edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann final Context context = this; 321edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 3225ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mEditOrAddContactImage.setVisibility(isMimeExcluded(Contacts.CONTENT_ITEM_TYPE) ? 3236cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee View.GONE : View.VISIBLE); 32472b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen final boolean isStarred = data.getStarred(); 32572b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen if (isStarred) { 32672b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen mStarImage.setImageResource(R.drawable.ic_favorite_on_lt); 32769f67d00a13279c010d2dde4414a0600dff99294Ben Gilad mStarImage.setContentDescription( 32869f67d00a13279c010d2dde4414a0600dff99294Ben Gilad getResources().getString(R.string.menu_removeStar)); 32972b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen } else { 33072b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen mStarImage.setImageResource(R.drawable.ic_favorite_off_lt); 33169f67d00a13279c010d2dde4414a0600dff99294Ben Gilad mStarImage.setContentDescription( 33269f67d00a13279c010d2dde4414a0600dff99294Ben Gilad getResources().getString(R.string.menu_addStar)); 33372b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen } 33472b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen final Uri lookupUri = data.getLookupUri(); 33572b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen 3362e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee // If this is a json encoded URI, there is no local contact to star 3372e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee if (UriUtils.isEncodedContactUri(lookupUri)) { 3382e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee mStarImage.setVisibility(View.GONE); 3396cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 3406cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee // If directory export support is not allowed, then don't allow the user to add 3416cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee // to contacts 3426cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee if (mContactData.getDirectoryExportSupport() == Directory.EXPORT_SUPPORT_NONE) { 34388df7126c8052ff0676587835662496399e44413Yorke Lee configureHeaderClickActions(false); 3446cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee } else { 34588df7126c8052ff0676587835662496399e44413Yorke Lee configureHeaderClickActions(true); 3466cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee } 3472e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } else { 34888df7126c8052ff0676587835662496399e44413Yorke Lee configureHeaderClickActions(false); 3492e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee mStarImage.setVisibility(View.VISIBLE); 3502e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee mStarImage.setOnClickListener(new OnClickListener() { 3512e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee @Override 3522e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee public void onClick(View view) { 3532e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee // Toggle "starred" state 3542e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee // Make sure there is a contact 3552e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee if (lookupUri != null) { 3562e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee // Changes the state of the image already before sending updates to the 3572e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee // database 3582e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee if (isStarred) { 3592e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee mStarImage.setImageResource(R.drawable.ic_favorite_off_lt); 3602e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } else { 3612e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee mStarImage.setImageResource(R.drawable.ic_favorite_on_lt); 3622e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } 3632e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee 3642e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee // Now perform the real save 3652e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee final Intent intent = ContactSaveService.createSetStarredIntent(context, 3662e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee lookupUri, !isStarred); 3672e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee context.startService(intent); 3682e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } 36972b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen } 3702e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee }); 3712e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } 372edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 373edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mDefaultsMap.clear(); 374edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 375851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mStopWatch.lap("sph"); // Start photo setting 376dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 3776219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee mPhotoSetter.setupContactPhoto(data, mPhotoView); 37831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell extractAndApplyTintFromPhotoViewAsynchronously(); 379edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 380dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("ph"); // Photo set 381dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 382851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContact rawContact : data.getRawContacts()) { 383851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (DataItem dataItem : rawContact.getDataItems()) { 384851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String mimeType = dataItem.getMimeType(); 38547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final AccountType accountType = rawContact.getAccountType(this); 38647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final DataKind dataKind = AccountTypeManager.getInstance(this) 38747b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng .getKindOrFallback(accountType, mimeType); 388cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 389cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Skip this data item if MIME-type excluded 390cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isMimeExcluded(mimeType)) continue; 391cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 392851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long dataId = dataItem.getId(); 393851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final boolean isPrimary = dataItem.isPrimary(); 394851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final boolean isSuperPrimary = dataItem.isSuperPrimary(); 395cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 39647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng if (dataKind != null) { 397cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Build an action for this data entry, find a mapping to a UI 398cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // element, build its summary from the cursor, and collect it 399cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // along with all others of this MIME-type. 40047b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final Action action = new DataAction(context, dataItem, dataKind); 4018a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu final boolean wasAdded = considerAdd(action, cache, isSuperPrimary); 402cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (wasAdded) { 403cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Remember the default 404cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) { 405cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann mDefaultsMap.put(mimeType, action); 406edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 407edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 408edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 409edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 410cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // Handle Email rows with presence data as Im entry 4119daca14706f3699c9e9d46dfb522132fc566e57eDaniel Lehmann final DataStatus status = data.getStatuses().get(dataId); 412851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (status != null && dataItem instanceof EmailDataItem) { 413851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final EmailDataItem email = (EmailDataItem) dataItem; 414851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final ImDataItem im = ImDataItem.createFromEmail(email); 41547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng if (dataKind != null) { 41647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final DataAction action = new DataAction(context, im, dataKind); 4179daca14706f3699c9e9d46dfb522132fc566e57eDaniel Lehmann action.setPresence(status.getPresence()); 4188a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu considerAdd(action, cache, isSuperPrimary); 419cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 420edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 421edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 422edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 423edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 424dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("e"); // Entities inflated 425dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 426edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann // Collapse Action Lists (remove e.g. duplicate e-mail addresses from different sources) 427edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (List<Action> actionChildren : mActions.values()) { 428edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann Collapser.collapseList(actionChildren); 429edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 430edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 431dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("c"); // List collapsed 432dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 433cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann setHeaderNameText(R.id.name, data.getDisplayName()); 434edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 4352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos // List of Entry that makes up the ExpandingEntryCardView 4362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos final List<Entry> entries = new ArrayList<>(); 437edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann // All the mime-types to add. 438edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann final Set<String> containedTypes = new HashSet<String>(mActions.keySet()); 439edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mSortedActionMimeTypes.clear(); 440edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann // First, add LEADING_MIMETYPES, which are most common. 441edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String mimeType : LEADING_MIMETYPES) { 442edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (containedTypes.contains(mimeType)) { 443edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mSortedActionMimeTypes.add(mimeType); 444edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann containedTypes.remove(mimeType); 4452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos entries.addAll(actionsToEntries(mActions.get(mimeType))); 446edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 447edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 448edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 449edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann // Add all the remaining ones that are not TRAILING 450edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String mimeType : containedTypes.toArray(new String[containedTypes.size()])) { 451edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (!TRAILING_MIMETYPES.contains(mimeType)) { 452edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mSortedActionMimeTypes.add(mimeType); 453edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann containedTypes.remove(mimeType); 4542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos entries.addAll(actionsToEntries(mActions.get(mimeType))); 455edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 456edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 457edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 458edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann // Then, add TRAILING_MIMETYPES, which are least common. 459edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String mimeType : TRAILING_MIMETYPES) { 460edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (containedTypes.contains(mimeType)) { 461edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann containedTypes.remove(mimeType); 462edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann mSortedActionMimeTypes.add(mimeType); 4632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos entries.addAll(actionsToEntries(mActions.get(mimeType))); 464edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 465edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 46671032f3fb7038995297666602773ae023c1351c4Brian Attwell mCommunicationCard.initialize(entries, /* numInitialVisibleEntries = */ 2, 4672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /* isExpanded = */ false, /* themeColor = */ 0); 468dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 469edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann final boolean hasData = !mSortedActionMimeTypes.isEmpty(); 4702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCommunicationCard.setVisibility(hasData ? View.VISIBLE: View.GONE); 471edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 472edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 473edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 47431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * Asynchronously extract the most vibrant color from the PhotoView. Once extracted, 47531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms 47631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * on a Nexus 5. 47731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell */ 47831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell private void extractAndApplyTintFromPhotoViewAsynchronously() { 47931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (mScroller == null) { 48031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return; 48131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 48231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 48331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell new AsyncTask<Void, Void, Integer>() { 48431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 48531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell protected Integer doInBackground(Void... params) { 48631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Bitmap bitmap; 48731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (imageViewDrawable instanceof BitmapDrawable) { 48831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap(); 48931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } else if (imageViewDrawable instanceof LetterTileDrawable) { 49031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // LetterTileDrawable doesn't normally draw unless it is visible. Therefore, 49131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // we need to directly ask it for its color via getColor(). We could directly 49231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // return this color. However, in the future Palette#generate() may incorporate 49331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // saturation boosting. So I want to use Palette#generate() for the sake of 49431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // consistency. 49531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final LetterTileDrawable tileDrawable = (LetterTileDrawable) imageViewDrawable; 49631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final int PALETTE_BITMAP_SIZE = 1; 49731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell bitmap = Bitmap.createBitmap(PALETTE_BITMAP_SIZE, 49831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell PALETTE_BITMAP_SIZE, Bitmap.Config.ARGB_8888); 49931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Canvas canvas = new Canvas(bitmap); 50031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell canvas.drawColor(tileDrawable.getColor()); 50131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } else { 50231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return 0; 50331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 50431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // Author of Palette recommends using 24 colors when analyzing profile photos. 50531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final int NUMBER_OF_PALETTE_COLORS = 24; 50631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS); 50731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (palette != null && palette.getVibrantColor() != null) { 50831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return palette.getVibrantColor().getRgb(); 50931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } else { 51031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return 0; 51131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 51231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 51331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 51431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 51531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell protected void onPostExecute(Integer color) { 51631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell super.onPostExecute(color); 51731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (color != 0 && imageViewDrawable == mPhotoView.getDrawable()) { 51831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell // TODO: animate from the previous tint. 51931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell mScroller.setHeaderTintColor(color); 52031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 52131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 52231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell }.execute(); 52331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 52431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 52531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell /** 526edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Consider adding the given {@link Action}, which will only happen if 527edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link PackageManager} finds an application to handle 528edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Action#getIntent()}. 5298a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu * @param action the action to handle 5308a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu * @param resolveCache cache of applications that can handle actions 5318a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu * @param front indicates whether to add the action to the front of the list 532edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * @return true if action has been added 533edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 5348a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu private boolean considerAdd(Action action, ResolveCache resolveCache, boolean front) { 535edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (resolveCache.hasResolve(action)) { 5368a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu mActions.put(action.getMimeType(), action, front); 537edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 538edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 539edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 540edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 541edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 542edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 54388df7126c8052ff0676587835662496399e44413Yorke Lee * Bind the correct image resource and click handlers to the header views 54488df7126c8052ff0676587835662496399e44413Yorke Lee * 54588df7126c8052ff0676587835662496399e44413Yorke Lee * @param canAdd Whether or not the user can directly add information in this quick contact 54688df7126c8052ff0676587835662496399e44413Yorke Lee * to their local contacts 54788df7126c8052ff0676587835662496399e44413Yorke Lee */ 54888df7126c8052ff0676587835662496399e44413Yorke Lee private void configureHeaderClickActions(boolean canAdd) { 54988df7126c8052ff0676587835662496399e44413Yorke Lee if (canAdd) { 550b8eb33c2ef87d0eeac209f43dab1fae51d9ed3ddPaul Soulos mEditOrAddContactImage.setImageResource(R.drawable.ic_person_add_24dp); 5515ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mEditOrAddContactImage.setOnClickListener(mAddToContactsClickHandler); 55288df7126c8052ff0676587835662496399e44413Yorke Lee mPhotoView.setOnClickListener(mAddToContactsClickHandler); 55388df7126c8052ff0676587835662496399e44413Yorke Lee } else { 554b8eb33c2ef87d0eeac209f43dab1fae51d9ed3ddPaul Soulos mEditOrAddContactImage.setImageResource(R.drawable.ic_create_24dp); 5555ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mEditOrAddContactImage.setOnClickListener(mEditContactClickHandler); 5565ec23fdf243596717197a0c45495f24492cf0641Paul Soulos mPhotoView.setOnClickListener(mEditContactClickHandler); 55788df7126c8052ff0676587835662496399e44413Yorke Lee } 55888df7126c8052ff0676587835662496399e44413Yorke Lee } 55988df7126c8052ff0676587835662496399e44413Yorke Lee 56088df7126c8052ff0676587835662496399e44413Yorke Lee /** 5612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Converts a list of Action into a list of Entry 5622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @param actions The list of Action to convert 5632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @return The converted list of Entry 564edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 5652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private List<Entry> actionsToEntries(List<Action> actions) { 5662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos List<Entry> entries = new ArrayList<>(); 5672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos for (Action action : actions) { 5682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos entries.add(new Entry(ResolveCache.getInstance(this).getIcon(action), 5692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos action.getMimeType(), action.getSubtitle().toString(), 5702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos action.getBody().toString(), action.getIntent(), /* isEditable= */ false)); 5712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 5722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return entries; 573edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 574edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 575851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private LoaderCallbacks<Contact> mLoaderCallbacks = 576851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 577cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 578851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 579cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 580cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 581cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 582851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 583dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("lf"); // onLoadFinished 584cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (isFinishing()) { 585cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann return; 586cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 587cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (data.isError()) { 588cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // This shouldn't ever happen, so throw an exception. The {@link ContactLoader} 589cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann // should log the actual exception. 590cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann throw new IllegalStateException("Failed to load contact", data.getException()); 591cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 592cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (data.isNotFound()) { 593cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri()); 594cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage, 595cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Toast.LENGTH_LONG).show(); 596cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann return; 597cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 598cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 599cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann bindData(data); 600cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 601dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.lap("bd"); // bindData finished 602dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 6032426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann if (TRACE_LAUNCH) android.os.Debug.stopMethodTracing(); 604fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 605fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki Log.d(Constants.PERFORMANCE_TAG, "QuickContact shown"); 606fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki } 607cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 608b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 609b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell // Data bound and ready, pull curtain to show. Put this on the Handler to ensure 610b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell // that the layout passes are completed 611b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell mScroller.setVisibility(View.VISIBLE); 612b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 613b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell new Runnable() { 614b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 615b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void run() { 616b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell runEntranceAnimation(); 617b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 618b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell }); 619b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 620dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki mStopWatch.stopAndLog(TAG, 0); 621b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell mStopWatch = StopWatch.getNullStopWatch(); 622cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 623cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 624cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 625851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 626cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (mLookupUri == null) { 627cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early"); 628cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 629b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee return new ContactLoader(getApplicationContext(), mLookupUri, 63045f23d4d67438c0561f74ef87b7028f6d74f7503Paul Sliwowski false /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/, 63145f23d4d67438c0561f74ef87b7028f6d74f7503Paul Sliwowski false /*postViewNotification*/, true /*computeFormattedPhoneNumber*/); 632cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 633cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann }; 634b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 635b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onBackPressed() { 636b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 637b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell // TODO: implement exit animation if the scroller isn't already off the screen 638b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell finish(); 639b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } else { 640b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell super.onBackPressed(); 641b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 642b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 643edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann} 644