PageRenderTime 70ms CodeModel.GetById 18ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/CVox/src/com/android/contacts/ContactsListActivity.java

http://eyes-free.googlecode.com/
Java | 1437 lines | 667 code | 136 blank | 634 comment | 100 complexity | 9cbc043d250443b1896557300326e5a9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2007 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;
  18package com.android.contacts;
  19
  20import com.cvox.browser.R;
  21import com.cvox.browser.R.drawable;
  22import com.cvox.browser.R.layout;
  23import com.cvox.browser.R.string;
  24
  25import android.app.Activity;
  26import android.app.AlertDialog;
  27import android.app.ListActivity;
  28import android.app.SearchManager;
  29import android.content.AsyncQueryHandler;
  30import android.content.ContentResolver;
  31import android.content.ContentUris;
  32import android.content.ContentValues;
  33import android.content.Context;
  34import android.content.DialogInterface;
  35import android.content.Intent;
  36import android.content.SharedPreferences;
  37import android.database.Cursor;
  38import android.database.CharArrayBuffer;
  39import android.graphics.Bitmap;
  40import android.net.Uri;
  41import android.os.Bundle;
  42import android.os.Parcelable;
  43import android.preference.PreferenceManager;
  44import android.provider.Contacts;
  45import android.provider.Contacts.ContactMethods;
  46import android.provider.Contacts.Groups;
  47import android.provider.Contacts.Intents;
  48import android.provider.Contacts.People;
  49import android.provider.Contacts.Phones;
  50//import android.provider.Contacts.Presence;
  51import android.provider.Contacts.Intents.UI;
  52import android.telephony.PhoneNumberUtils;
  53import android.text.TextUtils;
  54import android.util.Log;
  55import android.view.ContextMenu;
  56import android.view.KeyEvent;
  57import android.view.LayoutInflater;
  58import android.view.Menu;
  59import android.view.MenuItem;
  60import android.view.View;
  61import android.view.ViewGroup;
  62import android.view.ContextMenu.ContextMenuInfo;
  63import android.widget.AdapterView;
  64import android.widget.ListView;
  65import android.widget.ResourceCursorAdapter;
  66import android.widget.TextView;
  67
  68import java.util.ArrayList;
  69
  70
  71/**
  72 * Displays a list of contacts. Usually is embedded into the ContactsActivity.
  73 */
  74public final class ContactsListActivity extends ListActivity
  75        implements View.OnCreateContextMenuListener, DialogInterface.OnClickListener {
  76    private static final String TAG = "ContactsListActivity";
  77
  78    private static final String LIST_STATE_KEY = "liststate";
  79    private static final String FOCUS_KEY = "focused";
  80
  81    static final int MENU_ITEM_VIEW_CONTACT = 1;
  82    static final int MENU_ITEM_CALL = 2;
  83    static final int MENU_ITEM_EDIT_BEFORE_CALL = 3;
  84    static final int MENU_ITEM_SEND_SMS = 4;
  85    static final int MENU_ITEM_SEND_IM = 5;
  86    static final int MENU_ITEM_EDIT = 6;
  87    static final int MENU_ITEM_DELETE = 7;
  88    static final int MENU_ITEM_TOGGLE_STAR = 8;
  89
  90    public static final int MENU_DIALER = 9;
  91    public static final int MENU_NEW_CONTACT = 10;
  92    public static final int MENU_DISPLAY_GROUP = 11;
  93
  94    private static final int SUBACTIVITY_NEW_CONTACT = 1;
  95    
  96    /** Mask for picker mode */
  97    static final int MODE_MASK_PICKER = 0x80000000;
  98    /** Mask for no presence mode */
  99    static final int MODE_MASK_NO_PRESENCE = 0x40000000;
 100    /** Mask for enabling list filtering */
 101    static final int MODE_MASK_NO_FILTER = 0x20000000;
 102    /** Mask for having a "create new contact" header in the list */
 103    static final int MODE_MASK_CREATE_NEW = 0x10000000;
 104
 105    /** Unknown mode */
 106    static final int MODE_UNKNOWN = 0;
 107    /** Show members of the "Contacts" group */
 108    static final int MODE_GROUP = 5;
 109    /** Show all contacts sorted alphabetically */
 110    static final int MODE_ALL_CONTACTS = 10;
 111    /** Show all contacts with phone numbers, sorted alphabetically */
 112    static final int MODE_WITH_PHONES = 15;
 113    /** Show all starred contacts */
 114    static final int MODE_STARRED = 20;
 115    /** Show frequently contacted contacts */
 116    static final int MODE_FREQUENT = 30;
 117    /** Show starred and the frequent */
 118    static final int MODE_STREQUENT = 35;
 119    /** Show all contacts and pick them when clicking */
 120    static final int MODE_PICK_CONTACT = 40 | MODE_MASK_PICKER;
 121    /** Show all contacts as well as the option to create a new one */
 122    static final int MODE_PICK_OR_CREATE_CONTACT = 42 | MODE_MASK_PICKER | MODE_MASK_CREATE_NEW;
 123    /** Show all contacts and pick them when clicking, and allow creating a new contact */
 124    static final int MODE_INSERT_OR_EDIT_CONTACT = 45 | MODE_MASK_PICKER | MODE_MASK_CREATE_NEW;
 125    /** Show all phone numbers and pick them when clicking */
 126    static final int MODE_PICK_PHONE = 50 | MODE_MASK_PICKER | MODE_MASK_NO_PRESENCE;
 127    /** Show all postal addresses and pick them when clicking */
 128    static final int MODE_PICK_POSTAL =
 129            55 | MODE_MASK_PICKER | MODE_MASK_NO_PRESENCE | MODE_MASK_NO_FILTER;
 130    /** Show all email addresses and pick them when clicking */
 131    static final int MODE_PICK_EMAIL = 56 | MODE_MASK_PICKER | MODE_MASK_NO_PRESENCE | MODE_MASK_NO_FILTER;
 132    /** Run a search query */
 133    static final int MODE_QUERY = 60 | MODE_MASK_NO_FILTER;
 134
 135    static final int DEFAULT_MODE = MODE_ALL_CONTACTS;
 136
 137    static final String NAME_COLUMN = People.DISPLAY_NAME;
 138    
 139    static final String[] CONTACTS_PROJECTION = new String[] {
 140        People._ID, // 0
 141        NAME_COLUMN, // 1
 142        People.NUMBER, // 2
 143        People.TYPE, // 3
 144        People.LABEL, // 4
 145        People.STARRED, // 5
 146        People.PRIMARY_PHONE_ID, // 6
 147        People.PRIMARY_EMAIL_ID, // 7
 148//        People.PRESENCE_STATUS, // 8
 149    };
 150
 151    static final String[] STREQUENT_PROJECTION = new String[] {
 152        People._ID, // 0
 153        NAME_COLUMN, // 1
 154        People.NUMBER, // 2
 155        People.TYPE, // 3
 156        People.LABEL, // 4
 157        People.STARRED, // 5
 158        People.PRIMARY_PHONE_ID, // 6
 159        People.PRIMARY_EMAIL_ID, // 7
 160//        People.PRESENCE_STATUS, // 8
 161        People.TIMES_CONTACTED, // 9 (not displayed, but required for the order by to work)
 162    };
 163
 164    static final String[] PHONES_PROJECTION = new String[] {
 165        Phones._ID, // 0
 166        NAME_COLUMN, // 1
 167        Phones.NUMBER, // 2
 168        Phones.TYPE, // 3
 169        Phones.LABEL, // 4
 170        Phones.STARRED, // 5
 171    };
 172
 173    static final String[] CONTACT_METHODS_PROJECTION = new String[] {
 174        ContactMethods._ID, // 0
 175        NAME_COLUMN, // 1
 176        ContactMethods.DATA, // 2
 177        ContactMethods.TYPE, // 3
 178        ContactMethods.LABEL, // 4
 179        ContactMethods.STARRED, // 5
 180    };
 181
 182    static final int ID_COLUMN_INDEX = 0;
 183    static final int NAME_COLUMN_INDEX = 1;
 184    static final int NUMBER_COLUMN_INDEX = 2;
 185    static final int DATA_COLUMN_INDEX = 2;
 186    static final int TYPE_COLUMN_INDEX = 3;
 187    static final int LABEL_COLUMN_INDEX = 4;
 188    static final int STARRED_COLUMN_INDEX = 5;
 189    static final int PRIMARY_PHONE_ID_COLUMN_INDEX = 6;
 190    static final int PRIMARY_EMAIL_ID_COLUMN_INDEX = 7;
 191    static final int SERVER_STATUS_COLUMN_INDEX = 8;
 192
 193    
 194    static final int DISPLAY_GROUP_INDEX_ALL_CONTACTS = 0;
 195    static final int DISPLAY_GROUP_INDEX_ALL_CONTACTS_WITH_PHONES = 1;
 196    static final int DISPLAY_GROUP_INDEX_MY_CONTACTS = 2;
 197    
 198    static final String SORT_ORDER = NAME_COLUMN + " COLLATE LOCALIZED ASC";
 199    
 200    private static final int QUERY_TOKEN = 42;
 201
 202    private static final String[] GROUPS_PROJECTION = new String[] {
 203        Groups.SYSTEM_ID, // 0
 204        Groups.NAME, // 1
 205    };
 206    private static final int GROUPS_COLUMN_INDEX_SYSTEM_ID = 0;
 207    private static final int GROUPS_COLUMN_INDEX_NAME = 1;
 208    
 209    static final String GROUP_WITH_PHONES = "android_smartgroup_phone";
 210
 211    ContactItemListAdapter mAdapter;
 212
 213    private int mMode = DEFAULT_MODE;
 214    // The current display group
 215    private String mDisplayInfo;
 216    private int mDisplayType;
 217    // The current list of display groups, during selection from menu
 218    private CharSequence[] mDisplayGroups;
 219    // If true position 2 in mDisplayGroups is the MyContacts group
 220    private boolean mDisplayGroupsIncludesMyContacts = false;
 221
 222    private int mDisplayGroupOriginalSelection;
 223    private int mDisplayGroupCurrentSelection;
 224    
 225    private QueryHandler mQueryHandler;
 226    private String mQuery;
 227    private Uri mGroupFilterUri;
 228    private Uri mGroupUri;
 229    private boolean mJustCreated;
 230
 231    /**
 232     * Used to keep track of the scroll state of the list.
 233     */
 234    private Parcelable mListState = null;
 235    private boolean mListHasFocus;
 236
 237    private boolean mCreateShortcut;
 238    private boolean mDefaultMode = false;
 239
 240    private class DeleteClickListener implements DialogInterface.OnClickListener {
 241        private Uri mUri;
 242
 243        public DeleteClickListener(Uri uri) {
 244            mUri = uri;
 245        }
 246
 247        public void onClick(DialogInterface dialog, int which) {
 248            getContentResolver().delete(mUri, null, null);
 249        }
 250    }
 251
 252    @Override
 253    protected void onCreate(Bundle icicle) {
 254        super.onCreate(icicle);
 255
 256        // Make sure the preferences are setup
 257//        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
 258
 259        // Resolve the intent
 260        final Intent intent = getIntent();
 261
 262        // Allow the title to be set to a custom String using an extra on the intent
 263        String title = intent.getStringExtra(Contacts.Intents.UI.TITLE_EXTRA_KEY);
 264        if (title != null) {
 265            setTitle(title);
 266        }
 267
 268        final String action = intent.getAction();
 269        mMode = MODE_UNKNOWN;
 270        
 271        setContentView(R.layout.contacts_list_content);
 272
 273//        if (UI.LIST_DEFAULT.equals(action)) {
 274//            mDefaultMode = true;
 275//            // When mDefaultMode is true the mode is set in onResume(), since the preferneces
 276//            // activity may change it whenever this activity isn't running
 277//        } else if (UI.LIST_GROUP_ACTION.equals(action)) {
 278//            mMode = MODE_GROUP;
 279//            String groupName = intent.getStringExtra(UI.GROUP_NAME_EXTRA_KEY);
 280//            if (TextUtils.isEmpty(groupName)) {
 281//                finish();
 282//                return;
 283//            }
 284//            buildUserGroupUris(groupName);
 285//        } else if (UI.LIST_ALL_CONTACTS_ACTION.equals(action)) {
 286//            mMode = MODE_ALL_CONTACTS;
 287//        } else if (UI.LIST_STARRED_ACTION.equals(action)) {
 288//            mMode = MODE_STARRED;
 289//        } else if (UI.LIST_FREQUENT_ACTION.equals(action)) {
 290//            mMode = MODE_FREQUENT;
 291//        } else if (UI.LIST_STREQUENT_ACTION.equals(action)) {
 292//            mMode = MODE_STREQUENT;
 293//        } else if (UI.LIST_CONTACTS_WITH_PHONES_ACTION.equals(action)) {
 294//            mMode = MODE_WITH_PHONES;
 295//        } else if (Intent.ACTION_PICK.equals(action)) {
 296//            // XXX These should be showing the data from the URI given in
 297//            // the Intent.
 298//            final String type = intent.resolveType(this);
 299//            if (People.CONTENT_TYPE.equals(type)) {
 300//                mMode = MODE_PICK_CONTACT;
 301//            } else if (Phones.CONTENT_TYPE.equals(type)) {
 302//                mMode = MODE_PICK_PHONE;
 303//            } else if (ContactMethods.CONTENT_POSTAL_TYPE.equals(type)) {
 304//                mMode = MODE_PICK_POSTAL;
 305//            }
 306//        } else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
 307//            mMode = MODE_PICK_OR_CREATE_CONTACT;
 308//            mCreateShortcut = true;
 309//        } else 
 310        if (Intent.ACTION_GET_CONTENT.equals(action)) {
 311            final String type = intent.resolveType(this);
 312            if (People.CONTENT_ITEM_TYPE.equals(type)) {
 313                mMode = MODE_PICK_OR_CREATE_CONTACT;
 314            } else if (Phones.CONTENT_ITEM_TYPE.equals(type)) {
 315                mMode = MODE_PICK_PHONE;
 316            } else if (ContactMethods.CONTENT_POSTAL_ITEM_TYPE.equals(type)) {
 317                mMode = MODE_PICK_POSTAL;
 318            } else if (ContactMethods.CONTENT_EMAIL_ITEM_TYPE.equals(type)) {
 319                mMode = MODE_PICK_EMAIL;
 320            }
 321//        } else if (Intent.ACTION_INSERT_OR_EDIT.equals(action)) {
 322//            mMode = MODE_INSERT_OR_EDIT_CONTACT;
 323//        } else if (Intent.ACTION_SEARCH.equals(action)) {
 324//            // See if the suggestion was clicked with a search action key (call button)
 325//            if ("call".equals(intent.getStringExtra(SearchManager.ACTION_MSG))) {
 326//                String query = intent.getStringExtra(SearchManager.QUERY);
 327//                if (!TextUtils.isEmpty(query)) {
 328//                    Intent newIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
 329//                            Uri.fromParts("tel", query, null));
 330//                    startActivity(newIntent);
 331//                }
 332//                finish();
 333//                return;
 334//            }
 335//            // Otherwise handle the more normal search case
 336//            mMode = MODE_QUERY;
 337//
 338//        // Since this is the filter activity it receives all intents
 339//        // dispatched from the SearchManager for security reasons
 340//        // so we need to re-dispatch from here to the intended target.
 341//        } else if (Intents.SEARCH_SUGGESTION_CLICKED.equals(action)) {
 342//            // See if the suggestion was clicked with a search action key (call button)
 343//            Intent newIntent;
 344//            if ("call".equals(intent.getStringExtra(SearchManager.ACTION_MSG))) {
 345//                newIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData());
 346//            } else {
 347//                newIntent = new Intent(Intent.ACTION_VIEW, intent.getData());
 348//            }
 349//            startActivity(newIntent);
 350//            finish();
 351//            return;
 352//        } else if (Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED.equals(action)) {
 353//            Intent newIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData());
 354//            startActivity(newIntent);
 355//            finish();
 356//            return;
 357//        } else if (Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED.equals(action)) {
 358//            String number = intent.getData().getSchemeSpecificPart();
 359//            Intent newIntent = new Intent(Intent.ACTION_INSERT, People.CONTENT_URI);
 360//            newIntent.putExtra(Intents.Insert.PHONE, number);
 361//            startActivity(newIntent);
 362//            finish();
 363//            return;
 364        }
 365
 366//        if (mMode == MODE_UNKNOWN) {
 367//            mMode = DEFAULT_MODE;
 368//        }
 369
 370/*
 371        if (!mDefaultMode) {
 372            findViewById(R.id.contact_group).banner.setVisibility(View.GONE);
 373        }
 374*/
 375
 376        // Setup the UI
 377        final ListView list = getListView();
 378        list.setFocusable(true);
 379        list.setOnCreateContextMenuListener(this);
 380//        if ((mMode & MODE_MASK_NO_FILTER) != MODE_MASK_NO_FILTER) {
 381//            list.setTextFilterEnabled(true);
 382//        }
 383//
 384//        if ((mMode & MODE_MASK_CREATE_NEW) != 0) {
 385//            // Add the header for creating a new contact
 386//            final LayoutInflater inflater = getLayoutInflater();
 387//            View header = inflater.inflate(android.R.layout.simple_list_item_1, list, false);
 388//            TextView text = (TextView) header.findViewById(android.R.id.text1);
 389//            text.setText(R.string.pickerNewContactHeader);
 390//            list.addHeaderView(header);
 391//        }
 392
 393        // Set the proper empty string
 394        setEmptyText();
 395        
 396        mAdapter = new ContactItemListAdapter(this, R.layout.contacts_list_item, null);
 397        setListAdapter(mAdapter);
 398
 399        // We manually save/restore the listview state
 400        list.setSaveEnabled(false);
 401
 402        mQueryHandler = new QueryHandler(this);
 403        mJustCreated = true;
 404    }
 405
 406    private void setEmptyText() {
 407//        TextView empty = (TextView) findViewById(android.R.id.empty);
 408//        switch (mMode) {
 409//            case MODE_GROUP:
 410//                if (Groups.GROUP_MY_CONTACTS.equals(mDisplayInfo)) {
 411//                    empty.setText(getString(R.string.groupEmpty,
 412//                            getText(R.string.groupNameMyContacts)));
 413//                } else {
 414//                    empty.setText(getString(R.string.groupEmpty, mDisplayInfo));
 415//                }
 416//                break;
 417//
 418//            case MODE_STARRED:
 419//            case MODE_STREQUENT:
 420//            case MODE_FREQUENT:
 421//                empty.setText(getText(R.string.noFavorites));
 422//                break;
 423//
 424//            case MODE_WITH_PHONES:
 425//                empty.setText(getText(R.string.noContactsWithPhoneNumbers));
 426//                break;
 427//
 428//            default:
 429//                empty.setText(getText(R.string.noContacts));
 430//                break;
 431//        }
 432    }
 433
 434    /**
 435     * Builds the URIs to query when displaying a user group
 436     * 
 437     * @param groupName the group being displayed
 438     */
 439    private void buildUserGroupUris(String groupName) {
 440        mGroupFilterUri = Uri.parse("content://contacts/groups/name/" + groupName
 441                + "/members/filter/");
 442        mGroupUri = Uri.parse("content://contacts/groups/name/" + groupName + "/members");
 443    }
 444
 445    /**
 446     * Builds the URIs to query when displaying a system group
 447     * 
 448     * @param systemId the system group's ID 
 449     */
 450    private void buildSystemGroupUris(String systemId) {
 451        mGroupFilterUri = Uri.parse("content://contacts/groups/system_id/" + systemId
 452                + "/members/filter/");
 453        mGroupUri = Uri.parse("content://contacts/groups/system_id/" + systemId + "/members");
 454    }
 455
 456    /**
 457     * Sets the mode when the request is for "default"
 458     */
 459    private void setDefaultMode() {
 460//        // Load the preferences
 461//        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 462//        
 463//        // Lookup the group to display
 464//        mDisplayType = prefs.getInt(ContactsPreferenceActivity.PREF_DISPLAY_TYPE,
 465//                ContactsPreferenceActivity.DISPLAY_TYPE_UNKNOWN);
 466//        switch (mDisplayType) {
 467//            case ContactsPreferenceActivity.DISPLAY_TYPE_ALL_WITH_PHONES: {
 468//                mMode = MODE_WITH_PHONES;
 469//                mDisplayInfo = null;
 470//                break;
 471//            }
 472//
 473//            case ContactsPreferenceActivity.DISPLAY_TYPE_SYSTEM_GROUP: {
 474//                String systemId = prefs.getString(
 475//                        ContactsPreferenceActivity.PREF_DISPLAY_INFO, null);
 476//                if (!TextUtils.isEmpty(systemId)) {
 477//                    // Display the selected system group
 478//                    mMode = MODE_GROUP;
 479//                    buildSystemGroupUris(systemId);
 480//                    mDisplayInfo = systemId;
 481//                } else {
 482//                    // No valid group is present, display everything
 483//                    mMode = MODE_WITH_PHONES;
 484//                    mDisplayInfo = null;
 485//                    mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_ALL;
 486//                }
 487//                break;
 488//            }
 489//
 490//            case ContactsPreferenceActivity.DISPLAY_TYPE_USER_GROUP: {
 491//                String displayGroup = prefs.getString(
 492//                        ContactsPreferenceActivity.PREF_DISPLAY_INFO, null);
 493//                if (!TextUtils.isEmpty(displayGroup)) {
 494//                    // Display the selected user group
 495//                    mMode = MODE_GROUP;
 496//                    buildUserGroupUris(displayGroup);
 497//                    mDisplayInfo = displayGroup;
 498//                } else {
 499//                    // No valid group is present, display everything
 500//                    mMode = MODE_WITH_PHONES;
 501//                    mDisplayInfo = null;
 502//                    mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_ALL;
 503//                }
 504//                break;
 505//            }
 506//
 507//            case ContactsPreferenceActivity.DISPLAY_TYPE_ALL: {
 508//                mMode = MODE_ALL_CONTACTS;
 509//                mDisplayInfo = null;
 510//                break;
 511//            }
 512//
 513//            default: {
 514//                // We don't know what to display, default to My Contacts
 515//                mMode = MODE_GROUP;
 516//                mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_SYSTEM_GROUP;
 517//                buildSystemGroupUris(Groups.GROUP_MY_CONTACTS);
 518//                mDisplayInfo = Groups.GROUP_MY_CONTACTS;
 519//                break;
 520//            }
 521//        }
 522//
 523//        // Update the empty text view with the proper string, as the group may have changed
 524//        setEmptyText();
 525    }
 526
 527    @Override
 528    protected void onResume() {
 529        super.onResume();
 530
 531        boolean runQuery = true;
 532        Activity parent = getParent();
 533        
 534        // Do this before setting the filter. The filter thread relies
 535        // on some state that is initialized in setDefaultMode
 536        if (mDefaultMode) {
 537            // If we're in default mode we need to possibly reset the mode due to a change
 538            // in the preferences activity while we weren't running
 539            setDefaultMode();
 540        }
 541        
 542        // See if we were invoked with a filter
 543//        if (parent != null && parent instanceof DialtactsActivity) {
 544//            String filterText = ((DialtactsActivity) parent).getAndClearFilterText();
 545//            if (filterText != null && filterText.length() > 0) {
 546//                getListView().setFilterText(filterText);
 547//                // Don't start a new query since it will conflict with the filter
 548//                runQuery = false;
 549//            } else if (mJustCreated) {
 550//                getListView().clearTextFilter();
 551//            }
 552//        }
 553
 554        if (runQuery) {
 555            // Calling requery here may cause an ANR, so always do the async query
 556            startQuery();
 557        }
 558        mJustCreated = false;
 559    }
 560    
 561    private void updateGroup() {
 562        if (mDefaultMode) {
 563            setDefaultMode();
 564        }
 565
 566        // Calling requery here may cause an ANR, so always do the async query
 567        startQuery();
 568    }
 569
 570    @Override
 571    protected void onSaveInstanceState(Bundle icicle) {
 572        super.onSaveInstanceState(icicle);
 573        // Save list state in the bundle so we can restore it after the QueryHandler has run
 574//        icicle.putParcelable(LIST_STATE_KEY, mList.onSaveInstanceState());
 575//        icicle.putBoolean(FOCUS_KEY, mList.hasFocus());
 576    }
 577
 578    @Override
 579    protected void onRestoreInstanceState(Bundle icicle) {
 580        super.onRestoreInstanceState(icicle);
 581        // Retrieve list state. This will be applied after the QueryHandler has run
 582//        mListState = icicle.getParcelable(LIST_STATE_KEY);
 583//        mListHasFocus = icicle.getBoolean(FOCUS_KEY);
 584    }
 585
 586    @Override
 587    protected void onStop() {
 588        super.onStop();
 589
 590        // We don't want the list to display the empty state, since when we resume it will still
 591        // be there and show up while the new query is happening. After the async query finished
 592        // in response to onResume() setLoading(false) will be called.
 593        mAdapter.setLoading(true);
 594        mAdapter.changeCursor(null);
 595
 596        if (mMode == MODE_QUERY) {
 597            // Make sure the search box is closed
 598            SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
 599            searchManager.stopSearch();
 600        }
 601    }
 602
 603    @Override
 604    public boolean onCreateOptionsMenu(Menu menu) {
 605        // If Contacts was invoked by another Activity simply as a way of
 606        // picking a contact, don't show the options menu
 607        if ((mMode & MODE_MASK_PICKER) == MODE_MASK_PICKER) {
 608            return false;
 609        }
 610
 611//        menu.add(0, MENU_NEW_CONTACT, 0, R.string.menu_newContact)
 612//                .setIcon(android.R.drawable.ic_menu_add)
 613//                .setIntent(new Intent(Intents.Insert.ACTION, People.CONTENT_URI))
 614//                .setAlphabeticShortcut('n');
 615//        if (isChild()) {
 616//            menu.add(0, 0, 0, R.string.menu_preferences)
 617//                    .setIcon(android.R.drawable.ic_menu_preferences)
 618//                    .setIntent(new Intent(this, ContactsPreferenceActivity.class));
 619//        }
 620//        if (mDefaultMode) {
 621//            menu.add(0, MENU_DISPLAY_GROUP, 0, R.string.menu_displayGroup)
 622//                    .setIcon(R.drawable.ic_menu_allfriends);
 623//        }
 624        return super.onCreateOptionsMenu(menu);
 625    }
 626
 627    /*
 628     * Implements the handler for display group selection.
 629     */
 630    public void onClick(DialogInterface dialogInterface, int which) {
 631//        if (which == DialogInterface.BUTTON1) {
 632//            // The OK button was pressed
 633//            if (mDisplayGroupOriginalSelection != mDisplayGroupCurrentSelection) {
 634//                // Set the group to display
 635//                if (mDisplayGroupCurrentSelection == DISPLAY_GROUP_INDEX_ALL_CONTACTS) {
 636//                    // Display all
 637//                    mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_ALL;
 638//                    mDisplayInfo = null;
 639//                } else if (mDisplayGroupCurrentSelection
 640//                        == DISPLAY_GROUP_INDEX_ALL_CONTACTS_WITH_PHONES) {
 641//                    // Display all with phone numbers
 642//                    mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_ALL_WITH_PHONES;
 643//                    mDisplayInfo = null;
 644//                } else if (mDisplayGroupsIncludesMyContacts &&
 645//                        mDisplayGroupCurrentSelection == DISPLAY_GROUP_INDEX_MY_CONTACTS) {
 646//                    mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_SYSTEM_GROUP;
 647//                    mDisplayInfo = Groups.GROUP_MY_CONTACTS;
 648//                } else {
 649//                    mDisplayType = ContactsPreferenceActivity.DISPLAY_TYPE_USER_GROUP;
 650//                    mDisplayInfo = mDisplayGroups[mDisplayGroupCurrentSelection].toString();
 651//                }
 652//
 653//                // Save the changes to the preferences
 654//                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 655//                prefs.edit()
 656//                        .putInt(ContactsPreferenceActivity.PREF_DISPLAY_TYPE, mDisplayType)
 657//                        .putString(ContactsPreferenceActivity.PREF_DISPLAY_INFO, mDisplayInfo)
 658//                        .commit();
 659//
 660//                // Update the display state
 661//                updateGroup();
 662//            }
 663//        } else {
 664//            // A list item was selected, cache the position
 665//            mDisplayGroupCurrentSelection = which;
 666//        }
 667    }
 668    
 669    @Override
 670    public boolean onOptionsItemSelected(MenuItem item) {
 671//        if (item.getItemId() == MENU_DISPLAY_GROUP) {
 672//            AlertDialog.Builder builder = new AlertDialog.Builder(this)
 673//                .setTitle(R.string.select_group_title)
 674//                .setPositiveButton(android.R.string.ok, this)
 675//                .setNegativeButton(android.R.string.cancel, null);
 676//            
 677//            setGroupEntries(builder);
 678//            
 679//            builder.show();
 680//            return true;
 681//        }
 682        return false;
 683    }
 684
 685    @Override
 686    protected void onActivityResult(int requestCode, int resultCode,
 687            Intent data) {
 688        switch (requestCode) {
 689            case SUBACTIVITY_NEW_CONTACT:
 690                if (resultCode == RESULT_OK) {
 691                    // Contact was created, pass it back
 692                    returnPickerResult(data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
 693                            data.getData());
 694                }
 695        }
 696    }
 697
 698    @Override
 699    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
 700        // If Contacts was invoked by another Activity simply as a way of
 701        // picking a contact, don't show the context menu
 702        if ((mMode & MODE_MASK_PICKER) == MODE_MASK_PICKER) {
 703            return;
 704        }
 705
 706//        AdapterView.AdapterContextMenuInfo info;
 707//        try {
 708//             info = (AdapterView.AdapterContextMenuInfo) menuInfo;
 709//        } catch (ClassCastException e) {
 710//            Log.e(TAG, "bad menuInfo", e);
 711//            return;
 712//        }
 713//
 714//        Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
 715//        if (cursor == null) {
 716//            // For some reason the requested item isn't available, do nothing
 717//            return;
 718//        }
 719//        long id = info.id;
 720//        Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, id);
 721//
 722//        // Setup the menu header
 723//        menu.setHeaderTitle(cursor.getString(NAME_COLUMN_INDEX));
 724//
 725//        // View contact details
 726//        menu.add(0, MENU_ITEM_VIEW_CONTACT, 0, R.string.menu_viewContact)
 727//                .setIntent(new Intent(Intent.ACTION_VIEW, personUri));
 728//
 729//        // Calling contact
 730//        long phoneId = cursor.getLong(PRIMARY_PHONE_ID_COLUMN_INDEX);
 731//        if (phoneId > 0) {
 732//            // Get the display label for the number
 733//            CharSequence label = cursor.getString(LABEL_COLUMN_INDEX);
 734//            int type = cursor.getInt(TYPE_COLUMN_INDEX);
 735//            label = Phones.getDisplayLabel(this, type, label);
 736//            Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
 737//                    ContentUris.withAppendedId(Phones.CONTENT_URI, phoneId));
 738//            menu.add(0, MENU_ITEM_CALL, 0, String.format(getString(R.string.menu_callNumber), label))
 739//                    .setIntent(intent);
 740//
 741//            // Send SMS item
 742//            menu.add(0, MENU_ITEM_SEND_SMS, 0, R.string.menu_sendSMS)
 743//                    .setIntent(new Intent(Intent.ACTION_SENDTO,
 744//                            Uri.fromParts("sms", cursor.getString(NUMBER_COLUMN_INDEX), null)));
 745//        }
 746//
 747//        // Star toggling
 748//        int starState = cursor.getInt(STARRED_COLUMN_INDEX);
 749//        if (starState == 0) {
 750//            menu.add(0, MENU_ITEM_TOGGLE_STAR, 0, R.string.menu_addStar);
 751//        } else {
 752//            menu.add(0, MENU_ITEM_TOGGLE_STAR, 0, R.string.menu_removeStar);
 753//        }
 754//
 755//        // Contact editing
 756//        menu.add(0, MENU_ITEM_EDIT, 0, R.string.menu_editContact)
 757//                .setIntent(new Intent(Intent.ACTION_EDIT, personUri));
 758//        menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_deleteContact);
 759    }
 760
 761    @Override
 762    public boolean onContextItemSelected(MenuItem item) {
 763//        AdapterView.AdapterContextMenuInfo info;
 764//        try {
 765//             info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
 766//        } catch (ClassCastException e) {
 767//            Log.e(TAG, "bad menuInfo", e);
 768//            return false;
 769//        }
 770//
 771//        Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
 772//
 773//        switch (item.getItemId()) {
 774//            case MENU_ITEM_TOGGLE_STAR: {
 775//                // Toggle the star
 776//                ContentValues values = new ContentValues(1);
 777//                values.put(People.STARRED, cursor.getInt(STARRED_COLUMN_INDEX) == 0 ? 1 : 0);
 778//                Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI,
 779//                        cursor.getInt(ID_COLUMN_INDEX));
 780//                getContentResolver().update(personUri, values, null, null);
 781//                return true;
 782//            }
 783//
 784//            case MENU_ITEM_DELETE: {
 785//                // Get confirmation
 786//                Uri uri = ContentUris.withAppendedId(People.CONTENT_URI,
 787//                        cursor.getLong(ID_COLUMN_INDEX));
 788//                //TODO make this dialog persist across screen rotations
 789//                new AlertDialog.Builder(ContactsListActivity.this)
 790//                    .setTitle(R.string.deleteConfirmation_title)
 791//                    .setIcon(android.R.drawable.ic_dialog_alert)
 792//                    .setMessage(R.string.deleteConfirmation)
 793//                    .setNegativeButton(R.string.noButton, null)
 794//                    .setPositiveButton(R.string.yesButton, new DeleteClickListener(uri))
 795//                    .setCancelable(false)
 796//                    .show();
 797//                return true;
 798//            }
 799//        }
 800//
 801        return super.onContextItemSelected(item);
 802    }
 803
 804    @Override
 805    public boolean onKeyDown(int keyCode, KeyEvent event) {
 806//        switch (keyCode) {
 807//            case KeyEvent.KEYCODE_CALL: {
 808//                if (callSelection()) {
 809//                    return true;
 810//                }
 811//                break;
 812//            }
 813//
 814//            case KeyEvent.KEYCODE_DEL: {
 815//                Object o = getListView().getSelectedItem();
 816//                if (o != null) {
 817//                    Cursor cursor = (Cursor) o;
 818//                    Uri uri = ContentUris.withAppendedId(People.CONTENT_URI,
 819//                            cursor.getLong(ID_COLUMN_INDEX));
 820//                    //TODO make this dialog persist across screen rotations
 821//                    new AlertDialog.Builder(ContactsListActivity.this)
 822//                        .setTitle(R.string.deleteConfirmation_title)
 823//                        .setIcon(android.R.drawable.ic_dialog_alert)
 824//                        .setMessage(R.string.deleteConfirmation)
 825//                        .setNegativeButton(R.string.noButton, null)
 826//                        .setPositiveButton(R.string.yesButton, new DeleteClickListener(uri))
 827//                        .setCancelable(false)
 828//                        .show();
 829//                    return true;
 830//                }
 831//                break;
 832//            }
 833//        }
 834
 835        return super.onKeyDown(keyCode, event);
 836    }
 837
 838    @Override
 839    protected void onListItemClick(ListView l, View v, int position, long id) {
 840//        if (mMode == MODE_INSERT_OR_EDIT_CONTACT) {
 841//            Intent intent;
 842//            if (position == 0) {
 843//                // Insert
 844//                intent = new Intent(Intent.ACTION_INSERT, People.CONTENT_URI);
 845//            } else {
 846//                // Edit
 847//                intent = new Intent(Intent.ACTION_EDIT,
 848//                        ContentUris.withAppendedId(People.CONTENT_URI, id));
 849//            }
 850//            intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
 851//            final Bundle extras = getIntent().getExtras();
 852//            if (extras != null) {
 853//                intent.putExtras(extras);
 854//            }
 855//            startActivity(intent);
 856//            finish();
 857//        } else 
 858    	if (id != -1) {
 859            if ((mMode & MODE_MASK_PICKER) == 0) {
 860                Intent intent = new Intent(Intent.ACTION_VIEW,
 861                        ContentUris.withAppendedId(People.CONTENT_URI, id));
 862                startActivity(intent);
 863            } else if (mMode == MODE_PICK_CONTACT 
 864                    || mMode == MODE_PICK_OR_CREATE_CONTACT) {
 865                Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, id);
 866                if (mCreateShortcut) {
 867                    // Subtract one if we have Create Contact at the top
 868                    Cursor c = (Cursor) mAdapter.getItem(position
 869                            - (mMode == MODE_PICK_OR_CREATE_CONTACT? 1:0));
 870                    returnPickerResult(c.getString(NAME_COLUMN_INDEX), uri);
 871                } else {
 872                    returnPickerResult(null, uri);
 873                }
 874            } else if (mMode == MODE_PICK_PHONE) {
 875                setResult(RESULT_OK, new Intent().setData(
 876                        ContentUris.withAppendedId(Phones.CONTENT_URI, id)));
 877                finish();
 878            } else if (mMode == MODE_PICK_POSTAL) {
 879                setResult(RESULT_OK, new Intent().setData(
 880                        ContentUris.withAppendedId(ContactMethods.CONTENT_URI, id)));
 881                finish();
 882            } else if (mMode == MODE_PICK_EMAIL) {
 883                setResult(RESULT_OK, new Intent().setData(
 884                        ContentUris.withAppendedId(ContactMethods.CONTENT_URI, id)));
 885                finish();
 886            }
 887//        } else if ((mMode & MODE_MASK_CREATE_NEW) == MODE_MASK_CREATE_NEW
 888//                && position == 0) {
 889//            Intent newContact = new Intent(Intents.Insert.ACTION, People.CONTENT_URI);
 890//            startActivityForResult(newContact, SUBACTIVITY_NEW_CONTACT);
 891//        } else {
 892//            signalError();
 893        }
 894    }
 895
 896    private void returnPickerResult(String name, Uri uri) {
 897        final Intent intent = new Intent();
 898    
 899//        if (mCreateShortcut) {
 900//            Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, uri);
 901//            shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 902//            intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
 903//            intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
 904//            final Bitmap icon = People.loadContactPhoto(this, uri, 0, null);
 905//            if (icon != null) {
 906//                intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
 907//            } else {
 908//                intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
 909//                        Intent.ShortcutIconResource.fromContext(this,
 910//                                R.drawable.ic_launcher_contacts));
 911//            }
 912//            setResult(RESULT_OK, intent);
 913//        } else {
 914            setResult(RESULT_OK, intent.setData(uri));
 915//        }
 916        finish();
 917    }
 918
 919    String[] getProjection() {
 920        switch (mMode) {
 921            case MODE_GROUP:
 922            case MODE_ALL_CONTACTS:
 923            case MODE_WITH_PHONES:
 924            case MODE_PICK_CONTACT:
 925            case MODE_PICK_OR_CREATE_CONTACT:
 926            case MODE_QUERY:
 927            case MODE_STARRED:
 928            case MODE_FREQUENT:
 929            case MODE_INSERT_OR_EDIT_CONTACT:
 930                return CONTACTS_PROJECTION;
 931
 932            case MODE_STREQUENT:
 933                return STREQUENT_PROJECTION;
 934
 935            case MODE_PICK_PHONE:
 936                return PHONES_PROJECTION;
 937
 938            case MODE_PICK_POSTAL:
 939                return CONTACT_METHODS_PROJECTION;
 940
 941            case MODE_PICK_EMAIL:
 942                return CONTACT_METHODS_PROJECTION;
 943        }
 944        return null;
 945    }
 946
 947    private Uri getPeopleFilterUri(String filter) {
 948        if (!TextUtils.isEmpty(filter)) {
 949            return Uri.withAppendedPath(People.CONTENT_FILTER_URI, Uri.encode(filter));
 950        } else {
 951            return People.CONTENT_URI;
 952        }
 953    }
 954
 955    void startQuery() {
 956        mAdapter.setLoading(true);
 957        
 958        // Cancel any pending queries
 959        mQueryHandler.cancelOperation(QUERY_TOKEN);
 960
 961        // Kick off the new query
 962        switch (mMode) {
 963            case MODE_GROUP:
 964                mQueryHandler.startQuery(QUERY_TOKEN, null,
 965                        mGroupUri, CONTACTS_PROJECTION, null, null, SORT_ORDER);
 966                break;
 967
 968            case MODE_ALL_CONTACTS:
 969            case MODE_PICK_CONTACT:
 970            case MODE_PICK_OR_CREATE_CONTACT:
 971            case MODE_INSERT_OR_EDIT_CONTACT:
 972                mQueryHandler.startQuery(QUERY_TOKEN, null, People.CONTENT_URI, CONTACTS_PROJECTION,
 973                        null, null, SORT_ORDER);
 974                break;
 975
 976            case MODE_WITH_PHONES:
 977                mQueryHandler.startQuery(QUERY_TOKEN, null, People.CONTENT_URI, CONTACTS_PROJECTION,
 978                        People.PRIMARY_PHONE_ID + " IS NOT NULL", null, People.DEFAULT_SORT_ORDER);
 979                break;
 980
 981            case MODE_QUERY: {
 982                mQuery = getIntent().getStringExtra(SearchManager.QUERY);
 983                mQueryHandler.startQuery(QUERY_TOKEN, null, getPeopleFilterUri(mQuery),
 984                        CONTACTS_PROJECTION, null, null, SORT_ORDER);
 985                break;
 986            }
 987
 988            case MODE_STARRED:
 989                mQueryHandler.startQuery(QUERY_TOKEN, null, People.CONTENT_URI, CONTACTS_PROJECTION,
 990                        People.STARRED + "=1", null, SORT_ORDER);
 991                break;
 992
 993            case MODE_FREQUENT:
 994                mQueryHandler.startQuery(QUERY_TOKEN, null, People.CONTENT_URI, CONTACTS_PROJECTION,
 995                        People.TIMES_CONTACTED + " > 0", null,
 996                        People.TIMES_CONTACTED + " DESC, " + NAME_COLUMN + " ASC");
 997                break;
 998
 999            case MODE_STREQUENT:
1000                mQueryHandler.startQuery(QUERY_TOKEN, null,
1001                        Uri.withAppendedPath(People.CONTENT_URI, "strequent"), STREQUENT_PROJECTION,
1002                        null, null, null);
1003                break;
1004
1005            case MODE_PICK_PHONE:
1006                mQueryHandler.startQuery(QUERY_TOKEN, null, Phones.CONTENT_URI, PHONES_PROJECTION,
1007                        null, null, SORT_ORDER);
1008                break;
1009
1010            case MODE_PICK_POSTAL:
1011                mQueryHandler.startQuery(QUERY_TOKEN, null, ContactMethods.CONTENT_URI,
1012                        CONTACT_METHODS_PROJECTION,
1013                        ContactMethods.KIND + "=" + Contacts.KIND_POSTAL, null, SORT_ORDER);
1014                break;
1015                
1016            case MODE_PICK_EMAIL:
1017                mQueryHandler.startQuery(QUERY_TOKEN, null, ContactMethods.CONTENT_URI,
1018                        CONTACT_METHODS_PROJECTION,
1019                        ContactMethods.KIND + "=" + Contacts.KIND_EMAIL, null, SORT_ORDER);
1020                break;
1021        }
1022    }
1023
1024    /**
1025     * Called from a background thread to do the filter and return the resulting cursor.
1026     * 
1027     * @param filter the text that was entered to filter on
1028     * @return a cursor with the results of the filter
1029     */
1030    Cursor doFilter(String filter) {
1031        final ContentResolver resolver = getContentResolver();
1032
1033        switch (mMode) {
1034            case MODE_GROUP: {
1035                Uri uri;
1036                if (TextUtils.isEmpty(filter)) {
1037                    uri = mGroupUri;
1038                } else {
1039                    uri = Uri.withAppendedPath(mGroupFilterUri, Uri.encode(filter));
1040                }
1041                return resolver.query(uri, CONTACTS_PROJECTION, null, null,
1042                        People.DEFAULT_SORT_ORDER);
1043            }
1044
1045            case MODE_ALL_CONTACTS:
1046            case MODE_PICK_CONTACT:
1047            case MODE_PICK_OR_CREATE_CONTACT:
1048            case MODE_INSERT_OR_EDIT_CONTACT: {
1049                return resolver.query(getPeopleFilterUri(filter), CONTACTS_PROJECTION, null, null,
1050                        SORT_ORDER);
1051            }
1052
1053            case MODE_WITH_PHONES: {
1054                return resolver.query(getPeopleFilterUri(filter), CONTACTS_PROJECTION,
1055                        People.PRIMARY_PHONE_ID + " IS NOT NULL", null, SORT_ORDER);
1056            }
1057
1058            case MODE_STARRED: {
1059                return resolver.query(getPeopleFilterUri(filter), CONTACTS_PROJECTION,
1060                        People.STARRED + "=1", null, SORT_ORDER);
1061            }
1062
1063            case MODE_FREQUENT: {
1064                return resolver.query(getPeopleFilterUri(filter), CONTACTS_PROJECTION,
1065                        People.TIMES_CONTACTED + " > 0", null,
1066                        People.TIMES_CONTACTED + " DESC, " + NAME_COLUMN + " ASC");
1067            }
1068
1069            case MODE_STREQUENT: {
1070                Uri uri;
1071                if (!TextUtils.isEmpty(filter)) {
1072                    uri = Uri.withAppendedPath(People.CONTENT_URI, "strequent/filter/"
1073                            + Uri.encode(filter));
1074                } else {
1075                    uri = Uri.withAppendedPath(People.CONTENT_URI, "strequent");
1076                }
1077                return resolver.query(uri, STREQUENT_PROJECTION, null, null, null);
1078            }
1079
1080            case MODE_PICK_PHONE: {
1081                Uri uri;
1082                if (!TextUtils.isEmpty(filter)) {
1083                    uri = Uri.withAppendedPath(Phones.CONTENT_URI, "filter_name/"
1084                            + Uri.encode(filter));
1085                } else {
1086                    uri = Phones.CONTENT_URI;
1087                }
1088                return resolver.query(uri, PHONES_PROJECTION, null, null, SORT_ORDER);
1089            }
1090        }
1091        throw new UnsupportedOperationException("filtering not allowed in mode " + mMode);
1092    }
1093
1094    /**
1095     * Calls the currently selected list item.
1096     * @return true if the call was initiated, false otherwise
1097     */
1098    boolean callSelection() {
1099//        ListView list = getListView();
1100//        if (list.hasFocus()) {
1101//            Cursor cursor = (Cursor) list.getSelectedItem();
1102//            if (cursor != null) {
1103//                long phoneId = cursor.getLong(PRIMARY_PHONE_ID_COLUMN_INDEX);
1104//                if (phoneId == 0) {
1105//                    // There is no phone number.
1106//                    signalError();
1107//                    return false;
1108//                }
1109//                Uri uri = ContentUris.withAppendedId(Phones.CONTENT_URI, phoneId);
1110//                Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, uri);
1111//                startActivity(intent);
1112//                return true;
1113//            }
1114//        }
1115
1116        return false;
1117    }
1118
1119    /**
1120     * Signal an error to the user.
1121     */
1122    void signalError() {
1123        //TODO play an error beep or something...
1124    }
1125
1126    Cursor getItemForView(View view) {
1127        ListView listView = getListView();
1128        int index = listView.getPositionForView(view);
1129        if (index < 0) {
1130            return null;
1131        }
1132        return (Cursor) listView.getAdapter().getItem(index);
1133    }
1134
1135    private void setGroupEntries(AlertDialog.Builder builder) {
1136//        boolean syncEverything;
1137//        // For now we only support a single account and the UI doesn't know what
1138//        // the account name is, so we're using a global setting for SYNC_EVERYTHING.
1139//        // Some day when we add multiple accounts to the UI this should use the per
1140//        // account setting.
1141//        String value = Contacts.Settings.getSetting(getContentResolver(), null,
1142//                Contacts.Settings.SYNC_EVERYTHING);
1143//        if (value == null) {
1144//            // If nothing is set yet we default to syncing everything
1145//            syncEverything = true;
1146//        } else {
1147//            syncEverything = !TextUtils.isEmpty(value) && !"0".equals(value);
1148//        }
1149//
1150//        Cursor cursor;
1151//        if (!syncEverything) {
1152//            cursor = getContentResolver().query(Groups.CONTENT_URI, GROUPS_PROJECTION,
1153//                    Groups.SHOULD_SYNC + " != 0", null, Groups.DEFAULT_SORT_ORDER);
1154//        } else {
1155//            cursor = getContentResolver().query(Groups.CONTENT_URI, GROUPS_PROJECTION,
1156//                    null, null, Groups.DEFAULT_SORT_ORDER);
1157//        }
1158//        try {
1159//            ArrayList<CharSequence> groups = new ArrayList<CharSequence>();
1160//            ArrayList<CharSequence> prefStrings = new ArrayList<CharSequence>();
1161//
1162//            // Add All Contacts
1163//            groups.add(DISPLAY_GROUP_INDEX_ALL_CONTACTS, getString(R.string.showAllGroups));
1164//            prefStrings.add("");
1165//            
1166//            // Add Contacts with phones
1167//            groups.add(DISPLAY_GROUP_INDEX_ALL_CONTACTS_WITH_PHONES,
1168//                    getString(R.string.groupNameWithPhones));
1169//            prefStrings.add(GROUP_WITH_PHONES);
1170//            
1171//            int i = 3;
1172//            int currentIndex = DISPLAY_GROUP_INDEX_ALL_CONTACTS;
1173//            while (cursor.moveToNext()) {
1174//                String systemId = cursor.getString(GROUPS_COLUMN_INDEX_SYSTEM_ID);
1175//                String name = cursor.getString(GROUPS_COLUMN_INDEX_NAME);
1176//                if (cursor.isNull(GROUPS_COLUMN_INDEX_SYSTEM_ID)
1177//                        && !Groups.GROUP_MY_CONTACTS.equals(systemId)) {
1178//                    // All groups that aren't My Contacts, since that one is localized on the phone
1179//                    groups.add(name);
1180//                    if (name.equals(mDisplayInfo)) {
1181//                        currentIndex = i;
1182//                    }
1183//                    i++;
1184//                } else {
1185//                    // The My Contacts group
1186//                    groups.add(DISPLAY_GROUP_INDEX_MY_CONTACTS,
1187//                            getString(R.string.groupNameMyContacts));
1188//                    if (mDisplayType == ContactsPreferenceActivity.DISPLAY_TYPE_SYSTEM_GROUP
1189//                            && Groups.GROUP_MY_CONTACTS.equals(mDisplayInfo)) {
1190//                        currentIndex = DISPLAY_GROUP_INDEX_MY_CONTACTS;
1191//                    }
1192//                    mDisplayGroupsIncludesMyContacts = true;
1193//                }
1194//            }
1195//            if (mMode == MODE_ALL_CONTACTS) {
1196//                currentIndex = DISPLAY_GROUP_INDEX_ALL_CONTACTS;
1197//            } else if (mMode == MODE_WITH_PHONES) {
1198//                currentIndex = DISPLAY_GROUP_INDEX_ALL_CONTACTS_WITH_PHONES;
1199//            }
1200//            mDisplayGroups = groups.toArray(new CharSequence[groups.size()]);
1201//            builder.setSingleChoiceItems(mDisplayGroups,
1202//                    currentIndex, this);
1203//            mDisplayGroupOriginalSelection = currentIndex;
1204//        } finally {
1205//            cursor.close();
1206//        }
1207    }
1208
1209    private final class QueryHandler extends AsyncQueryHandler {
1210        public QueryHandler(Context context) {
1211            super(context.getContentResolver());
1212        }
1213
1214        @Override
1215        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
1216            if (!isFinishing()) {
1217                mAdapter.setLoading(false);
1218                mAdapter.changeCursor(cursor);
1219    
1220                // Now that the cursor is populated again, it's possible to restore the list state
1221                if (mListState != null) {
1222                	getListView().onRestoreInstanceState(mListState);
1223                    if (mListH

Large files files are truncated, but you can click here to view the full file