DialtactsActivity.java revision 903137768d56ca85d026c2f4b92e4ace6e068d3b
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; 18 19import android.app.Activity; 20import android.app.TabActivity; 21import android.content.Intent; 22import android.content.SharedPreferences; 23import android.graphics.drawable.Drawable; 24import android.net.Uri; 25import android.os.Bundle; 26import android.os.RemoteException; 27import android.os.ServiceManager; 28import android.provider.CallLog; 29import android.provider.Contacts; 30import android.provider.CallLog.Calls; 31import android.provider.Contacts.Intents.UI; 32import android.util.Log; 33import android.view.KeyEvent; 34import android.view.Window; 35import android.widget.TabHost; 36import com.android.internal.telephony.ITelephony; 37 38/** 39 * The dialer activity that has one tab with the virtual 12key dialer, 40 * and another tab with recent calls in it. This is the container and the tabs 41 * are embedded using intents. 42 */ 43public class DialtactsActivity extends TabActivity implements TabHost.OnTabChangeListener { 44 private static final String TAG = "Dailtacts"; 45 private static final String FAVORITES_ENTRY_COMPONENT = 46 "com.android.contacts.DialtactsFavoritesEntryActivity"; 47 48 private static final int TAB_INDEX_DIALER = 0; 49 private static final int TAB_INDEX_CALL_LOG = 1; 50 private static final int TAB_INDEX_CONTACTS = 2; 51 private static final int TAB_INDEX_FAVORITES = 3; 52 53 static final String EXTRA_IGNORE_STATE = "ignore-state"; 54 55 /** Name of the dialtacts shared preferences */ 56 static final String PREFS_DIALTACTS = "dialtacts"; 57 /** If true, when handling the contacts intent the favorites tab will be shown instead */ 58 static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts"; 59 static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false; 60 61 private TabHost mTabHost; 62 private String mFilterText; 63 private Uri mDialUri; 64 65 @Override 66 protected void onCreate(Bundle icicle) { 67 super.onCreate(icicle); 68 69 final Intent intent = getIntent(); 70 fixIntent(intent); 71 72 requestWindowFeature(Window.FEATURE_NO_TITLE); 73 setContentView(R.layout.dialer_activity); 74 75 mTabHost = getTabHost(); 76 mTabHost.setOnTabChangedListener(this); 77 78 // Setup the tabs 79 setupDialerTab(); 80 setupCallLogTab(); 81 setupContactsTab(); 82 setupFavoritesTab(); 83 84 setCurrentTab(intent); 85 86 if (intent.getAction().equals(Contacts.Intents.UI.FILTER_CONTACTS_ACTION) 87 && icicle == null) { 88 setupFilterText(intent); 89 } 90 } 91 92 @Override 93 protected void onPause() { 94 super.onPause(); 95 96 int currentTabIndex = mTabHost.getCurrentTab(); 97 if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) { 98 SharedPreferences.Editor editor = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE) 99 .edit(); 100 editor.putBoolean(PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES); 101 editor.commit(); 102 } 103 } 104 105 private void fixIntent(Intent intent) { 106 // This should be cleaned up: the call key used to send an Intent 107 // that just said to go to the recent calls list. It now sends this 108 // abstract action, but this class hasn't been rewritten to deal with it. 109 if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) { 110 intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE); 111 intent.putExtra("call_key", true); 112 setIntent(intent); 113 } 114 } 115 116 private void setupCallLogTab() { 117 // Force the class since overriding tab entries doesn't work 118 Intent intent = new Intent("com.android.phone.action.RECENT_CALLS"); 119 intent.setClass(this, RecentCallsListActivity.class); 120 121 mTabHost.addTab(mTabHost.newTabSpec("call_log") 122 .setIndicator(getString(R.string.recentCallsIconLabel), 123 getResources().getDrawable(R.drawable.ic_tab_recent)) 124 .setContent(intent)); 125 } 126 127 private void setupDialerTab() { 128 Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER"); 129 intent.setClass(this, TwelveKeyDialer.class); 130 131 mTabHost.addTab(mTabHost.newTabSpec("dialer") 132 .setIndicator(getString(R.string.dialerIconLabel), 133 getResources().getDrawable(R.drawable.ic_tab_dialer)) 134 .setContent(intent)); 135 } 136 137 private void setupContactsTab() { 138 Intent intent = new Intent(UI.LIST_DEFAULT); 139 intent.setClass(this, ContactsListActivity.class); 140 141 mTabHost.addTab(mTabHost.newTabSpec("contacts") 142 .setIndicator(getText(R.string.contactsIconLabel), 143 getResources().getDrawable(R.drawable.ic_tab_contacts)) 144 .setContent(intent)); 145 } 146 147 private void setupFavoritesTab() { 148 Intent intent = new Intent(UI.LIST_STREQUENT_ACTION); 149 intent.setClass(this, ContactsListActivity.class); 150 151 mTabHost.addTab(mTabHost.newTabSpec("favorites") 152 .setIndicator(getString(R.string.contactsFavoritesLabel), 153 getResources().getDrawable(R.drawable.ic_tab_starred)) 154 .setContent(intent)); 155 } 156 157 /** 158 * Returns true if the intent is due to hitting the green send key while in a call. 159 * 160 * @param intent the intent that launched this activity 161 * @param recentCallsRequest true if the intent is requesting to view recent calls 162 * @return true if the intent is due to hitting the green send key while in a call 163 */ 164 private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) { 165 // If there is a call in progress go to the call screen 166 if (recentCallsRequest) { 167 final boolean callKey = intent.getBooleanExtra("call_key", false); 168 169 try { 170 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 171 if (callKey && phone != null && phone.showCallScreen()) { 172 return true; 173 } 174 } catch (RemoteException e) { 175 Log.e(TAG, "Failed to handle send while in call", e); 176 } 177 } 178 179 return false; 180 } 181 182 /** 183 * Sets the current tab based on the intent's request type 184 * 185 * @param recentCallsRequest true is the recent calls tab is desired, false otherwise 186 */ 187 private void setCurrentTab(Intent intent) { 188 // If we got here by hitting send and we're in call forward along to the in-call activity 189 final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType()); 190 if (isSendKeyWhileInCall(intent, recentCallsRequest)) { 191 finish(); 192 return; 193 } 194 195 // Dismiss menu provided by any children activities 196 Activity activity = getLocalActivityManager(). 197 getActivity(mTabHost.getCurrentTabTag()); 198 if (activity != null) { 199 activity.closeOptionsMenu(); 200 } 201 202 // Tell the children activities that they should ignore any possible saved 203 // state and instead reload their state from the parent's intent 204 intent.putExtra(EXTRA_IGNORE_STATE, true); 205 206 // Choose the tab based on the inbound intent 207 String componentName = intent.getComponent().getClassName(); 208 if (getClass().getName().equals(componentName)) { 209 if (recentCallsRequest) { 210 mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG); 211 } else { 212 mTabHost.setCurrentTab(TAB_INDEX_DIALER); 213 } 214 } else if (FAVORITES_ENTRY_COMPONENT.equals(componentName)) { 215 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES); 216 } else { 217 SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE); 218 boolean favoritesAsContacts = prefs.getBoolean(PREF_FAVORITES_AS_CONTACTS, 219 PREF_FAVORITES_AS_CONTACTS_DEFAULT); 220 if (favoritesAsContacts) { 221 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES); 222 } else { 223 mTabHost.setCurrentTab(TAB_INDEX_CONTACTS); 224 } 225 } 226 227 // Tell the children activities that they should honor their saved states 228 // instead of the state from the parent's intent 229 intent.putExtra(EXTRA_IGNORE_STATE, false); 230 } 231 232 @Override 233 public void onNewIntent(Intent newIntent) { 234 setIntent(newIntent); 235 fixIntent(newIntent); 236 setCurrentTab(newIntent); 237 final String action = newIntent.getAction(); 238 if (action.equals(Contacts.Intents.UI.FILTER_CONTACTS_ACTION)) { 239 setupFilterText(newIntent); 240 } else if (isDialIntent(newIntent)) { 241 setupDialUri(newIntent); 242 } 243 } 244 245 /** Returns true if the given intent contains a phone number to populate the dialer with */ 246 private boolean isDialIntent(Intent intent) { 247 final String action = intent.getAction(); 248 if (Intent.ACTION_DIAL.equals(action)) { 249 return true; 250 } 251 if (Intent.ACTION_VIEW.equals(action)) { 252 final Uri data = intent.getData(); 253 if (data != null && "tel".equals(data.getScheme())) { 254 return true; 255 } 256 } 257 return false; 258 } 259 260 /** 261 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}. 262 * This text originally came from a FILTER_CONTACTS_ACTION intent received 263 * by this activity. The stored text will then be cleared after after this 264 * method returns. 265 * 266 * @return The stored filter text 267 */ 268 public String getAndClearFilterText() { 269 String filterText = mFilterText; 270 mFilterText = null; 271 return filterText; 272 } 273 274 /** 275 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent. 276 * This is so child activities can check if they are supposed to display a filter. 277 * 278 * @param intent The intent received in {@link #onNewIntent(Intent)} 279 */ 280 private void setupFilterText(Intent intent) { 281 // If the intent was relaunched from history, don't apply the filter text. 282 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 283 return; 284 } 285 String filter = intent.getStringExtra(Contacts.Intents.UI.FILTER_TEXT_EXTRA_KEY); 286 if (filter != null && filter.length() > 0) { 287 mFilterText = filter; 288 } 289 } 290 291 /** 292 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri 293 * originally came from a dial intent received by this activity. The stored 294 * uri will then be cleared after after this method returns. 295 * 296 * @return The stored uri 297 */ 298 public Uri getAndClearDialUri() { 299 Uri dialUri = mDialUri; 300 mDialUri = null; 301 return dialUri; 302 } 303 304 /** 305 * Stores the uri associated with a dial intent. This is so child activities can 306 * check if they are supposed to display new dial info. 307 * 308 * @param intent The intent received in {@link #onNewIntent(Intent)} 309 */ 310 private void setupDialUri(Intent intent) { 311 // If the intent was relaunched from history, don't reapply the intent. 312 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 313 return; 314 } 315 mDialUri = intent.getData(); 316 } 317 318 @Override 319 public boolean onKeyDown(int keyCode, KeyEvent event) { 320 // Handle BACK 321 if (keyCode == KeyEvent.KEYCODE_BACK && isTaskRoot()) { 322 // Instead of stopping, simply push this to the back of the stack. 323 // This is only done when running at the top of the stack; 324 // otherwise, we have been launched by someone else so need to 325 // allow the user to go back to the caller. 326 moveTaskToBack(false); 327 return true; 328 } 329 330 return super.onKeyDown(keyCode, event); 331 } 332 333 /** {@inheritDoc} */ 334 public void onTabChanged(String tabId) { 335 // Because we're using Activities as our tab children, we trigger 336 // onWindowFocusChanged() to let them know when they're active. This may 337 // seem to duplicate the purpose of onResume(), but it's needed because 338 // onResume() can't reliably check if a keyguard is active. 339 Activity activity = getLocalActivityManager().getActivity(tabId); 340 if (activity != null) { 341 activity.onWindowFocusChanged(true); 342 } 343 } 344} 345