blob: 73d702b80c21d4e7a3af08a3fa025e15e4230b01 [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
19import android.app.Activity;
20import android.app.TabActivity;
21import android.content.Intent;
The Android Open Source Project1f620962009-03-09 11:52:14 -070022import android.content.SharedPreferences;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080023import android.graphics.drawable.Drawable;
24import android.net.Uri;
25import android.os.Bundle;
26import android.os.RemoteException;
27import android.os.ServiceManager;
The Android Open Source Project1f620962009-03-09 11:52:14 -070028import android.provider.CallLog;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080029import 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";
The Android Open Source Project1f620962009-03-09 11:52:14 -070045 private static final String FAVORITES_ENTRY_COMPONENT =
46 "com.android.contacts.DialtactsFavoritesEntryActivity";
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080047
The Android Open Source Project1f620962009-03-09 11:52:14 -070048 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";
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080054
The Android Open Source Project1f620962009-03-09 11:52:14 -070055 /** 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;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080060
The Android Open Source Project1f620962009-03-09 11:52:14 -070061 private TabHost mTabHost;
62 private String mFilterText;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080063 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);
The Android Open Source Project1f620962009-03-09 11:52:14 -070085
86 if (intent.getAction().equals(Contacts.Intents.UI.FILTER_CONTACTS_ACTION)
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080087 && icicle == null) {
88 setupFilterText(intent);
89 }
90 }
91
The Android Open Source Project1f620962009-03-09 11:52:14 -070092 @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
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800105 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() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700117 // 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
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800121 mTabHost.addTab(mTabHost.newTabSpec("call_log")
122 .setIndicator(getString(R.string.recentCallsIconLabel),
123 getResources().getDrawable(R.drawable.ic_tab_recent))
The Android Open Source Project1f620962009-03-09 11:52:14 -0700124 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800125 }
126
127 private void setupDialerTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700128 Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER");
129 intent.setClass(this, TwelveKeyDialer.class);
130
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800131 mTabHost.addTab(mTabHost.newTabSpec("dialer")
132 .setIndicator(getString(R.string.dialerIconLabel),
133 getResources().getDrawable(R.drawable.ic_tab_dialer))
The Android Open Source Project1f620962009-03-09 11:52:14 -0700134 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800135 }
136
137 private void setupContactsTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700138 Intent intent = new Intent(UI.LIST_DEFAULT);
139 intent.setClass(this, ContactsListActivity.class);
140
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800141 mTabHost.addTab(mTabHost.newTabSpec("contacts")
142 .setIndicator(getText(R.string.contactsIconLabel),
143 getResources().getDrawable(R.drawable.ic_tab_contacts))
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 setupFavoritesTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700148 Intent intent = new Intent(UI.LIST_STREQUENT_ACTION);
149 intent.setClass(this, ContactsListActivity.class);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800150
151 mTabHost.addTab(mTabHost.newTabSpec("favorites")
The Android Open Source Project1f620962009-03-09 11:52:14 -0700152 .setIndicator(getString(R.string.contactsFavoritesLabel),
153 getResources().getDrawable(R.drawable.ic_tab_starred))
154 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800155 }
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 *
The Android Open Source Project1f620962009-03-09 11:52:14 -0700185 * @param recentCallsRequest true is the recent calls tab is desired, false otherwise
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800186 */
187 private void setCurrentTab(Intent intent) {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700188 // 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 -0800189 final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
190 if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
191 finish();
192 return;
193 }
194
The Android Open Source Project1f620962009-03-09 11:52:14 -0700195 // Dismiss menu provided by any children activities
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800196 Activity activity = getLocalActivityManager().
197 getActivity(mTabHost.getCurrentTabTag());
198 if (activity != null) {
199 activity.closeOptionsMenu();
200 }
201
The Android Open Source Project1f620962009-03-09 11:52:14 -0700202 // Tell the children activities that they should ignore any possible saved
203 // state and instead reload their state from the parent's intent
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800204 intent.putExtra(EXTRA_IGNORE_STATE, true);
The Android Open Source Project1f620962009-03-09 11:52:14 -0700205
206 // Choose the tab based on the inbound intent
207 String componentName = intent.getComponent().getClassName();
208 if (getClass().getName().equals(componentName)) {
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800209 if (recentCallsRequest) {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700210 mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800211 } else {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700212 mTabHost.setCurrentTab(TAB_INDEX_DIALER);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800213 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700214 } else if (FAVORITES_ENTRY_COMPONENT.equals(componentName)) {
215 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800216 } else {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700217 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 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800225 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700226
227 // Tell the children activities that they should honor their saved states
228 // instead of the state from the parent's intent
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800229 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 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700244
245 /** 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 -0800246 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}