DialtactsActivity.java revision 7979ea27c046dfc2d9305b3282233046acef6ec4
1032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov/* 2032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Copyright (C) 2008 The Android Open Source Project 3032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * 4032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * you may not use this file except in compliance with the License. 6032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * You may obtain a copy of the License at 7032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * 8032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * 10032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 12032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * See the License for the specific language governing permissions and 14032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * limitations under the License. 15032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 16032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 1709fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmannpackage com.android.contacts.activities; 18032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 1909fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmannimport com.android.contacts.R; 20c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport com.android.contacts.calllog.CallLogFragment; 21c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport com.android.contacts.dialpad.DialpadFragment; 22aae838c5a7ef38f4f2778cff6dfaa1f650a44522Daniel Lehmannimport com.android.contacts.interactions.PhoneNumberInteraction; 23b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport com.android.contacts.list.OnPhoneNumberPickerActionListener; 24b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport com.android.contacts.list.PhoneNumberPickerFragment; 257979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaroimport com.android.contacts.list.ContactTileListFragment; 26b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamiltonimport com.android.internal.telephony.ITelephony; 27b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamilton 28c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.ActionBar; 29b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.app.ActionBar.LayoutParams; 30c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.ActionBar.Tab; 31c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.ActionBar.TabListener; 32032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.app.Activity; 33c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.Fragment; 34c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.FragmentManager; 35c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.FragmentTransaction; 36c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasaniimport android.content.Context; 37032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.content.Intent; 38903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamiltonimport android.content.SharedPreferences; 39032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.net.Uri; 40032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.os.Bundle; 41032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.os.RemoteException; 42032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.os.ServiceManager; 43032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.provider.CallLog.Calls; 44b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamiltonimport android.provider.ContactsContract.Intents.UI; 45438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawaimport android.support.v13.app.FragmentPagerAdapter; 46438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawaimport android.support.v4.view.ViewPager; 47438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawaimport android.support.v4.view.ViewPager.OnPageChangeListener; 48b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.text.TextUtils; 49032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.util.Log; 50c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.view.Menu; 51c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.view.MenuInflater; 52c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.view.MenuItem; 53aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawaimport android.view.MenuItem.OnMenuItemClickListener; 54b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.view.View; 55c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasaniimport android.view.View.OnAttachStateChangeListener; 56c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasaniimport android.view.inputmethod.InputMethodManager; 57b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.widget.SearchView; 58b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.widget.SearchView.OnCloseListener; 59b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.widget.SearchView.OnQueryTextListener; 60032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 61032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov/** 6208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * The dialer activity that has one tab with the virtual 12key 6308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * dialer, a tab with recent calls in it, a tab with the contacts and 6408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * a tab with the favorite. This is the container and the tabs are 6508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * embedded using intents. 6608832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * The dialer tab's title is 'phone', a more common name (see strings.xml). 67032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 68c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannpublic class DialtactsActivity extends Activity { 6909fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmann private static final String TAG = "DialtactsActivity"; 707675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 7143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa /** Used to open Call Setting */ 7243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private static final String PHONE_PACKAGE = "com.android.phone"; 7343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private static final String CALL_SETTINGS_CLASS_NAME = 7443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa "com.android.phone.CallFeaturesSetting"; 7543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 76438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa /** Used both by {@link ActionBar} and {@link ViewPagerAdapter} */ 77032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private static final int TAB_INDEX_DIALER = 0; 78032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private static final int TAB_INDEX_CALL_LOG = 1; 7920962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa private static final int TAB_INDEX_FAVORITES = 2; 8020962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa 8120962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa private static final int TAB_INDEX_COUNT = 3; 8208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 83903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton /** Name of the dialtacts shared preferences */ 84903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton static final String PREFS_DIALTACTS = "dialtacts"; 85903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false; 86903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton 877675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann /** Last manually selected tab index */ 887675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab"; 897675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER; 907675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 91438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa /** 92438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa * Listener interface for Fragments accommodated in {@link ViewPager} enabling them to know 93438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa * when it becomes visible or invisible inside the ViewPager. 94438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa */ 95438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public interface ViewPagerVisibilityListener { 96aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa public void onVisibilityChanged(boolean visible); 97438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 98438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 99438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public class ViewPagerAdapter extends FragmentPagerAdapter { 100438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public ViewPagerAdapter(FragmentManager fm) { 101438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa super(fm); 102438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 103438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 104438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa @Override 105438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public Fragment getItem(int position) { 106438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa switch (position) { 107438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa case TAB_INDEX_DIALER: 10843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa return new DialpadFragment(); 109438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa case TAB_INDEX_CALL_LOG: 11043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa return new CallLogFragment(); 111438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa case TAB_INDEX_FAVORITES: 1127979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro return new ContactTileListFragment(); 113438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 114438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa throw new IllegalStateException("No fragment at position " + position); 115438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 116438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 117438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa @Override 118438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public int getCount() { 119438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa return TAB_INDEX_COUNT; 120438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 121438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 122438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 123438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa private class PageChangeListener implements OnPageChangeListener { 124aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private int mPreviousPosition = -1; // Invalid at first 125aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 126438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa @Override 127438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public void onPageScrolled( 128438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa int position, float positionOffset, int positionOffsetPixels) { 129438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 130438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 131438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa @Override 132438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public void onPageSelected(int position) { 133438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa final ActionBar actionBar = getActionBar(); 134aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa if (mPreviousPosition == position) { 135aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa Log.w(TAG, "Previous position and next position became same (" + position + ")"); 136aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 137aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 138aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa if (mPreviousPosition >= 0) { 13943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(mPreviousPosition, false); 140aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 14143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(position, true); 142aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 143438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa actionBar.selectTab(actionBar.getTabAt(position)); 144aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 145aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa // Activity#onPrepareOptionsMenu() may not be called when Fragment has it's own 146aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa // options menu. We force this Activity to call it to hide/show bottom bar. Also 147aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa // we don't want to do so when it is unnecessary (buttons may flicker). 148aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa if (mPreviousPosition == TAB_INDEX_DIALER || position == TAB_INDEX_DIALER) { 149aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa // Force this Activity to prepare Menu again. 150aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa invalidateOptionsMenu(); 151aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 152aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 153aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mPreviousPosition = position; 154438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 155438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 15643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void setCurrentPosition(int position) { 15743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mPreviousPosition = position; 15843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 15943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 160438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa @Override 161438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa public void onPageScrollStateChanged(int state) { 162438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 163438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 164438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 16508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania private String mFilterText; 166032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private Uri mDialUri; 167438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 168438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa /** Enables horizontal swipe between Fragments. */ 169438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa private ViewPager mViewPager; 17043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private final PageChangeListener mPageChangeListener = new PageChangeListener(); 171c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private DialpadFragment mDialpadFragment; 172c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private CallLogFragment mCallLogFragment; 1737979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro private ContactTileListFragment mStrequentFragment; 174032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 1752c1f7878d72184a56e9c2b0d9f4d74be439979c2Daisuke Miyakawa private final TabListener mTabListener = new TabListener() { 17643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa @Override 17743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void onTabUnselected(Tab tab, FragmentTransaction ft) { 17843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 17943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 18043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa @Override 18143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void onTabSelected(Tab tab, FragmentTransaction ft) { 18243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mViewPager.getCurrentItem() != tab.getPosition()) { 18343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mViewPager.setCurrentItem(tab.getPosition(), false /* smoothScroll */); 18443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 18543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 18643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa // During the call, we don't remember the tab position. 18743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (!DialpadFragment.phoneIsInUse()) { 18843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa // Remember this tab index. This function is also called, if the tab is set 18943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa // automatically in which case the setter (setCurrentTab) has to set this to its old 19043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa // value afterwards 19143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mLastManuallySelectedFragment = tab.getPosition(); 19243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 19343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 19443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 19543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa @Override 19643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void onTabReselected(Tab tab, FragmentTransaction ft) { 19743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 19843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa }; 19943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 2007675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann /** 201b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Fragment for searching phone numbers. Unlike the other Fragments, this doesn't correspond 202b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * to tab but is shown by a search action. 203b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 204aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private PhoneNumberPickerFragment mSearchFragment; 205b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 206b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * True when this Activity is in its search UI (with a {@link SearchView} and 207b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * {@link PhoneNumberPickerFragment}). 208b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 209b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private boolean mInSearchUi; 210aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private SearchView mSearchView; 211b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 212b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 213aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa * The index of the Fragment (or, the tab) that has last been manually selected. 214cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call) 215cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa */ 216aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private int mLastManuallySelectedFragment; 217cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa 218cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa /** 219b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Listener used when one of phone numbers in search UI is selected. This will initiate a 220b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * phone call using the phone number. 221b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 222b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private final OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener = 223b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa new OnPhoneNumberPickerActionListener() { 224b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 225b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public void onPickPhoneNumberAction(Uri dataUri) { 226b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa PhoneNumberInteraction.startInteractionForPhoneCall( 227b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa DialtactsActivity.this, dataUri); 228b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 229b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 230b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 231b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public void onShortcutIntentCreated(Intent intent) { 232b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa Log.w(TAG, "Unsupported intent has come (" + intent + "). Ignoring."); 233b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 23488f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa 23588f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa @Override 23688f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa public void onHomeInActionBarSelected() { 23788f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa exitSearchUi(); 23888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa } 239b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa }; 240b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 241b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 242b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Listener used to send search queries to the phone search fragment. 243b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 244b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private final OnQueryTextListener mPhoneSearchQueryTextListener = 245b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa new OnQueryTextListener() { 246b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 247b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public boolean onQueryTextSubmit(String query) { 248b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // Ignore. 249b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa return true; 250b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 251b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 252b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 253b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public boolean onQueryTextChange(String newText) { 254b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // Show search result with non-empty text. Show a bare list otherwise. 255aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mSearchFragment.setQueryString(newText, true); 256aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mSearchFragment.setSearchMode(!TextUtils.isEmpty(newText)); 257b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa return true; 258b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 259b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa }; 260b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 261b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 262b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Listener used to handle the "close" button on the right side of {@link SearchView}. 263b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * If some text is in the search view, this will clean it up. Otherwise this will exit 264b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * the search UI and let users go back to usual Phone UI. 265b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * 266b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * This does _not_ handle back button. 267b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * 268b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * TODO: need "up" button instead of close button 269b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 270b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private final OnCloseListener mPhoneSearchCloseListener = 271b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa new OnCloseListener() { 272b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 273b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public boolean onClose() { 274b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa if (TextUtils.isEmpty(mSearchView.getQuery())) { 275b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa exitSearchUi(); 276b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else { 277b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setQuery(null, true); 278b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 279b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa return true; 280b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 281b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa }; 282b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 283032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov @Override 284032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov protected void onCreate(Bundle icicle) { 285032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov super.onCreate(icicle); 286032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 287032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final Intent intent = getIntent(); 288032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov fixIntent(intent); 28908832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 29009fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmann setContentView(R.layout.dialtacts_activity); 291032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 292438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa mViewPager = (ViewPager) findViewById(R.id.pager); 293438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager())); 29443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mViewPager.setOnPageChangeListener(mPageChangeListener); 295c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann 296c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann // Setup the ActionBar tabs (the order matches the tab-index contants TAB_INDEX_*) 297c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann setupDialer(); 298c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann setupCallLog(); 299c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann setupFavorites(); 300c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 301c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().setDisplayShowTitleEnabled(false); 302c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().setDisplayShowHomeEnabled(false); 303032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 3047675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // Load the last manually loaded tab 3057675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE); 306aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mLastManuallySelectedFragment = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB, 3077675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT); 308aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa if (mLastManuallySelectedFragment >= TAB_INDEX_COUNT) { 30920962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa // Stored value may have exceeded the number of current tabs. Reset it. 310aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mLastManuallySelectedFragment = PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT; 31120962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa } 3127675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 313032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setCurrentTab(intent); 314903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton 3157fa3cd652fdaa5284fdf5fa9c306f2ca89227c1aJeff Hamilton if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction()) 316903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton && icicle == null) { 317903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton setupFilterText(intent); 318903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 319032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 320032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 321903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton @Override 32243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void onAttachFragment(Fragment fragment) { 32343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa // This method can be called before onCreate(), at which point we cannot rely on ViewPager. 32443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa // In that case, we will setup the "current position" soon after the ViewPager is ready. 32543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa final int currentPosition = mViewPager != null ? mViewPager.getCurrentItem() : -1; 32643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 32743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (fragment instanceof DialpadFragment) { 32843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mDialpadFragment = (DialpadFragment) fragment; 32943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mDialpadFragment.setListener(mDialpadListener); 33043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mDialpadFragment.onVisibilityChanged(currentPosition == TAB_INDEX_DIALER); 33143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else if (fragment instanceof CallLogFragment) { 33243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mCallLogFragment = (CallLogFragment) fragment; 33343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mCallLogFragment.onVisibilityChanged(currentPosition == TAB_INDEX_CALL_LOG); 3347979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro } else if (fragment instanceof ContactTileListFragment) { 3357979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mStrequentFragment = (ContactTileListFragment) fragment; 3367979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mStrequentFragment.enableQuickContact(false); 3377979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mStrequentFragment.enableSecondaryTarget(true); 33843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mStrequentFragment.setListener(mStrequentListener); 33943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else if (fragment instanceof PhoneNumberPickerFragment) { 34043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment = (PhoneNumberPickerFragment) fragment; 34143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment.setOnPhoneNumberPickerActionListener(mPhoneNumberPickerActionListener); 34243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment.setQuickContactEnabled(true); 34343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 34443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mInSearchUi) { 34543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa transaction.show(mSearchFragment); 34643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else { 34743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa transaction.hide(mSearchFragment); 34843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 34943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa transaction.commit(); 35043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 35143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 35243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 35343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa @Override 354903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton protected void onPause() { 355903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton super.onPause(); 35608832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 3577675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann final SharedPreferences.Editor editor = 3587675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit(); 359aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedFragment); 3607675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 361909271c9b60f755a5298c611400502e7418d161bBrad Fitzpatrick editor.apply(); 362903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 36308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 364032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private void fixIntent(Intent intent) { 365032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // This should be cleaned up: the call key used to send an Intent 366032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // that just said to go to the recent calls list. It now sends this 367032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // abstract action, but this class hasn't been rewritten to deal with it. 368032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) { 369032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE); 370032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov intent.putExtra("call_key", true); 371032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setIntent(intent); 372032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 373032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 37408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 375c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private void setupDialer() { 376c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann final Tab tab = getActionBar().newTab(); 37700848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // TODO: Temporarily disable tab text labels (in all 4 tabs in this 37800848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // activity) so that the current tabs will all fit onscreen in 37900848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // portrait (bug 4520620). (Also note we do setText("") rather 38000848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // leaving the text null, to work around bug 4521549.) 38100848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown tab.setText(""); // R.string.dialerIconLabel 38243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa tab.setTabListener(mTabListener); 383c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann tab.setIcon(R.drawable.ic_tab_dialer); 384c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().addTab(tab); 385032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 386032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 387c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private void setupCallLog() { 388c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann final Tab tab = getActionBar().newTab(); 38900848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown tab.setText(""); // R.string.recentCallsIconLabel 390c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann tab.setIcon(R.drawable.ic_tab_recent); 39143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa tab.setTabListener(mTabListener); 392c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().addTab(tab); 393032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 394032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 395c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private void setupFavorites() { 396c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann final Tab tab = getActionBar().newTab(); 39700848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown tab.setText(""); // R.string.contactsFavoritesLabel 398c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann tab.setIcon(R.drawable.ic_tab_starred); 39943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa tab.setTabListener(mTabListener); 400c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().addTab(tab); 4019add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan } 4029add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan 403032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 404032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Returns true if the intent is due to hitting the green send key while in a call. 40508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 406032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @param intent the intent that launched this activity 407032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @param recentCallsRequest true if the intent is requesting to view recent calls 40808832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * @return true if the intent is due to hitting the green send key while in a call 409032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 410aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private boolean isSendKeyWhileInCall(final Intent intent, 411aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa final boolean recentCallsRequest) { 412032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // If there is a call in progress go to the call screen 413032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (recentCallsRequest) { 414032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final boolean callKey = intent.getBooleanExtra("call_key", false); 415032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 416032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov try { 417032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 418032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (callKey && phone != null && phone.showCallScreen()) { 419032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return true; 420032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 421032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } catch (RemoteException e) { 422032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov Log.e(TAG, "Failed to handle send while in call", e); 423032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 424032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 425032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 426032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return false; 427032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 428032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 429032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 430032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Sets the current tab based on the intent's request type 43108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 4327675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann * @param intent Intent that contains information about which tab should be selected 433032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 434032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private void setCurrentTab(Intent intent) { 435032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // If we got here by hitting send and we're in call forward along to the in-call activity 436032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType()); 437032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (isSendKeyWhileInCall(intent, recentCallsRequest)) { 438032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov finish(); 439032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return; 440032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 44108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 4427675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // Remember the old manually selected tab index so that it can be restored if it is 4437675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // overwritten by one of the programmatic tab selections 444aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa final int savedTabIndex = mLastManuallySelectedFragment; 4457675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 446438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa final int tabIndex; 447438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa if (DialpadFragment.phoneIsInUse() || isDialIntent(intent)) { 448438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa tabIndex = TAB_INDEX_DIALER; 449c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa } else if (recentCallsRequest) { 450438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa tabIndex = TAB_INDEX_CALL_LOG; 451903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } else { 452aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa tabIndex = mLastManuallySelectedFragment; 453032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 454aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mViewPager.setCurrentItem(tabIndex, false /* smoothScroll */); 45543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mViewPager.getCurrentItem() == tabIndex) { 45643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mPageChangeListener.setCurrentPosition(tabIndex); 45743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(tabIndex, true); 45843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else { 45943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa getActionBar().selectTab(getActionBar().getTabAt(tabIndex)); 46043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 461032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 4627675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // Restore to the previous manual selection 463aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mLastManuallySelectedFragment = savedTabIndex; 464032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 465032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 466032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov @Override 467032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov public void onNewIntent(Intent newIntent) { 468032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setIntent(newIntent); 469032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov fixIntent(newIntent); 470032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setCurrentTab(newIntent); 471903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton final String action = newIntent.getAction(); 4727fa3cd652fdaa5284fdf5fa9c306f2ca89227c1aJeff Hamilton if (UI.FILTER_CONTACTS_ACTION.equals(action)) { 473903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton setupFilterText(newIntent); 474903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } else if (isDialIntent(newIntent)) { 475032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setupDialUri(newIntent); 476032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 47743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mInSearchUi || mSearchFragment.isVisible()) { 478438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa exitSearchUi(); 479438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 480032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 481032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 482032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** Returns true if the given intent contains a phone number to populate the dialer with */ 483032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private boolean isDialIntent(Intent intent) { 484032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final String action = intent.getAction(); 485032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (Intent.ACTION_DIAL.equals(action)) { 486032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return true; 487032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 488032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (Intent.ACTION_VIEW.equals(action)) { 489032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final Uri data = intent.getData(); 490032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (data != null && "tel".equals(data.getScheme())) { 491032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return true; 492032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 493032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 494032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return false; 495032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 49608832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 497903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton /** 498903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * Retrieves the filter text stored in {@link #setupFilterText(Intent)}. 499903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * This text originally came from a FILTER_CONTACTS_ACTION intent received 500903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * by this activity. The stored text will then be cleared after after this 501903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * method returns. 50208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 503903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * @return The stored filter text 504903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton */ 505903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton public String getAndClearFilterText() { 506903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton String filterText = mFilterText; 507903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton mFilterText = null; 508903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton return filterText; 509903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 510903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton 511903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton /** 512903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent. 513903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * This is so child activities can check if they are supposed to display a filter. 51408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 515903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * @param intent The intent received in {@link #onNewIntent(Intent)} 516903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton */ 517903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton private void setupFilterText(Intent intent) { 518903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton // If the intent was relaunched from history, don't apply the filter text. 519903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 520903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton return; 521903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 522b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamilton String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY); 523903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton if (filter != null && filter.length() > 0) { 524903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton mFilterText = filter; 525903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 526903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 527032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 528032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 529032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri 530032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * originally came from a dial intent received by this activity. The stored 531032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * uri will then be cleared after after this method returns. 53208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 533032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @return The stored uri 534032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 535032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov public Uri getAndClearDialUri() { 536032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov Uri dialUri = mDialUri; 537032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov mDialUri = null; 538032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return dialUri; 539032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 540032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 541032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 542032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Stores the uri associated with a dial intent. This is so child activities can 543032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * check if they are supposed to display new dial info. 54408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 545032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @param intent The intent received in {@link #onNewIntent(Intent)} 546032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 547032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private void setupDialUri(Intent intent) { 548032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // If the intent was relaunched from history, don't reapply the intent. 549032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 550032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return; 551032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 552032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov mDialUri = intent.getData(); 553032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 554032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 555032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov @Override 556242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn public void onBackPressed() { 557b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa if (mInSearchUi) { 558b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // We should let the user go back to usual screens with tabs. 559b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa exitSearchUi(); 560b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else if (isTaskRoot()) { 561032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // Instead of stopping, simply push this to the back of the stack. 562032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // This is only done when running at the top of the stack; 563032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // otherwise, we have been launched by someone else so need to 564032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // allow the user to go back to the caller. 565032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov moveTaskToBack(false); 566242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn } else { 567242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn super.onBackPressed(); 568032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 569032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 570032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 57143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private DialpadFragment.Listener mDialpadListener = new DialpadFragment.Listener() { 572c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann @Override 57343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void onSearchButtonPressed() { 57443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa enterSearchUi(); 575c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 57643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa }; 577c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann 5787979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro private ContactTileListFragment.Listener mStrequentListener = 5797979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro new ContactTileListFragment.Listener() { 58032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 58132f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public void onContactSelected(Uri contactUri) { 582b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa PhoneNumberInteraction.startInteractionForPhoneCall( 583b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa DialtactsActivity.this, contactUri); 58432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro } 58532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro }; 58632f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro 587c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann @Override 588c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann public boolean onCreateOptionsMenu(Menu menu) { 589c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann MenuInflater inflater = getMenuInflater(); 590aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa inflater.inflate(R.menu.dialtacts_options, menu); 591c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann return true; 592c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 593c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann 594c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann @Override 595aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa public boolean onPrepareOptionsMenu(Menu menu) { 596aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa final MenuItem searchMenuItem = menu.findItem(R.id.search_on_action_bar); 597aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa if (mInSearchUi || getActionBar().getSelectedTab().getPosition() == TAB_INDEX_DIALER) { 598aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa searchMenuItem.setVisible(false); 599aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } else { 600aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa searchMenuItem.setVisible(true); 601aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa searchMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { 602aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa @Override 603aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa public boolean onMenuItemClick(MenuItem item) { 604aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa enterSearchUi(); 605aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return true; 606aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 607c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann }); 608c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 609aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 610aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return true; 611c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 612b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 613b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 614b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public void startSearch(String initialQuery, boolean selectInitialQuery, 615b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa Bundle appSearchData, boolean globalSearch) { 61643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mSearchFragment != null && mSearchFragment.isAdded() && !globalSearch) { 617b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa enterSearchUi(); 618b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else { 619b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch); 620b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 621b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 622b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 623b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 624b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Hides every tab and shows search UI for phone lookup. 625b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 626b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private void enterSearchUi() { 627b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final ActionBar actionBar = getActionBar(); 628b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 629b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final Tab tab = actionBar.getSelectedTab(); 630c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa 631c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa // User can search during the call, but we don't want to remember the status. 632c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa if (tab != null && !DialpadFragment.phoneIsInUse()) { 633aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mLastManuallySelectedFragment = tab.getPosition(); 634b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 635b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 636b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // Instantiate or reset SearchView in ActionBar. 637b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa if (mSearchView == null) { 638b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // TODO: layout is not what we want. Need "up" button instead of "close" button, etc. 639b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final View searchViewLayout = 640b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa getLayoutInflater().inflate(R.layout.custom_action_bar, null); 641b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView = (SearchView) searchViewLayout.findViewById(R.id.search_view); 642b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setQueryHint(getString(R.string.hint_findContacts)); 643b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener); 644b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setOnCloseListener(mPhoneSearchCloseListener); 645b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.requestFocus(); 64636c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa // Show soft keyboard when SearchView has a focus. Need to delay the request in order 64736c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa // to let InputMethodManager handle it correctly. 648c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani mSearchView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { 649c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani @Override 650c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani public void onViewDetachedFromWindow(View v) { 651c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 652c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani 653c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani @Override 654c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani public void onViewAttachedToWindow(View v) { 655c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani if (mSearchView.hasFocus()) { 656c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani mSearchView.postDelayed(new Runnable() { 657c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani public void run() { 658c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani showInputMethod(mSearchView.findFocus()); 659c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 660c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani }, 0); 661c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 662c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 663c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani }); 664b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setCustomView(searchViewLayout, 665b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 666b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else { 667b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setQuery(null, true); 668b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 669b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 670b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setDisplayShowCustomEnabled(true); 671b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 67288f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa actionBar.setDisplayShowHomeEnabled(true); 67388f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa actionBar.setDisplayHomeAsUpEnabled(true); 674b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 67543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(mViewPager.getCurrentItem(), false); 67643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 677b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // Show the search fragment and hide everything else. 678b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 679aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa transaction.show(mSearchFragment); 680b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa transaction.commit(); 681438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa mViewPager.setVisibility(View.GONE); 682b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 683b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mInSearchUi = true; 684b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 685b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 686c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani private void showInputMethod(View view) { 687c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 688c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani if (imm != null) { 689c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani imm.showSoftInput(view, 0); 690c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 691c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 692c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani 69388f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa private void hideInputMethod(View view) { 69488f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 69588f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa if (imm != null) { 69688f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 69788f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa } 69888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa } 69988f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa 700b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 701b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment 702b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * should be automatically focused again. 703b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 704b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private void exitSearchUi() { 705b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final ActionBar actionBar = getActionBar(); 706b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 707b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // We want to hide SearchView and show Tabs. Also focus on previously selected one. 708b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setDisplayShowCustomEnabled(false); 70988f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa actionBar.setDisplayShowHomeEnabled(false); 710b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 711b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 71243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(mViewPager.getCurrentItem(), true); 71343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 714438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 715aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa transaction.hide(mSearchFragment); 716438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa transaction.commit(); 717438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 718438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa mViewPager.setVisibility(View.VISIBLE); 719438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 72088f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa hideInputMethod(getCurrentFocus()); 72188f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa 722350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa // Request to update option menu. 723350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa invalidateOptionsMenu(); 724350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa 725b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mInSearchUi = false; 726b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 727aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 728aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private Fragment getFragmentAt(int position) { 729aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa switch (position) { 730aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa case TAB_INDEX_DIALER: 731aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return mDialpadFragment; 732aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa case TAB_INDEX_CALL_LOG: 733aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return mCallLogFragment; 734aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa case TAB_INDEX_FAVORITES: 735aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return mStrequentFragment; 736aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa default: 737aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa throw new IllegalStateException("Unknown fragment index: " + position); 738aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 739aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 74043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 74143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private void sendFragmentVisibilityChange(int position, boolean visibility) { 74243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa final Fragment fragment = getFragmentAt(position); 74343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (fragment instanceof ViewPagerVisibilityListener) { 74443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa ((ViewPagerVisibilityListener) fragment).onVisibilityChanged(visibility); 74543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 74643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 747bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa 748bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa /** Returns an Intent to launch Call Settings screen */ 749bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa public static Intent getCallSettingsIntent() { 750bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa final Intent intent = new Intent(Intent.ACTION_MAIN); 751bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa intent.setClassName(PHONE_PACKAGE, CALL_SETTINGS_CLASS_NAME); 752bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa return intent; 753bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa } 754032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov} 755