blob: afb86069015a499f70c7f62abefac276c42c10b2 [file] [log] [blame]
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001/*
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
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -050019import com.android.internal.telephony.ITelephony;
20
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080021import android.app.Activity;
22import android.app.TabActivity;
23import android.content.Intent;
Jeff Hamilton90313772009-07-28 10:20:31 -050024import android.content.SharedPreferences;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080025import android.net.Uri;
26import android.os.Bundle;
27import android.os.RemoteException;
28import android.os.ServiceManager;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080029import android.provider.CallLog.Calls;
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -050030import android.provider.ContactsContract.Intents.UI;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080031import android.util.Log;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080032import android.view.Window;
33import android.widget.TabHost;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080034
35/**
Nicolas Catania08832402009-09-24 09:52:50 -070036 * 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).
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080041 */
Jeff Hamilton90313772009-07-28 10:20:31 -050042public 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";
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080046
Daniel Lehmann7675e122010-04-21 17:31:11 -070047 /** Opens the Contacts app in the state the user has last set it to */
48 private static final String CONTACTS_LAUNCH_ACTIVITY =
49 "com.android.contacts.ContactsLaunchActivity";
50
The Android Open Source Project1f620962009-03-09 11:52:14 -070051 private static final int TAB_INDEX_DIALER = 0;
52 private static final int TAB_INDEX_CALL_LOG = 1;
Jeff Hamilton90313772009-07-28 10:20:31 -050053 private static final int TAB_INDEX_CONTACTS = 2;
54 private static final int TAB_INDEX_FAVORITES = 3;
Nicolas Catania08832402009-09-24 09:52:50 -070055
The Android Open Source Project1f620962009-03-09 11:52:14 -070056 static final String EXTRA_IGNORE_STATE = "ignore-state";
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080057
Jeff Hamilton90313772009-07-28 10:20:31 -050058 /** Name of the dialtacts shared preferences */
59 static final String PREFS_DIALTACTS = "dialtacts";
60 /** If true, when handling the contacts intent the favorites tab will be shown instead */
61 static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts";
62 static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
63
Daniel Lehmann7675e122010-04-21 17:31:11 -070064 /** Last manually selected tab index */
65 private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
66 private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
67
The Android Open Source Project1f620962009-03-09 11:52:14 -070068 private TabHost mTabHost;
Nicolas Catania08832402009-09-24 09:52:50 -070069 private String mFilterText;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080070 private Uri mDialUri;
71
Daniel Lehmann7675e122010-04-21 17:31:11 -070072 /**
73 * The index of the tab that has last been manually selected (the user clicked on a tab).
74 * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call)
75 */
76 private int mLastManuallySelectedTab;
77
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080078 @Override
79 protected void onCreate(Bundle icicle) {
80 super.onCreate(icicle);
81
82 final Intent intent = getIntent();
83 fixIntent(intent);
Nicolas Catania08832402009-09-24 09:52:50 -070084
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080085 requestWindowFeature(Window.FEATURE_NO_TITLE);
86 setContentView(R.layout.dialer_activity);
87
88 mTabHost = getTabHost();
89 mTabHost.setOnTabChangedListener(this);
90
91 // Setup the tabs
92 setupDialerTab();
93 setupCallLogTab();
Jeff Hamilton90313772009-07-28 10:20:31 -050094 setupContactsTab();
95 setupFavoritesTab();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080096
Daniel Lehmann7675e122010-04-21 17:31:11 -070097 // Load the last manually loaded tab
98 final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
99 mLastManuallySelectedTab = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
100 PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);
101
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800102 setCurrentTab(intent);
Jeff Hamilton90313772009-07-28 10:20:31 -0500103
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -0500104 if (intent.getAction().equals(UI.FILTER_CONTACTS_ACTION)
Jeff Hamilton90313772009-07-28 10:20:31 -0500105 && icicle == null) {
106 setupFilterText(intent);
107 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800108 }
109
Jeff Hamilton90313772009-07-28 10:20:31 -0500110 @Override
111 protected void onPause() {
112 super.onPause();
Nicolas Catania08832402009-09-24 09:52:50 -0700113
Daniel Lehmann7675e122010-04-21 17:31:11 -0700114 final int currentTabIndex = mTabHost.getCurrentTab();
115 final SharedPreferences.Editor editor =
116 getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
Jeff Hamilton90313772009-07-28 10:20:31 -0500117 if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) {
Jeff Hamilton90313772009-07-28 10:20:31 -0500118 editor.putBoolean(PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES);
Jeff Hamilton90313772009-07-28 10:20:31 -0500119 }
Daniel Lehmann7675e122010-04-21 17:31:11 -0700120 editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedTab);
121
122 editor.commit();
Jeff Hamilton90313772009-07-28 10:20:31 -0500123 }
Nicolas Catania08832402009-09-24 09:52:50 -0700124
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800125 private void fixIntent(Intent intent) {
126 // This should be cleaned up: the call key used to send an Intent
127 // that just said to go to the recent calls list. It now sends this
128 // abstract action, but this class hasn't been rewritten to deal with it.
129 if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) {
130 intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
131 intent.putExtra("call_key", true);
132 setIntent(intent);
133 }
134 }
Nicolas Catania08832402009-09-24 09:52:50 -0700135
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800136 private void setupCallLogTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700137 // Force the class since overriding tab entries doesn't work
138 Intent intent = new Intent("com.android.phone.action.RECENT_CALLS");
139 intent.setClass(this, RecentCallsListActivity.class);
140
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800141 mTabHost.addTab(mTabHost.newTabSpec("call_log")
142 .setIndicator(getString(R.string.recentCallsIconLabel),
143 getResources().getDrawable(R.drawable.ic_tab_recent))
The Android Open Source Project1f620962009-03-09 11:52:14 -0700144 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800145 }
146
147 private void setupDialerTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700148 Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER");
149 intent.setClass(this, TwelveKeyDialer.class);
150
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800151 mTabHost.addTab(mTabHost.newTabSpec("dialer")
152 .setIndicator(getString(R.string.dialerIconLabel),
153 getResources().getDrawable(R.drawable.ic_tab_dialer))
The Android Open Source Project1f620962009-03-09 11:52:14 -0700154 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800155 }
156
Jeff Hamilton90313772009-07-28 10:20:31 -0500157 private void setupContactsTab() {
158 Intent intent = new Intent(UI.LIST_DEFAULT);
159 intent.setClass(this, ContactsListActivity.class);
160
161 mTabHost.addTab(mTabHost.newTabSpec("contacts")
162 .setIndicator(getText(R.string.contactsIconLabel),
163 getResources().getDrawable(R.drawable.ic_tab_contacts))
164 .setContent(intent));
165 }
166
167 private void setupFavoritesTab() {
168 Intent intent = new Intent(UI.LIST_STREQUENT_ACTION);
169 intent.setClass(this, ContactsListActivity.class);
170
171 mTabHost.addTab(mTabHost.newTabSpec("favorites")
172 .setIndicator(getString(R.string.contactsFavoritesLabel),
173 getResources().getDrawable(R.drawable.ic_tab_starred))
174 .setContent(intent));
175 }
176
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800177 /**
178 * Returns true if the intent is due to hitting the green send key while in a call.
Nicolas Catania08832402009-09-24 09:52:50 -0700179 *
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800180 * @param intent the intent that launched this activity
181 * @param recentCallsRequest true if the intent is requesting to view recent calls
Nicolas Catania08832402009-09-24 09:52:50 -0700182 * @return true if the intent is due to hitting the green send key while in a call
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800183 */
184 private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) {
185 // If there is a call in progress go to the call screen
186 if (recentCallsRequest) {
187 final boolean callKey = intent.getBooleanExtra("call_key", false);
188
189 try {
190 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
191 if (callKey && phone != null && phone.showCallScreen()) {
192 return true;
193 }
194 } catch (RemoteException e) {
195 Log.e(TAG, "Failed to handle send while in call", e);
196 }
197 }
198
199 return false;
200 }
201
202 /**
203 * Sets the current tab based on the intent's request type
Nicolas Catania08832402009-09-24 09:52:50 -0700204 *
Daniel Lehmann7675e122010-04-21 17:31:11 -0700205 * @param intent Intent that contains information about which tab should be selected
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800206 */
207 private void setCurrentTab(Intent intent) {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700208 // If we got here by hitting send and we're in call forward along to the in-call activity
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800209 final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
210 if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
211 finish();
212 return;
213 }
Nicolas Catania08832402009-09-24 09:52:50 -0700214
The Android Open Source Project1f620962009-03-09 11:52:14 -0700215 // Dismiss menu provided by any children activities
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800216 Activity activity = getLocalActivityManager().
217 getActivity(mTabHost.getCurrentTabTag());
218 if (activity != null) {
219 activity.closeOptionsMenu();
220 }
221
The Android Open Source Project1f620962009-03-09 11:52:14 -0700222 // Tell the children activities that they should ignore any possible saved
223 // state and instead reload their state from the parent's intent
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800224 intent.putExtra(EXTRA_IGNORE_STATE, true);
The Android Open Source Project1f620962009-03-09 11:52:14 -0700225
Daniel Lehmann7675e122010-04-21 17:31:11 -0700226 // Remember the old manually selected tab index so that it can be restored if it is
227 // overwritten by one of the programmatic tab selections
228 final int savedTabIndex = mLastManuallySelectedTab;
229
The Android Open Source Project1f620962009-03-09 11:52:14 -0700230 // Choose the tab based on the inbound intent
231 String componentName = intent.getComponent().getClassName();
232 if (getClass().getName().equals(componentName)) {
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800233 if (recentCallsRequest) {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700234 mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800235 } else {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700236 mTabHost.setCurrentTab(TAB_INDEX_DIALER);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800237 }
Jeff Hamilton90313772009-07-28 10:20:31 -0500238 } else if (FAVORITES_ENTRY_COMPONENT.equals(componentName)) {
239 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
Daniel Lehmann7675e122010-04-21 17:31:11 -0700240 } else if (CONTACTS_LAUNCH_ACTIVITY.equals(componentName)) {
241 mTabHost.setCurrentTab(mLastManuallySelectedTab);
Jeff Hamilton90313772009-07-28 10:20:31 -0500242 } else {
243 SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
244 boolean favoritesAsContacts = prefs.getBoolean(PREF_FAVORITES_AS_CONTACTS,
245 PREF_FAVORITES_AS_CONTACTS_DEFAULT);
246 if (favoritesAsContacts) {
247 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
248 } else {
249 mTabHost.setCurrentTab(TAB_INDEX_CONTACTS);
250 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800251 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700252
Daniel Lehmann7675e122010-04-21 17:31:11 -0700253 // Restore to the previous manual selection
254 mLastManuallySelectedTab = savedTabIndex;
255
The Android Open Source Project1f620962009-03-09 11:52:14 -0700256 // Tell the children activities that they should honor their saved states
257 // instead of the state from the parent's intent
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800258 intent.putExtra(EXTRA_IGNORE_STATE, false);
259 }
260
261 @Override
262 public void onNewIntent(Intent newIntent) {
263 setIntent(newIntent);
264 fixIntent(newIntent);
265 setCurrentTab(newIntent);
Jeff Hamilton90313772009-07-28 10:20:31 -0500266 final String action = newIntent.getAction();
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -0500267 if (action.equals(UI.FILTER_CONTACTS_ACTION)) {
Jeff Hamilton90313772009-07-28 10:20:31 -0500268 setupFilterText(newIntent);
269 } else if (isDialIntent(newIntent)) {
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800270 setupDialUri(newIntent);
271 }
272 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700273
274 /** Returns true if the given intent contains a phone number to populate the dialer with */
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800275 private boolean isDialIntent(Intent intent) {
276 final String action = intent.getAction();
277 if (Intent.ACTION_DIAL.equals(action)) {
278 return true;
279 }
280 if (Intent.ACTION_VIEW.equals(action)) {
281 final Uri data = intent.getData();
282 if (data != null && "tel".equals(data.getScheme())) {
283 return true;
284 }
285 }
286 return false;
287 }
Nicolas Catania08832402009-09-24 09:52:50 -0700288
Jeff Hamilton90313772009-07-28 10:20:31 -0500289 /**
290 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
291 * This text originally came from a FILTER_CONTACTS_ACTION intent received
292 * by this activity. The stored text will then be cleared after after this
293 * method returns.
Nicolas Catania08832402009-09-24 09:52:50 -0700294 *
Jeff Hamilton90313772009-07-28 10:20:31 -0500295 * @return The stored filter text
296 */
297 public String getAndClearFilterText() {
298 String filterText = mFilterText;
299 mFilterText = null;
300 return filterText;
301 }
302
303 /**
304 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
305 * This is so child activities can check if they are supposed to display a filter.
Nicolas Catania08832402009-09-24 09:52:50 -0700306 *
Jeff Hamilton90313772009-07-28 10:20:31 -0500307 * @param intent The intent received in {@link #onNewIntent(Intent)}
308 */
309 private void setupFilterText(Intent intent) {
310 // If the intent was relaunched from history, don't apply the filter text.
311 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
312 return;
313 }
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -0500314 String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY);
Jeff Hamilton90313772009-07-28 10:20:31 -0500315 if (filter != null && filter.length() > 0) {
316 mFilterText = filter;
317 }
318 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800319
320 /**
321 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
322 * originally came from a dial intent received by this activity. The stored
323 * uri will then be cleared after after this method returns.
Nicolas Catania08832402009-09-24 09:52:50 -0700324 *
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800325 * @return The stored uri
326 */
327 public Uri getAndClearDialUri() {
328 Uri dialUri = mDialUri;
329 mDialUri = null;
330 return dialUri;
331 }
332
333 /**
334 * Stores the uri associated with a dial intent. This is so child activities can
335 * check if they are supposed to display new dial info.
Nicolas Catania08832402009-09-24 09:52:50 -0700336 *
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800337 * @param intent The intent received in {@link #onNewIntent(Intent)}
338 */
339 private void setupDialUri(Intent intent) {
340 // If the intent was relaunched from history, don't reapply the intent.
341 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
342 return;
343 }
344 mDialUri = intent.getData();
345 }
346
347 @Override
Dianne Hackborn242599a2009-09-14 21:33:24 -0700348 public void onBackPressed() {
349 if (isTaskRoot()) {
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800350 // Instead of stopping, simply push this to the back of the stack.
351 // This is only done when running at the top of the stack;
352 // otherwise, we have been launched by someone else so need to
353 // allow the user to go back to the caller.
354 moveTaskToBack(false);
Dianne Hackborn242599a2009-09-14 21:33:24 -0700355 } else {
356 super.onBackPressed();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800357 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800358 }
359
360 /** {@inheritDoc} */
361 public void onTabChanged(String tabId) {
362 // Because we're using Activities as our tab children, we trigger
363 // onWindowFocusChanged() to let them know when they're active. This may
364 // seem to duplicate the purpose of onResume(), but it's needed because
365 // onResume() can't reliably check if a keyguard is active.
366 Activity activity = getLocalActivityManager().getActivity(tabId);
367 if (activity != null) {
368 activity.onWindowFocusChanged(true);
369 }
Daniel Lehmann7675e122010-04-21 17:31:11 -0700370
371 // Remember this tab index. This function is also called, if the tab is set automatically
372 // in which case the setter (setCurrentTab) has to set this to its old value afterwards
373 mLastManuallySelectedTab = mTabHost.getCurrentTab();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800374 }
375}