DialtactsActivity.java revision 9add0e5ef2a267acbe104e04f4cf6ab24cb8ba3e
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.contacts.activities; 18 19import com.android.contacts.R; 20import com.android.contacts.activities.ContactsFrontDoor; 21import com.android.contacts.activities.ContactBrowserActivity; 22import com.android.contacts.activities.DialpadActivity; 23import com.android.internal.telephony.ITelephony; 24 25import android.app.Activity; 26import android.app.TabActivity; 27import android.content.Intent; 28import android.content.SharedPreferences; 29import android.net.Uri; 30import android.os.Bundle; 31import android.os.RemoteException; 32import android.os.ServiceManager; 33import android.provider.CallLog.Calls; 34import android.provider.ContactsContract.Intents.UI; 35import android.util.Log; 36import android.view.Window; 37import android.widget.TabHost; 38 39/** 40 * The dialer activity that has one tab with the virtual 12key 41 * dialer, a tab with recent calls in it, a tab with the contacts and 42 * a tab with the favorite. This is the container and the tabs are 43 * embedded using intents. 44 * The dialer tab's title is 'phone', a more common name (see strings.xml). 45 */ 46public class DialtactsActivity extends TabActivity implements TabHost.OnTabChangeListener { 47 private static final String TAG = "DialtactsActivity"; 48 49 private static final int TAB_INDEX_DIALER = 0; 50 private static final int TAB_INDEX_CALL_LOG = 1; 51 private static final int TAB_INDEX_CONTACTS = 2; 52 private static final int TAB_INDEX_FAVORITES = 3; 53 54 static final String EXTRA_IGNORE_STATE = "ignore-state"; 55 56 /** Name of the dialtacts shared preferences */ 57 static final String PREFS_DIALTACTS = "dialtacts"; 58 /** If true, when handling the contacts intent the favorites tab will be shown instead */ 59 static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts"; 60 static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false; 61 62 /** Last manually selected tab index */ 63 private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab"; 64 private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER; 65 66 private TabHost mTabHost; 67 private String mFilterText; 68 private Uri mDialUri; 69 70 /** 71 * The index of the tab that has last been manually selected (the user clicked on a tab). 72 * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call) 73 */ 74 private int mLastManuallySelectedTab; 75 76 @Override 77 protected void onCreate(Bundle icicle) { 78 super.onCreate(icicle); 79 80 final Intent intent = getIntent(); 81 fixIntent(intent); 82 83 requestWindowFeature(Window.FEATURE_NO_TITLE); 84 setContentView(R.layout.dialtacts_activity); 85 86 mTabHost = getTabHost(); 87 mTabHost.setOnTabChangedListener(this); 88 89 // Setup the tabs 90 setupDialerTab(); 91 setupCallLogTab(); 92 setupContactsTab(); 93 setupFavoritesTab(); 94 setupGroupsTab(); 95 96 // Load the last manually loaded tab 97 final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE); 98 mLastManuallySelectedTab = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB, 99 PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT); 100 101 setCurrentTab(intent); 102 103 if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction()) 104 && icicle == null) { 105 setupFilterText(intent); 106 } 107 } 108 109 @Override 110 protected void onPause() { 111 super.onPause(); 112 113 final int currentTabIndex = mTabHost.getCurrentTab(); 114 final SharedPreferences.Editor editor = 115 getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit(); 116 if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) { 117 editor.putBoolean(PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES); 118 } 119 editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedTab); 120 121 editor.apply(); 122 } 123 124 private void fixIntent(Intent intent) { 125 // This should be cleaned up: the call key used to send an Intent 126 // that just said to go to the recent calls list. It now sends this 127 // abstract action, but this class hasn't been rewritten to deal with it. 128 if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) { 129 intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE); 130 intent.putExtra("call_key", true); 131 setIntent(intent); 132 } 133 } 134 135 private void setupCallLogTab() { 136 // Force the class since overriding tab entries doesn't work 137 Intent intent = new Intent("com.android.phone.action.RECENT_CALLS"); 138 intent.setClass(this, CallLogActivity.class); 139 140 mTabHost.addTab(mTabHost.newTabSpec("call_log") 141 .setIndicator(getString(R.string.recentCallsIconLabel), 142 getResources().getDrawable(R.drawable.ic_tab_recent)) 143 .setContent(intent)); 144 } 145 146 private void setupDialerTab() { 147 Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER"); 148 intent.setClass(this, DialpadActivity.class); 149 150 mTabHost.addTab(mTabHost.newTabSpec("dialer") 151 .setIndicator(getString(R.string.dialerIconLabel), 152 getResources().getDrawable(R.drawable.ic_tab_dialer)) 153 .setContent(intent)); 154 } 155 156 private void setupContactsTab() { 157 Intent intent = new Intent(UI.LIST_ALL_CONTACTS_ACTION); 158 intent.setClass(this, ContactBrowserActivity.class); 159 160 mTabHost.addTab(mTabHost.newTabSpec("contacts") 161 .setIndicator(getText(R.string.contactsIconLabel), 162 getResources().getDrawable(R.drawable.ic_tab_contacts)) 163 .setContent(intent)); 164 } 165 166 private void setupFavoritesTab() { 167 Intent intent = new Intent(UI.LIST_STREQUENT_ACTION); 168 intent.setClass(this, ContactBrowserActivity.class); 169 170 mTabHost.addTab(mTabHost.newTabSpec("favorites") 171 .setIndicator(getString(R.string.contactsFavoritesLabel), 172 getResources().getDrawable(R.drawable.ic_tab_starred)) 173 .setContent(intent)); 174 } 175 176 private void setupGroupsTab() { 177 // This is a temporary intent action until the refactoring for the phone/contacts 178 // split is complete. 179 Intent intent = new Intent("com.android.phone.action.GROUPS_LIST"); 180 intent.setClass(this, GroupBrowserActivity.class); 181 182 mTabHost.addTab(mTabHost.newTabSpec("groups") 183 .setIndicator(getString(R.string.contactsGroupsLabel), 184 getResources().getDrawable(R.drawable.ic_menu_display_all_holo_light)) 185 .setContent(intent)); 186 } 187 188 /** 189 * Returns true if the intent is due to hitting the green send key while in a call. 190 * 191 * @param intent the intent that launched this activity 192 * @param recentCallsRequest true if the intent is requesting to view recent calls 193 * @return true if the intent is due to hitting the green send key while in a call 194 */ 195 private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) { 196 // If there is a call in progress go to the call screen 197 if (recentCallsRequest) { 198 final boolean callKey = intent.getBooleanExtra("call_key", false); 199 200 try { 201 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 202 if (callKey && phone != null && phone.showCallScreen()) { 203 return true; 204 } 205 } catch (RemoteException e) { 206 Log.e(TAG, "Failed to handle send while in call", e); 207 } 208 } 209 210 return false; 211 } 212 213 /** 214 * Sets the current tab based on the intent's request type 215 * 216 * @param intent Intent that contains information about which tab should be selected 217 */ 218 private void setCurrentTab(Intent intent) { 219 // If we got here by hitting send and we're in call forward along to the in-call activity 220 final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType()); 221 if (isSendKeyWhileInCall(intent, recentCallsRequest)) { 222 finish(); 223 return; 224 } 225 226 // Dismiss menu provided by any children activities 227 Activity activity = getLocalActivityManager(). 228 getActivity(mTabHost.getCurrentTabTag()); 229 if (activity != null) { 230 activity.closeOptionsMenu(); 231 } 232 233 // Tell the children activities that they should ignore any possible saved 234 // state and instead reload their state from the parent's intent 235 intent.putExtra(EXTRA_IGNORE_STATE, true); 236 237 // Remember the old manually selected tab index so that it can be restored if it is 238 // overwritten by one of the programmatic tab selections 239 final int savedTabIndex = mLastManuallySelectedTab; 240 241 // Choose the tab based on the inbound intent 242 if (intent.getBooleanExtra(ContactsFrontDoor.EXTRA_FRONT_DOOR, false)) { 243 // Launched through the contacts front door, set the proper contacts tab (sticky 244 // between favorites and contacts) 245 SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE); 246 boolean favoritesAsContacts = prefs.getBoolean(PREF_FAVORITES_AS_CONTACTS, 247 PREF_FAVORITES_AS_CONTACTS_DEFAULT); 248 if (favoritesAsContacts) { 249 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES); 250 } else { 251 mTabHost.setCurrentTab(TAB_INDEX_CONTACTS); 252 } 253 } else { 254 // Not launched through the front door, look at the component to determine the tab 255 String componentName = intent.getComponent().getClassName(); 256 if (getClass().getName().equals(componentName)) { 257 if (recentCallsRequest) { 258 mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG); 259 } else { 260 mTabHost.setCurrentTab(TAB_INDEX_DIALER); 261 } 262 } else { 263 mTabHost.setCurrentTab(mLastManuallySelectedTab); 264 } 265 } 266 267 // Restore to the previous manual selection 268 mLastManuallySelectedTab = savedTabIndex; 269 270 // Tell the children activities that they should honor their saved states 271 // instead of the state from the parent's intent 272 intent.putExtra(EXTRA_IGNORE_STATE, false); 273 } 274 275 @Override 276 public void onNewIntent(Intent newIntent) { 277 setIntent(newIntent); 278 fixIntent(newIntent); 279 setCurrentTab(newIntent); 280 final String action = newIntent.getAction(); 281 if (UI.FILTER_CONTACTS_ACTION.equals(action)) { 282 setupFilterText(newIntent); 283 } else if (isDialIntent(newIntent)) { 284 setupDialUri(newIntent); 285 } 286 } 287 288 /** Returns true if the given intent contains a phone number to populate the dialer with */ 289 private boolean isDialIntent(Intent intent) { 290 final String action = intent.getAction(); 291 if (Intent.ACTION_DIAL.equals(action)) { 292 return true; 293 } 294 if (Intent.ACTION_VIEW.equals(action)) { 295 final Uri data = intent.getData(); 296 if (data != null && "tel".equals(data.getScheme())) { 297 return true; 298 } 299 } 300 return false; 301 } 302 303 /** 304 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}. 305 * This text originally came from a FILTER_CONTACTS_ACTION intent received 306 * by this activity. The stored text will then be cleared after after this 307 * method returns. 308 * 309 * @return The stored filter text 310 */ 311 public String getAndClearFilterText() { 312 String filterText = mFilterText; 313 mFilterText = null; 314 return filterText; 315 } 316 317 /** 318 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent. 319 * This is so child activities can check if they are supposed to display a filter. 320 * 321 * @param intent The intent received in {@link #onNewIntent(Intent)} 322 */ 323 private void setupFilterText(Intent intent) { 324 // If the intent was relaunched from history, don't apply the filter text. 325 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 326 return; 327 } 328 String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY); 329 if (filter != null && filter.length() > 0) { 330 mFilterText = filter; 331 } 332 } 333 334 /** 335 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri 336 * originally came from a dial intent received by this activity. The stored 337 * uri will then be cleared after after this method returns. 338 * 339 * @return The stored uri 340 */ 341 public Uri getAndClearDialUri() { 342 Uri dialUri = mDialUri; 343 mDialUri = null; 344 return dialUri; 345 } 346 347 /** 348 * Stores the uri associated with a dial intent. This is so child activities can 349 * check if they are supposed to display new dial info. 350 * 351 * @param intent The intent received in {@link #onNewIntent(Intent)} 352 */ 353 private void setupDialUri(Intent intent) { 354 // If the intent was relaunched from history, don't reapply the intent. 355 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 356 return; 357 } 358 mDialUri = intent.getData(); 359 } 360 361 @Override 362 public void onBackPressed() { 363 if (isTaskRoot()) { 364 // Instead of stopping, simply push this to the back of the stack. 365 // This is only done when running at the top of the stack; 366 // otherwise, we have been launched by someone else so need to 367 // allow the user to go back to the caller. 368 moveTaskToBack(false); 369 } else { 370 super.onBackPressed(); 371 } 372 } 373 374 /** {@inheritDoc} */ 375 public void onTabChanged(String tabId) { 376 // Because we're using Activities as our tab children, we trigger 377 // onWindowFocusChanged() to let them know when they're active. This may 378 // seem to duplicate the purpose of onResume(), but it's needed because 379 // onResume() can't reliably check if a keyguard is active. 380 Activity activity = getLocalActivityManager().getActivity(tabId); 381 if (activity != null) { 382 activity.onWindowFocusChanged(true); 383 } 384 385 // Remember this tab index. This function is also called, if the tab is set automatically 386 // in which case the setter (setCurrentTab) has to set this to its old value afterwards 387 mLastManuallySelectedTab = mTabHost.getCurrentTab(); 388 } 389} 390