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