DialtactsActivity.java revision bd762dc826d85e5b7db634ef14a0dbb70c42eaab
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; 25aae838c5a7ef38f4f2778cff6dfaa1f650a44522Daniel Lehmannimport com.android.contacts.list.StrequentContactListFragment; 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: 11243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa return new StrequentContactListFragment(); 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; 173aae838c5a7ef38f4f2778cff6dfaa1f650a44522Daniel Lehmann private StrequentContactListFragment 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); 33443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else if (fragment instanceof StrequentContactListFragment) { 33543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mStrequentFragment = (StrequentContactListFragment) fragment; 33643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mStrequentFragment.setListener(mStrequentListener); 33743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else if (fragment instanceof PhoneNumberPickerFragment) { 33843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment = (PhoneNumberPickerFragment) fragment; 33943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment.setOnPhoneNumberPickerActionListener(mPhoneNumberPickerActionListener); 34043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment.setNameHighlightingEnabled(true); 34143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mSearchFragment.setQuickContactEnabled(true); 34243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 34343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mInSearchUi) { 34443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa transaction.show(mSearchFragment); 34543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else { 34643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa transaction.hide(mSearchFragment); 34743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 34843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa transaction.commit(); 34943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 35043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 35143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 35243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa @Override 353903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton protected void onPause() { 354903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton super.onPause(); 35508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 3567675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann final SharedPreferences.Editor editor = 3577675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit(); 358aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedFragment); 3597675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 360909271c9b60f755a5298c611400502e7418d161bBrad Fitzpatrick editor.apply(); 361903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 36208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 363032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private void fixIntent(Intent intent) { 364032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // This should be cleaned up: the call key used to send an Intent 365032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // that just said to go to the recent calls list. It now sends this 366032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // abstract action, but this class hasn't been rewritten to deal with it. 367032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) { 368032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE); 369032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov intent.putExtra("call_key", true); 370032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setIntent(intent); 371032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 372032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 37308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 374c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private void setupDialer() { 375c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann final Tab tab = getActionBar().newTab(); 37600848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // TODO: Temporarily disable tab text labels (in all 4 tabs in this 37700848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // activity) so that the current tabs will all fit onscreen in 37800848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // portrait (bug 4520620). (Also note we do setText("") rather 37900848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown // leaving the text null, to work around bug 4521549.) 38000848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown tab.setText(""); // R.string.dialerIconLabel 38143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa tab.setTabListener(mTabListener); 382c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann tab.setIcon(R.drawable.ic_tab_dialer); 383c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().addTab(tab); 384032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 385032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 386c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private void setupCallLog() { 387c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann final Tab tab = getActionBar().newTab(); 38800848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown tab.setText(""); // R.string.recentCallsIconLabel 389c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann tab.setIcon(R.drawable.ic_tab_recent); 39043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa tab.setTabListener(mTabListener); 391c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().addTab(tab); 392032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 393032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 394c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann private void setupFavorites() { 395c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann final Tab tab = getActionBar().newTab(); 39600848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown tab.setText(""); // R.string.contactsFavoritesLabel 397c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann tab.setIcon(R.drawable.ic_tab_starred); 39843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa tab.setTabListener(mTabListener); 399c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann getActionBar().addTab(tab); 4009add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan } 4019add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan 402032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 403032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Returns true if the intent is due to hitting the green send key while in a call. 40408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 405032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @param intent the intent that launched this activity 406032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @param recentCallsRequest true if the intent is requesting to view recent calls 40708832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * @return true if the intent is due to hitting the green send key while in a call 408032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 409aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private boolean isSendKeyWhileInCall(final Intent intent, 410aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa final boolean recentCallsRequest) { 411032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // If there is a call in progress go to the call screen 412032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (recentCallsRequest) { 413032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final boolean callKey = intent.getBooleanExtra("call_key", false); 414032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 415032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov try { 416032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 417032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (callKey && phone != null && phone.showCallScreen()) { 418032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return true; 419032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 420032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } catch (RemoteException e) { 421032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov Log.e(TAG, "Failed to handle send while in call", e); 422032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 423032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 424032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 425032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return false; 426032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 427032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 428032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 429032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Sets the current tab based on the intent's request type 43008832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 4317675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann * @param intent Intent that contains information about which tab should be selected 432032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 433032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private void setCurrentTab(Intent intent) { 434032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // If we got here by hitting send and we're in call forward along to the in-call activity 435032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType()); 436032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (isSendKeyWhileInCall(intent, recentCallsRequest)) { 437032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov finish(); 438032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return; 439032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 44008832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 4417675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // Remember the old manually selected tab index so that it can be restored if it is 4427675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // overwritten by one of the programmatic tab selections 443aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa final int savedTabIndex = mLastManuallySelectedFragment; 4447675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann 445438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa final int tabIndex; 446438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa if (DialpadFragment.phoneIsInUse() || isDialIntent(intent)) { 447438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa tabIndex = TAB_INDEX_DIALER; 448c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa } else if (recentCallsRequest) { 449438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa tabIndex = TAB_INDEX_CALL_LOG; 450903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } else { 451aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa tabIndex = mLastManuallySelectedFragment; 452032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 453aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mViewPager.setCurrentItem(tabIndex, false /* smoothScroll */); 45443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mViewPager.getCurrentItem() == tabIndex) { 45543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa mPageChangeListener.setCurrentPosition(tabIndex); 45643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(tabIndex, true); 45743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } else { 45843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa getActionBar().selectTab(getActionBar().getTabAt(tabIndex)); 45943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 460032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 4617675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann // Restore to the previous manual selection 462aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mLastManuallySelectedFragment = savedTabIndex; 463032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 464032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 465032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov @Override 466032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov public void onNewIntent(Intent newIntent) { 467032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setIntent(newIntent); 468032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov fixIntent(newIntent); 469032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setCurrentTab(newIntent); 470903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton final String action = newIntent.getAction(); 4717fa3cd652fdaa5284fdf5fa9c306f2ca89227c1aJeff Hamilton if (UI.FILTER_CONTACTS_ACTION.equals(action)) { 472903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton setupFilterText(newIntent); 473903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } else if (isDialIntent(newIntent)) { 474032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov setupDialUri(newIntent); 475032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 47643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mInSearchUi || mSearchFragment.isVisible()) { 477438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa exitSearchUi(); 478438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa } 479032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 480032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 481032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** Returns true if the given intent contains a phone number to populate the dialer with */ 482032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private boolean isDialIntent(Intent intent) { 483032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final String action = intent.getAction(); 484032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (Intent.ACTION_DIAL.equals(action)) { 485032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return true; 486032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 487032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (Intent.ACTION_VIEW.equals(action)) { 488032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov final Uri data = intent.getData(); 489032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if (data != null && "tel".equals(data.getScheme())) { 490032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return true; 491032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 492032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 493032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return false; 494032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 49508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania 496903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton /** 497903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * Retrieves the filter text stored in {@link #setupFilterText(Intent)}. 498903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * This text originally came from a FILTER_CONTACTS_ACTION intent received 499903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * by this activity. The stored text will then be cleared after after this 500903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * method returns. 50108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 502903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * @return The stored filter text 503903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton */ 504903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton public String getAndClearFilterText() { 505903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton String filterText = mFilterText; 506903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton mFilterText = null; 507903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton return filterText; 508903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 509903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton 510903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton /** 511903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent. 512903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * This is so child activities can check if they are supposed to display a filter. 51308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 514903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton * @param intent The intent received in {@link #onNewIntent(Intent)} 515903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton */ 516903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton private void setupFilterText(Intent intent) { 517903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton // If the intent was relaunched from history, don't apply the filter text. 518903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 519903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton return; 520903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 521b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamilton String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY); 522903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton if (filter != null && filter.length() > 0) { 523903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton mFilterText = filter; 524903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 525903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton } 526032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 527032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 528032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri 529032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * originally came from a dial intent received by this activity. The stored 530032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * uri will then be cleared after after this method returns. 53108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 532032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @return The stored uri 533032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 534032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov public Uri getAndClearDialUri() { 535032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov Uri dialUri = mDialUri; 536032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov mDialUri = null; 537032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return dialUri; 538032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 539032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 540032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov /** 541032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Stores the uri associated with a dial intent. This is so child activities can 542032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * check if they are supposed to display new dial info. 54308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * 544032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * @param intent The intent received in {@link #onNewIntent(Intent)} 545032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */ 546032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov private void setupDialUri(Intent intent) { 547032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // If the intent was relaunched from history, don't reapply the intent. 548032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 549032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov return; 550032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 551032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov mDialUri = intent.getData(); 552032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 553032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 554032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov @Override 555242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn public void onBackPressed() { 556b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa if (mInSearchUi) { 557b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // We should let the user go back to usual screens with tabs. 558b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa exitSearchUi(); 559b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else if (isTaskRoot()) { 560032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // Instead of stopping, simply push this to the back of the stack. 561032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // This is only done when running at the top of the stack; 562032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // otherwise, we have been launched by someone else so need to 563032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov // allow the user to go back to the caller. 564032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov moveTaskToBack(false); 565242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn } else { 566242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn super.onBackPressed(); 567032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 568032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov } 569032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov 57043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private DialpadFragment.Listener mDialpadListener = new DialpadFragment.Listener() { 571c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann @Override 57243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa public void onSearchButtonPressed() { 57343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa enterSearchUi(); 574c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 57543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa }; 576c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann 57732f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro private StrequentContactListFragment.Listener mStrequentListener = 57832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro new StrequentContactListFragment.Listener() { 57932f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 58032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public void onContactSelected(Uri contactUri) { 581b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa PhoneNumberInteraction.startInteractionForPhoneCall( 582b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa DialtactsActivity.this, contactUri); 58332f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro } 58432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro }; 58532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro 586c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann @Override 587c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann public boolean onCreateOptionsMenu(Menu menu) { 588c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann MenuInflater inflater = getMenuInflater(); 589aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa inflater.inflate(R.menu.dialtacts_options, menu); 590c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann return true; 591c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 592c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann 593c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann @Override 594aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa public boolean onPrepareOptionsMenu(Menu menu) { 595aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa final MenuItem searchMenuItem = menu.findItem(R.id.search_on_action_bar); 596aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa if (mInSearchUi || getActionBar().getSelectedTab().getPosition() == TAB_INDEX_DIALER) { 597aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa searchMenuItem.setVisible(false); 598aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } else { 599aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa searchMenuItem.setVisible(true); 600aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa searchMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { 601aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa @Override 602aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa public boolean onMenuItemClick(MenuItem item) { 603aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa enterSearchUi(); 604aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return true; 605aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 606c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann }); 607c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 608aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 609aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return true; 610c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann } 611b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 612b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa @Override 613b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa public void startSearch(String initialQuery, boolean selectInitialQuery, 614b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa Bundle appSearchData, boolean globalSearch) { 61543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (mSearchFragment != null && mSearchFragment.isAdded() && !globalSearch) { 616b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa enterSearchUi(); 617b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else { 618b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch); 619b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 620b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 621b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 622b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 623b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Hides every tab and shows search UI for phone lookup. 624b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 625b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private void enterSearchUi() { 626b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final ActionBar actionBar = getActionBar(); 627b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 628b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final Tab tab = actionBar.getSelectedTab(); 629c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa 630c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa // User can search during the call, but we don't want to remember the status. 631c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa if (tab != null && !DialpadFragment.phoneIsInUse()) { 632aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa mLastManuallySelectedFragment = tab.getPosition(); 633b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 634b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 635b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // Instantiate or reset SearchView in ActionBar. 636b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa if (mSearchView == null) { 637b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // TODO: layout is not what we want. Need "up" button instead of "close" button, etc. 638b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final View searchViewLayout = 639b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa getLayoutInflater().inflate(R.layout.custom_action_bar, null); 640b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView = (SearchView) searchViewLayout.findViewById(R.id.search_view); 641b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setQueryHint(getString(R.string.hint_findContacts)); 642b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener); 643b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setOnCloseListener(mPhoneSearchCloseListener); 644b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.requestFocus(); 64536c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa // Show soft keyboard when SearchView has a focus. Need to delay the request in order 64636c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa // to let InputMethodManager handle it correctly. 647c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani mSearchView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { 648c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani @Override 649c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani public void onViewDetachedFromWindow(View v) { 650c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 651c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani 652c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani @Override 653c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani public void onViewAttachedToWindow(View v) { 654c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani if (mSearchView.hasFocus()) { 655c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani mSearchView.postDelayed(new Runnable() { 656c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani public void run() { 657c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani showInputMethod(mSearchView.findFocus()); 658c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 659c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani }, 0); 660c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 661c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 662c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani }); 663b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setCustomView(searchViewLayout, 664b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 665b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } else { 666b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mSearchView.setQuery(null, true); 667b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 668b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 669b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setDisplayShowCustomEnabled(true); 670b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 67188f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa actionBar.setDisplayShowHomeEnabled(true); 67288f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa actionBar.setDisplayHomeAsUpEnabled(true); 673b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 67443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(mViewPager.getCurrentItem(), false); 67543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 676b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // Show the search fragment and hide everything else. 677b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 678aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa transaction.show(mSearchFragment); 679b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa transaction.commit(); 680438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa mViewPager.setVisibility(View.GONE); 681b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 682b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mInSearchUi = true; 683b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 684b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 685c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani private void showInputMethod(View view) { 686c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 687c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani if (imm != null) { 688c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani imm.showSoftInput(view, 0); 689c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 690c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani } 691c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani 69288f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa private void hideInputMethod(View view) { 69388f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 69488f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa if (imm != null) { 69588f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 69688f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa } 69788f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa } 69888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa 699b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa /** 700b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment 701b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa * should be automatically focused again. 702b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa */ 703b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa private void exitSearchUi() { 704b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa final ActionBar actionBar = getActionBar(); 705b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 706b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa // We want to hide SearchView and show Tabs. Also focus on previously selected one. 707b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setDisplayShowCustomEnabled(false); 70888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa actionBar.setDisplayShowHomeEnabled(false); 709b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 710b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa 71143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa sendFragmentVisibilityChange(mViewPager.getCurrentItem(), true); 71243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 713438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 714aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa transaction.hide(mSearchFragment); 715438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa transaction.commit(); 716438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 717438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa mViewPager.setVisibility(View.VISIBLE); 718438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa 71988f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa hideInputMethod(getCurrentFocus()); 72088f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa 721350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa // Request to update option menu. 722350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa invalidateOptionsMenu(); 723350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa 724b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa mInSearchUi = false; 725b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa } 726aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa 727aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa private Fragment getFragmentAt(int position) { 728aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa switch (position) { 729aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa case TAB_INDEX_DIALER: 730aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return mDialpadFragment; 731aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa case TAB_INDEX_CALL_LOG: 732aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return mCallLogFragment; 733aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa case TAB_INDEX_FAVORITES: 734aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa return mStrequentFragment; 735aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa default: 736aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa throw new IllegalStateException("Unknown fragment index: " + position); 737aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 738aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa } 73943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa 74043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa private void sendFragmentVisibilityChange(int position, boolean visibility) { 74143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa final Fragment fragment = getFragmentAt(position); 74243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa if (fragment instanceof ViewPagerVisibilityListener) { 74343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa ((ViewPagerVisibilityListener) fragment).onVisibilityChanged(visibility); 74443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 74543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa } 746bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa 747bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa /** Returns an Intent to launch Call Settings screen */ 748bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa public static Intent getCallSettingsIntent() { 749bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa final Intent intent = new Intent(Intent.ACTION_MAIN); 750bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa intent.setClassName(PHONE_PACKAGE, CALL_SETTINGS_CLASS_NAME); 751bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa return intent; 752bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa } 753032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov} 754