Changing preferences to PreferenceActivity.
Change-Id: I30f76e94c22828a9516cf2a72a2a772e0b4da44c
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d6b6bf2..334d97f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -301,10 +301,10 @@
/>
</activity-alias>
- <!-- Used to select display and sync groups -->
+ <!-- Used to set options -->
<activity
- android:name=".ui.ContactsPreferencesActivity"
- android:label="@string/displayGroups"
+ android:name=".preference.ContactsPreferenceActivity"
+ android:label="@string/activity_title_settings"
android:theme="@style/ContactsPreferencesTheme" />
<!-- Used to select display and sync groups -->
diff --git a/res/menu/actions.xml b/res/menu/actions.xml
index 282f996..496b138 100644
--- a/res/menu/actions.xml
+++ b/res/menu/actions.xml
@@ -21,9 +21,9 @@
android:showAsAction="always" />
<item
- android:id="@+id/menu_display_groups"
- android:icon="@*android:drawable/ic_menu_allfriends"
- android:title="@string/menu_displayGroup" />
+ android:id="@+id/menu_settings"
+ android:icon="@*android:drawable/ic_menu_preferences"
+ android:title="@string/menu_settings" />
<item
android:id="@+id/menu_accounts"
diff --git a/res/values-xlarge/styles.xml b/res/values-xlarge/styles.xml
index 48923fe..439d68c 100644
--- a/res/values-xlarge/styles.xml
+++ b/res/values-xlarge/styles.xml
@@ -44,8 +44,9 @@
<item name="list_item_photo_size">64dip</item>
</style>
- <style name="ContactsPreferencesTheme" parent="@android:Theme.Dialog">
+ <style name="ContactsPreferencesTheme" parent="@android:Theme.Light.Holo">
</style>
+
<style name="CallDetailActivityTheme" parent="@android:Theme.Dialog">
<item name="android:windowContentOverlay">@null</item>
</style>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0a88e78..fa712e1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -260,12 +260,6 @@
For example, this may be used to set a phone number's label to "Vaction house" -->
<string name="customLabelPickerTitle">Custom label name</string>
- <!-- The menu item to open the list of groups to display -->
- <string name="menu_displayGroup">Display options</string>
-
- <!-- Title of activity that lets user pick which contact groups to display -->
- <string name="displayGroups">Display options</string>
-
<!-- Check box label that allows calls to the contact to be sent directly to voicemail -->
<string name="send_to_voicemail_checkbox">Send calls directly to voicemail</string>
@@ -1329,4 +1323,14 @@
<!-- Title of the activity that allows the user to customize filtering of contact list [CHAR LIMIT=128] -->
<string name="custom_list_filter">Custom contact list</string>
+
+ <!-- Title of the settings activity [CHAR LIMIT=64] -->
+ <string name="activity_title_settings">Settings</string>
+
+ <!-- Menu item for the settings activity [CHAR LIMIT=64] -->
+ <string name="menu_settings">Settings</string>
+
+ <!-- The preference section title for contact display options [CHAR LIMIT=128] -->
+ <string name="preference_displayOptions">Display options</string>
+
</resources>
diff --git a/res/xml/preference_display_options.xml b/res/xml/preference_display_options.xml
new file mode 100644
index 0000000..a662efa
--- /dev/null
+++ b/res/xml/preference_display_options.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <PreferenceCategory
+ android:title="@string/preference_displayOptions">
+ <com.android.contacts.preference.SortOrderPreference
+ android:key="sortOrder"
+ android:title="@string/display_options_sort_list_by"
+ android:dialogTitle="@string/display_options_sort_list_by" />
+
+ <com.android.contacts.preference.DisplayOrderPreference
+ android:key="sortOrder"
+ android:title="@string/display_options_view_names_as"
+ android:dialogTitle="@string/display_options_view_names_as" />
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/res/xml/preference_headers.xml b/res/xml/preference_headers.xml
new file mode 100644
index 0000000..ed709fc
--- /dev/null
+++ b/res/xml/preference_headers.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<preference-headers
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <header
+ android:fragment="com.android.contacts.preference.DisplayOptionsPreferenceFragment"
+ android:title="@string/preference_displayOptions" />
+
+</preference-headers>
diff --git a/src/com/android/contacts/activities/ContactBrowserActivity.java b/src/com/android/contacts/activities/ContactBrowserActivity.java
index dd23455..09e19ff 100644
--- a/src/com/android/contacts/activities/ContactBrowserActivity.java
+++ b/src/com/android/contacts/activities/ContactBrowserActivity.java
@@ -28,7 +28,7 @@
import com.android.contacts.list.DefaultContactBrowseListFragment;
import com.android.contacts.list.OnContactBrowserActionListener;
import com.android.contacts.list.StrequentContactListFragment;
-import com.android.contacts.ui.ContactsPreferencesActivity;
+import com.android.contacts.preference.ContactsPreferenceActivity;
import com.android.contacts.util.DialogManager;
import com.android.contacts.views.ContactSaveService;
import com.android.contacts.views.detail.ContactDetailFragment;
@@ -74,7 +74,7 @@
private static final String KEY_MODE = "mode";
private static final int SUBACTIVITY_NEW_CONTACT = 2;
- private static final int SUBACTIVITY_DISPLAY_GROUP = 3;
+ private static final int SUBACTIVITY_SETTINGS = 3;
private static final int SUBACTIVITY_EDIT_CONTACT = 4;
private DialogManager mDialogManager = new DialogManager(this);
@@ -643,9 +643,9 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.menu_display_groups: {
- final Intent intent = new Intent(this, ContactsPreferencesActivity.class);
- startActivityForResult(intent, SUBACTIVITY_DISPLAY_GROUP);
+ case R.id.menu_settings: {
+ final Intent intent = new Intent(this, ContactsPreferenceActivity.class);
+ startActivityForResult(intent, SUBACTIVITY_SETTINGS);
return true;
}
case R.id.menu_search: {
@@ -741,7 +741,7 @@
break;
}
- case SUBACTIVITY_DISPLAY_GROUP:
+ case SUBACTIVITY_SETTINGS:
// TODO: Force the ListFragment to reload its setting and update (don't lookup
// directories here)
break;
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index 49852a7..7b9142b 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -22,7 +22,7 @@
import com.android.contacts.ContactPhotoLoader;
import com.android.contacts.ContactsSearchManager;
import com.android.contacts.R;
-import com.android.contacts.ui.ContactsPreferences;
+import com.android.contacts.preference.ContactsPreferences;
import com.android.contacts.widget.ContextMenuAdapter;
import android.accounts.Account;
diff --git a/src/com/android/contacts/list/CustomContactListFilterActivity.java b/src/com/android/contacts/list/CustomContactListFilterActivity.java
index b6c6f4c..4cb58af 100644
--- a/src/com/android/contacts/list/CustomContactListFilterActivity.java
+++ b/src/com/android/contacts/list/CustomContactListFilterActivity.java
@@ -22,6 +22,7 @@
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.GoogleSource;
import com.android.contacts.model.Sources;
+import com.android.contacts.preference.ContactsPreferences;
import com.android.contacts.util.EmptyService;
import com.android.contacts.util.LocalizedNameResolver;
import com.android.contacts.util.WeakAsyncTask;
@@ -81,9 +82,6 @@
private static final String TAG = "CustomContactListFilterActivity";
- public static final boolean PREF_DISPLAY_ONLY_PHONES_DEFAULT = false;
- public static final String PREF_DISPLAY_ONLY_PHONES = "only_phones";
-
private ExpandableListView mList;
private DisplayAdapter mAdapter;
@@ -122,8 +120,8 @@
mHeaderPhones = inflater.inflate(R.layout.display_options_phones_only, mList, false);
mHeaderPhones.setId(R.id.header_phones);
mDisplayPhones = (CheckBox) mHeaderPhones.findViewById(android.R.id.checkbox);
- mDisplayPhones.setChecked(
- mPrefs.getBoolean(PREF_DISPLAY_ONLY_PHONES, PREF_DISPLAY_ONLY_PHONES_DEFAULT));
+ mDisplayPhones.setChecked(mPrefs.getBoolean(ContactsPreferences.PREF_DISPLAY_ONLY_PHONES,
+ ContactsPreferences.PREF_DISPLAY_ONLY_PHONES_DEFAULT));
{
final TextView text1 = (TextView)mHeaderPhones.findViewById(android.R.id.text1);
final TextView text2 = (TextView)mHeaderPhones.findViewById(android.R.id.text2);
@@ -681,14 +679,14 @@
}
/**
- * Assign a specific value to {@link #PREF_DISPLAY_ONLY_PHONES}, refreshing
+ * Assign a specific value to {@link ContactsPreferences#PREF_DISPLAY_ONLY_PHONES}, refreshing
* the visible list as needed.
*/
protected void setDisplayOnlyPhones(boolean displayOnlyPhones) {
mDisplayPhones.setChecked(displayOnlyPhones);
Editor editor = mPrefs.edit();
- editor.putBoolean(PREF_DISPLAY_ONLY_PHONES, displayOnlyPhones);
+ editor.putBoolean(ContactsPreferences.PREF_DISPLAY_ONLY_PHONES, displayOnlyPhones);
editor.apply();
mAdapter.setChildDescripWithPhones(displayOnlyPhones);
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 9f6fec0..0cc8901 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -16,7 +16,7 @@
package com.android.contacts.list;
import com.android.contacts.R;
-import com.android.contacts.ui.ContactsPreferencesActivity.Prefs;
+import com.android.contacts.preference.ContactsPreferences;
import com.android.contacts.widget.NotifyingSpinner;
import android.app.Activity;
@@ -134,8 +134,8 @@
case ContactsRequest.DISPLAY_ONLY_WITH_PHONES_PREFERENCE:
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getContext());
- return prefs.getBoolean(Prefs.DISPLAY_ONLY_PHONES,
- Prefs.DISPLAY_ONLY_PHONES_DEFAULT);
+ return prefs.getBoolean(ContactsPreferences.PREF_DISPLAY_ONLY_PHONES,
+ ContactsPreferences.PREF_DISPLAY_ONLY_PHONES_DEFAULT);
}
return false;
}
diff --git a/src/com/android/contacts/preference/ContactsPreferenceActivity.java b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
new file mode 100644
index 0000000..0828abe
--- /dev/null
+++ b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
@@ -0,0 +1,1100 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.preference;
+
+import com.android.contacts.ContactsSearchManager;
+import com.android.contacts.R;
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.model.GoogleSource;
+import com.android.contacts.model.Sources;
+import com.android.contacts.util.EmptyService;
+import com.android.contacts.util.LocalizedNameResolver;
+import com.android.contacts.util.WeakAsyncTask;
+import com.google.android.collect.Lists;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ExpandableListActivity;
+import android.app.ProgressDialog;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderOperation.Builder;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.EntityIterator;
+import android.content.Intent;
+import android.content.OperationApplicationException;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceActivity.Header;
+import android.preference.PreferenceManager;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Groups;
+import android.provider.ContactsContract.Settings;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.CheckBox;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Contacts settings.
+ */
+public final class ContactsPreferenceActivity extends PreferenceActivity
+//implements
+// AdapterView.OnItemClickListener, View.OnClickListener
+ {
+ private static final String TAG = "ContactsSettingsActivity";
+
+ /**
+ * Populate the activity with the top-level headers.
+ */
+ @Override
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.preference_headers, target);
+ }
+
+
+// public interface Prefs {
+// public static final String DISPLAY_ONLY_PHONES = "only_phones";
+// public static final boolean DISPLAY_ONLY_PHONES_DEFAULT = false;
+//
+// }
+//
+// private static final int DIALOG_SORT_ORDER = 1;
+// private static final int DIALOG_DISPLAY_ORDER = 2;
+//
+// private ExpandableListView mList;
+// private DisplayAdapter mAdapter;
+//
+// private SharedPreferences mPrefs;
+// private ContactsPreferences mContactsPrefs;
+//
+// private CheckBox mDisplayPhones;
+//
+// private View mHeaderPhones;
+// private View mHeaderSeparator;
+//
+// private View mSortOrderView;
+// private TextView mSortOrderTextView;
+// private int mSortOrder;
+//
+// private View mDisplayOrderView;
+// private TextView mDisplayOrderTextView;
+// private int mDisplayOrder;
+//
+// @Override
+// protected void onCreate(Bundle icicle) {
+// super.onCreate(icicle);
+// setContentView(R.layout.contacts_preferences);
+//
+// mList = getExpandableListView();
+// mList.setHeaderDividersEnabled(true);
+// mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+// mContactsPrefs = new ContactsPreferences(this);
+// mAdapter = new DisplayAdapter(this);
+//
+// final LayoutInflater inflater = getLayoutInflater();
+//
+// createWithPhonesOnlyPreferenceView(inflater);
+// createSortOrderPreferenceView(inflater);
+// createDisplayOrderPreferenceView(inflater);
+// createDisplayGroupHeader(inflater);
+//
+// findViewById(R.id.btn_done).setOnClickListener(this);
+// findViewById(R.id.btn_discard).setOnClickListener(this);
+//
+// // Catch clicks on the header views
+// mList.setOnItemClickListener(this);
+// mList.setOnCreateContextMenuListener(this);
+//
+// mSortOrder = mContactsPrefs.getSortOrder();
+// mDisplayOrder = mContactsPrefs.getDisplayOrder();
+// }
+//
+// private void createWithPhonesOnlyPreferenceView(LayoutInflater inflater) {
+// // Add the "Only contacts with phones" header modifier.
+// mHeaderPhones = inflater.inflate(R.layout.display_options_phones_only, mList, false);
+// mHeaderPhones.setId(R.id.header_phones);
+// mDisplayPhones = (CheckBox) mHeaderPhones.findViewById(android.R.id.checkbox);
+// mDisplayPhones.setChecked(mPrefs.getBoolean(Prefs.DISPLAY_ONLY_PHONES,
+// Prefs.DISPLAY_ONLY_PHONES_DEFAULT));
+// {
+// final TextView text1 = (TextView)mHeaderPhones.findViewById(android.R.id.text1);
+// final TextView text2 = (TextView)mHeaderPhones.findViewById(android.R.id.text2);
+// text1.setText(R.string.showFilterPhones);
+// text2.setText(R.string.showFilterPhonesDescrip);
+// }
+// }
+//
+// private void createSortOrderPreferenceView(LayoutInflater inflater) {
+// mSortOrderView = inflater.inflate(R.layout.preference_with_more_button, mList, false);
+//
+// View preferenceLayout = mSortOrderView.findViewById(R.id.preference);
+//
+// TextView label = (TextView)preferenceLayout.findViewById(R.id.label);
+// label.setText(getString(R.string.display_options_sort_list_by));
+//
+// mSortOrderTextView = (TextView)preferenceLayout.findViewById(R.id.data);
+// }
+//
+// private void createDisplayOrderPreferenceView(LayoutInflater inflater) {
+// mDisplayOrderView = inflater.inflate(R.layout.preference_with_more_button, mList, false);
+// View preferenceLayout = mDisplayOrderView.findViewById(R.id.preference);
+//
+// TextView label = (TextView)preferenceLayout.findViewById(R.id.label);
+// label.setText(getString(R.string.display_options_view_names_as));
+//
+// mDisplayOrderTextView = (TextView)preferenceLayout.findViewById(R.id.data);
+// }
+//
+// private void createDisplayGroupHeader(LayoutInflater inflater) {
+// // Add the separator before showing the detailed group list.
+// mHeaderSeparator = inflater.inflate(R.layout.list_separator, mList, false);
+// {
+// final TextView text1 = (TextView)mHeaderSeparator;
+// text1.setText(R.string.headerContactGroups);
+// }
+// }
+//
+// @Override
+// protected void onResume() {
+// super.onResume();
+// mList.removeHeaderView(mHeaderPhones);
+// mList.removeHeaderView(mSortOrderView);
+// mList.removeHeaderView(mDisplayOrderView);
+// mList.removeHeaderView(mHeaderSeparator);
+//
+// // List adapter needs to be reset, because header views cannot be added
+// // to a list with an existing adapter.
+// setListAdapter(null);
+//
+// mList.addHeaderView(mHeaderPhones, null, true);
+// if (mContactsPrefs.isSortOrderUserChangeable()) {
+// mList.addHeaderView(mSortOrderView, null, true);
+// }
+//
+// if (mContactsPrefs.isSortOrderUserChangeable()) {
+// mList.addHeaderView(mDisplayOrderView, null, true);
+// }
+//
+// mList.addHeaderView(mHeaderSeparator, null, false);
+//
+// setListAdapter(mAdapter);
+//
+// bindView();
+//
+// // Start background query to find account details
+// new QueryGroupsTask(this).execute();
+// }
+//
+// private void bindView() {
+// mSortOrderTextView.setText(
+// mSortOrder == ContactsContract.Preferences.SORT_ORDER_PRIMARY
+// ? getString(R.string.display_options_sort_by_given_name)
+// : getString(R.string.display_options_sort_by_family_name));
+//
+// mDisplayOrderTextView.setText(
+// mDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY
+// ? getString(R.string.display_options_view_given_name_first)
+// : getString(R.string.display_options_view_family_name_first));
+// }
+//
+// @Override
+// protected Dialog onCreateDialog(int id, Bundle args) {
+// switch (id) {
+// case DIALOG_SORT_ORDER:
+// return createSortOrderDialog();
+// case DIALOG_DISPLAY_ORDER:
+// return createDisplayOrderDialog();
+// }
+//
+// return null;
+// }
+//
+// private Dialog createSortOrderDialog() {
+// String[] items = new String[] {
+// getString(R.string.display_options_sort_by_given_name),
+// getString(R.string.display_options_sort_by_family_name),
+// };
+//
+// return new AlertDialog.Builder(this)
+// .setIcon(com.android.internal.R.drawable.ic_dialog_menu_generic)
+// .setTitle(R.string.display_options_sort_list_by)
+// .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
+// public void onClick(DialogInterface dialog, int whichButton) {
+// setSortOrder(dialog);
+// dialog.dismiss();
+// }
+// })
+// .setNegativeButton(android.R.string.cancel, null)
+// .create();
+// }
+//
+// private Dialog createDisplayOrderDialog() {
+// String[] items = new String[] {
+// getString(R.string.display_options_view_given_name_first),
+// getString(R.string.display_options_view_family_name_first),
+// };
+//
+// return new AlertDialog.Builder(this)
+// .setIcon(com.android.internal.R.drawable.ic_dialog_menu_generic)
+// .setTitle(R.string.display_options_view_names_as)
+// .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
+// public void onClick(DialogInterface dialog, int whichButton) {
+// setDisplayOrder(dialog);
+// dialog.dismiss();
+// }
+// })
+// .setNegativeButton(android.R.string.cancel, null)
+// .create();
+// }
+//
+// @Override
+// protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+// switch (id) {
+// case DIALOG_SORT_ORDER:
+// setCheckedItem(dialog,
+// mSortOrder == ContactsContract.Preferences.SORT_ORDER_PRIMARY ? 0 : 1);
+// break;
+// case DIALOG_DISPLAY_ORDER:
+// setCheckedItem(dialog,
+// mDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY
+// ? 0 : 1);
+// break;
+// }
+// }
+//
+// private void setCheckedItem(Dialog dialog, int position) {
+// ListView listView = ((AlertDialog)dialog).getListView();
+// listView.setItemChecked(position, true);
+// listView.setSelection(position);
+// }
+//
+// protected void setSortOrder(DialogInterface dialog) {
+// ListView listView = ((AlertDialog)dialog).getListView();
+// int checked = listView.getCheckedItemPosition();
+// mSortOrder = checked == 0
+// ? ContactsContract.Preferences.SORT_ORDER_PRIMARY
+// : ContactsContract.Preferences.SORT_ORDER_ALTERNATIVE;
+//
+// bindView();
+// }
+//
+// protected void setDisplayOrder(DialogInterface dialog) {
+// ListView listView = ((AlertDialog)dialog).getListView();
+// int checked = listView.getCheckedItemPosition();
+// mDisplayOrder = checked == 0
+// ? ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY
+// : ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE;
+//
+// bindView();
+// }
+//
+// /**
+// * Background operation to build set of {@link AccountDisplay} for each
+// * {@link Sources#getAccounts(boolean)} that provides groups.
+// */
+// private static class QueryGroupsTask extends
+// WeakAsyncTask<Void, Void, AccountSet, ContactsPreferenceActivity> {
+// public QueryGroupsTask(ContactsPreferenceActivity target) {
+// super(target);
+// }
+//
+// @Override
+// protected AccountSet doInBackground(ContactsPreferenceActivity target,
+// Void... params) {
+// final Context context = target;
+// final Sources sources = Sources.getInstance(context);
+// final ContentResolver resolver = context.getContentResolver();
+//
+// // Inflate groups entry for each account
+// final AccountSet accounts = new AccountSet();
+// for (Account account : sources.getAccounts(false)) {
+// accounts.add(new AccountDisplay(resolver, account.name, account.type));
+// }
+//
+// return accounts;
+// }
+//
+// @Override
+// protected void onPostExecute(ContactsPreferenceActivity target, AccountSet result) {
+// target.mAdapter.setAccounts(result);
+// }
+// }
+//
+// private static final int DEFAULT_SHOULD_SYNC = 1;
+// private static final int DEFAULT_VISIBLE = 0;
+//
+// /**
+// * Entry holding any changes to {@link Groups} or {@link Settings} rows,
+// * such as {@link Groups#SHOULD_SYNC} or {@link Groups#GROUP_VISIBLE}.
+// */
+// protected static class GroupDelta extends ValuesDelta {
+// private boolean mUngrouped = false;
+// private boolean mAccountHasGroups;
+//
+// private GroupDelta() {
+// super();
+// }
+//
+// /**
+// * Build {@link GroupDelta} from the {@link Settings} row for the given
+// * {@link Settings#ACCOUNT_NAME} and {@link Settings#ACCOUNT_TYPE}.
+// */
+// public static GroupDelta fromSettings(ContentResolver resolver, String accountName,
+// String accountType, boolean accountHasGroups) {
+// final Uri settingsUri = Settings.CONTENT_URI.buildUpon()
+// .appendQueryParameter(Settings.ACCOUNT_NAME, accountName)
+// .appendQueryParameter(Settings.ACCOUNT_TYPE, accountType).build();
+// final Cursor cursor = resolver.query(settingsUri, new String[] {
+// Settings.SHOULD_SYNC, Settings.UNGROUPED_VISIBLE
+// }, null, null, null);
+//
+// try {
+// final ContentValues values = new ContentValues();
+// values.put(Settings.ACCOUNT_NAME, accountName);
+// values.put(Settings.ACCOUNT_TYPE, accountType);
+//
+// if (cursor != null && cursor.moveToFirst()) {
+// // Read existing values when present
+// values.put(Settings.SHOULD_SYNC, cursor.getInt(0));
+// values.put(Settings.UNGROUPED_VISIBLE, cursor.getInt(1));
+// return fromBefore(values).setUngrouped(accountHasGroups);
+// } else {
+// // Nothing found, so treat as create
+// values.put(Settings.SHOULD_SYNC, DEFAULT_SHOULD_SYNC);
+// values.put(Settings.UNGROUPED_VISIBLE, DEFAULT_VISIBLE);
+// return fromAfter(values).setUngrouped(accountHasGroups);
+// }
+// } finally {
+// if (cursor != null) cursor.close();
+// }
+// }
+//
+// public static GroupDelta fromBefore(ContentValues before) {
+// final GroupDelta entry = new GroupDelta();
+// entry.mBefore = before;
+// entry.mAfter = new ContentValues();
+// return entry;
+// }
+//
+// public static GroupDelta fromAfter(ContentValues after) {
+// final GroupDelta entry = new GroupDelta();
+// entry.mBefore = null;
+// entry.mAfter = after;
+// return entry;
+// }
+//
+// protected GroupDelta setUngrouped(boolean accountHasGroups) {
+// mUngrouped = true;
+// mAccountHasGroups = accountHasGroups;
+// return this;
+// }
+//
+// @Override
+// public boolean beforeExists() {
+// return mBefore != null;
+// }
+//
+// public boolean getShouldSync() {
+// return getAsInteger(mUngrouped ? Settings.SHOULD_SYNC : Groups.SHOULD_SYNC,
+// DEFAULT_SHOULD_SYNC) != 0;
+// }
+//
+// public boolean getVisible() {
+// return getAsInteger(mUngrouped ? Settings.UNGROUPED_VISIBLE : Groups.GROUP_VISIBLE,
+// DEFAULT_VISIBLE) != 0;
+// }
+//
+// public void putShouldSync(boolean shouldSync) {
+// put(mUngrouped ? Settings.SHOULD_SYNC : Groups.SHOULD_SYNC, shouldSync ? 1 : 0);
+// }
+//
+// public void putVisible(boolean visible) {
+// put(mUngrouped ? Settings.UNGROUPED_VISIBLE : Groups.GROUP_VISIBLE, visible ? 1 : 0);
+// }
+//
+// private String getAccountType() {
+// return (mBefore == null ? mAfter : mBefore).getAsString(Settings.ACCOUNT_TYPE);
+// }
+//
+// public CharSequence getTitle(Context context) {
+// if (mUngrouped) {
+// final String customAllContactsName =
+// LocalizedNameResolver.getAllContactsName(context, getAccountType());
+// if (customAllContactsName != null) {
+// return customAllContactsName;
+// }
+// if (mAccountHasGroups) {
+// return context.getText(R.string.display_ungrouped);
+// } else {
+// return context.getText(R.string.display_all_contacts);
+// }
+// } else {
+// final Integer titleRes = getAsInteger(Groups.TITLE_RES);
+// if (titleRes != null) {
+// final String packageName = getAsString(Groups.RES_PACKAGE);
+// return context.getPackageManager().getText(packageName, titleRes, null);
+// } else {
+// return getAsString(Groups.TITLE);
+// }
+// }
+// }
+//
+// /**
+// * Build a possible {@link ContentProviderOperation} to persist any
+// * changes to the {@link Groups} or {@link Settings} row described by
+// * this {@link GroupDelta}.
+// */
+// public ContentProviderOperation buildDiff() {
+// if (isNoop()) {
+// return null;
+// } else if (isUpdate()) {
+// // When has changes and "before" exists, then "update"
+// final Builder builder = ContentProviderOperation
+// .newUpdate(mUngrouped ? Settings.CONTENT_URI : addCallerIsSyncAdapterParameter(Groups.CONTENT_URI));
+// if (mUngrouped) {
+// builder.withSelection(Settings.ACCOUNT_NAME + "=? AND " + Settings.ACCOUNT_TYPE
+// + "=?", new String[] {
+// this.getAsString(Settings.ACCOUNT_NAME),
+// this.getAsString(Settings.ACCOUNT_TYPE)
+// });
+// } else {
+// builder.withSelection(Groups._ID + "=" + this.getId(), null);
+// }
+// builder.withValues(mAfter);
+// return builder.build();
+// } else if (isInsert() && mUngrouped) {
+// // Only allow inserts for Settings
+// mAfter.remove(mIdColumn);
+// final Builder builder = ContentProviderOperation.newInsert(Settings.CONTENT_URI);
+// builder.withValues(mAfter);
+// return builder.build();
+// } else {
+// throw new IllegalStateException("Unexpected delete or insert");
+// }
+// }
+// }
+//
+// private static Uri addCallerIsSyncAdapterParameter(Uri uri) {
+// return uri.buildUpon()
+// .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
+// .build();
+// }
+//
+// /**
+// * {@link Comparator} to sort by {@link Groups#_ID}.
+// */
+// private static Comparator<GroupDelta> sIdComparator = new Comparator<GroupDelta>() {
+// public int compare(GroupDelta object1, GroupDelta object2) {
+// final Long id1 = object1.getId();
+// final Long id2 = object2.getId();
+// if (id1 == null && id2 == null) {
+// return 0;
+// } else if (id1 == null) {
+// return -1;
+// } else if (id2 == null) {
+// return 1;
+// } else if (id1 < id2) {
+// return -1;
+// } else if (id1 > id2) {
+// return 1;
+// } else {
+// return 0;
+// }
+// }
+// };
+//
+// /**
+// * Set of all {@link AccountDisplay} entries, one for each source.
+// */
+// protected static class AccountSet extends ArrayList<AccountDisplay> {
+// public ArrayList<ContentProviderOperation> buildDiff() {
+// final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
+// for (AccountDisplay account : this) {
+// account.buildDiff(diff);
+// }
+// return diff;
+// }
+// }
+//
+// /**
+// * {@link GroupDelta} details for a single {@link Account}, usually shown as
+// * children under a single expandable group.
+// */
+// protected static class AccountDisplay {
+// public String mName;
+// public String mType;
+//
+// public GroupDelta mUngrouped;
+// public ArrayList<GroupDelta> mSyncedGroups = Lists.newArrayList();
+// public ArrayList<GroupDelta> mUnsyncedGroups = Lists.newArrayList();
+//
+// /**
+// * Build an {@link AccountDisplay} covering all {@link Groups} under the
+// * given {@link Account}.
+// */
+// public AccountDisplay(ContentResolver resolver, String accountName, String accountType) {
+// mName = accountName;
+// mType = accountType;
+//
+// final Uri groupsUri = Groups.CONTENT_URI.buildUpon()
+// .appendQueryParameter(Groups.ACCOUNT_NAME, accountName)
+// .appendQueryParameter(Groups.ACCOUNT_TYPE, accountType).build();
+// EntityIterator iterator = ContactsContract.Groups.newEntityIterator(resolver.query(
+// groupsUri, null, null, null, null));
+// try {
+// boolean hasGroups = false;
+//
+// // Create entries for each known group
+// while (iterator.hasNext()) {
+// final ContentValues values = iterator.next().getEntityValues();
+// final GroupDelta group = GroupDelta.fromBefore(values);
+// addGroup(group);
+// hasGroups = true;
+// }
+// // Create single entry handling ungrouped status
+// mUngrouped = GroupDelta.fromSettings(resolver, accountName, accountType, hasGroups);
+// addGroup(mUngrouped);
+// } finally {
+// iterator.close();
+// }
+// }
+//
+// /**
+// * Add the given {@link GroupDelta} internally, filing based on its
+// * {@link GroupDelta#getShouldSync()} status.
+// */
+// private void addGroup(GroupDelta group) {
+// if (group.getShouldSync()) {
+// mSyncedGroups.add(group);
+// } else {
+// mUnsyncedGroups.add(group);
+// }
+// }
+//
+// /**
+// * Set the {@link GroupDelta#putShouldSync(boolean)} value for all
+// * children {@link GroupDelta} rows.
+// */
+// public void setShouldSync(boolean shouldSync) {
+// final Iterator<GroupDelta> oppositeChildren = shouldSync ?
+// mUnsyncedGroups.iterator() : mSyncedGroups.iterator();
+// while (oppositeChildren.hasNext()) {
+// final GroupDelta child = oppositeChildren.next();
+// setShouldSync(child, shouldSync, false);
+// oppositeChildren.remove();
+// }
+// }
+//
+// public void setShouldSync(GroupDelta child, boolean shouldSync) {
+// setShouldSync(child, shouldSync, true);
+// }
+//
+// /**
+// * Set {@link GroupDelta#putShouldSync(boolean)}, and file internally
+// * based on updated state.
+// */
+// public void setShouldSync(GroupDelta child, boolean shouldSync, boolean attemptRemove) {
+// child.putShouldSync(shouldSync);
+// if (shouldSync) {
+// if (attemptRemove) {
+// mUnsyncedGroups.remove(child);
+// }
+// mSyncedGroups.add(child);
+// Collections.sort(mSyncedGroups, sIdComparator);
+// } else {
+// if (attemptRemove) {
+// mSyncedGroups.remove(child);
+// }
+// mUnsyncedGroups.add(child);
+// }
+// }
+//
+// /**
+// * Build set of {@link ContentProviderOperation} to persist any user
+// * changes to {@link GroupDelta} rows under this {@link Account}.
+// */
+// public void buildDiff(ArrayList<ContentProviderOperation> diff) {
+// for (GroupDelta group : mSyncedGroups) {
+// final ContentProviderOperation oper = group.buildDiff();
+// if (oper != null) diff.add(oper);
+// }
+// for (GroupDelta group : mUnsyncedGroups) {
+// final ContentProviderOperation oper = group.buildDiff();
+// if (oper != null) diff.add(oper);
+// }
+// }
+// }
+//
+// /**
+// * {@link ExpandableListAdapter} that shows {@link GroupDelta} settings,
+// * grouped by {@link Account} source. Shows footer row when any groups are
+// * unsynced, as determined through {@link AccountDisplay#mUnsyncedGroups}.
+// */
+// protected static class DisplayAdapter extends BaseExpandableListAdapter {
+// private Context mContext;
+// private LayoutInflater mInflater;
+// private Sources mSources;
+// private AccountSet mAccounts;
+//
+// private boolean mChildWithPhones = false;
+//
+// public DisplayAdapter(Context context) {
+// mContext = context;
+// mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+// mSources = Sources.getInstance(context);
+// }
+//
+// public void setAccounts(AccountSet accounts) {
+// mAccounts = accounts;
+// notifyDataSetChanged();
+// }
+//
+// /**
+// * In group descriptions, show the number of contacts with phone
+// * numbers, in addition to the total contacts.
+// */
+// public void setChildDescripWithPhones(boolean withPhones) {
+// mChildWithPhones = withPhones;
+// }
+//
+// /** {@inheritDoc} */
+// public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+// View convertView, ViewGroup parent) {
+// if (convertView == null) {
+// convertView = mInflater.inflate(R.layout.display_child, parent, false);
+// }
+//
+// final TextView text1 = (TextView)convertView.findViewById(android.R.id.text1);
+// final TextView text2 = (TextView)convertView.findViewById(android.R.id.text2);
+// final CheckBox checkbox = (CheckBox)convertView.findViewById(android.R.id.checkbox);
+//
+// final AccountDisplay account = mAccounts.get(groupPosition);
+// final GroupDelta child = (GroupDelta)this.getChild(groupPosition, childPosition);
+// if (child != null) {
+// // Handle normal group, with title and checkbox
+// final boolean groupVisible = child.getVisible();
+// checkbox.setVisibility(View.VISIBLE);
+// checkbox.setChecked(groupVisible);
+//
+// final CharSequence groupTitle = child.getTitle(mContext);
+// text1.setText(groupTitle);
+//
+//// final int count = cursor.getInt(GroupsQuery.SUMMARY_COUNT);
+//// final int withPhones = cursor.getInt(GroupsQuery.SUMMARY_WITH_PHONES);
+//
+//// final CharSequence descrip = mContext.getResources().getQuantityString(
+//// mChildWithPhones ? R.plurals.groupDescripPhones : R.plurals.groupDescrip,
+//// count, count, withPhones);
+//
+//// text2.setText(descrip);
+// text2.setVisibility(View.GONE);
+// } else {
+// // When unknown child, this is "more" footer view
+// checkbox.setVisibility(View.GONE);
+// text1.setText(R.string.display_more_groups);
+// text2.setVisibility(View.GONE);
+// }
+//
+// return convertView;
+// }
+//
+// /** {@inheritDoc} */
+// public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+// ViewGroup parent) {
+// if (convertView == null) {
+// convertView = mInflater.inflate(R.layout.display_group, parent, false);
+// }
+//
+// final TextView text1 = (TextView)convertView.findViewById(android.R.id.text1);
+// final TextView text2 = (TextView)convertView.findViewById(android.R.id.text2);
+//
+// final AccountDisplay account = (AccountDisplay)this.getGroup(groupPosition);
+//
+// final ContactsSource source = mSources.getInflatedSource(account.mType,
+// ContactsSource.LEVEL_SUMMARY);
+//
+// text1.setText(account.mName);
+// text2.setText(source.getDisplayLabel(mContext));
+// text2.setVisibility(account.mName == null ? View.GONE : View.VISIBLE);
+//
+// return convertView;
+// }
+//
+// /** {@inheritDoc} */
+// public Object getChild(int groupPosition, int childPosition) {
+// final AccountDisplay account = mAccounts.get(groupPosition);
+// final boolean validChild = childPosition >= 0
+// && childPosition < account.mSyncedGroups.size();
+// if (validChild) {
+// return account.mSyncedGroups.get(childPosition);
+// } else {
+// return null;
+// }
+// }
+//
+// /** {@inheritDoc} */
+// public long getChildId(int groupPosition, int childPosition) {
+// final GroupDelta child = (GroupDelta)getChild(groupPosition, childPosition);
+// if (child != null) {
+// final Long childId = child.getId();
+// return childId != null ? childId : Long.MIN_VALUE;
+// } else {
+// return Long.MIN_VALUE;
+// }
+// }
+//
+// /** {@inheritDoc} */
+// public int getChildrenCount(int groupPosition) {
+// // Count is any synced groups, plus possible footer
+// final AccountDisplay account = mAccounts.get(groupPosition);
+// final boolean anyHidden = account.mUnsyncedGroups.size() > 0;
+// return account.mSyncedGroups.size() + (anyHidden ? 1 : 0);
+// }
+//
+// /** {@inheritDoc} */
+// public Object getGroup(int groupPosition) {
+// return mAccounts.get(groupPosition);
+// }
+//
+// /** {@inheritDoc} */
+// public int getGroupCount() {
+// if (mAccounts == null) {
+// return 0;
+// }
+// return mAccounts.size();
+// }
+//
+// /** {@inheritDoc} */
+// public long getGroupId(int groupPosition) {
+// return groupPosition;
+// }
+//
+// /** {@inheritDoc} */
+// public boolean hasStableIds() {
+// return true;
+// }
+//
+// /** {@inheritDoc} */
+// public boolean isChildSelectable(int groupPosition, int childPosition) {
+// return true;
+// }
+// }
+//
+// /**
+// * Handle any clicks on header views added to our {@link #mAdapter}, which
+// * are usually the global modifier checkboxes.
+// */
+// public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+// Log.d(TAG, "OnItemClick, position=" + position + ", id=" + id);
+// if (view == mHeaderPhones) {
+// mDisplayPhones.toggle();
+// return;
+// }
+// if (view == mDisplayOrderView) {
+// Log.d(TAG, "Showing Display Order dialog");
+// showDialog(DIALOG_DISPLAY_ORDER);
+// return;
+// }
+// if (view == mSortOrderView) {
+// Log.d(TAG, "Showing Sort Order dialog");
+// showDialog(DIALOG_SORT_ORDER);
+// return;
+// }
+// }
+//
+// /** {@inheritDoc} */
+// public void onClick(View view) {
+// switch (view.getId()) {
+// case R.id.btn_done: {
+// this.doSaveAction();
+// break;
+// }
+// case R.id.btn_discard: {
+// this.finish();
+// break;
+// }
+// }
+// }
+//
+// /**
+// * Assign a specific value to {@link Prefs#DISPLAY_ONLY_PHONES}, refreshing
+// * the visible list as needed.
+// */
+// protected void setDisplayOnlyPhones(boolean displayOnlyPhones) {
+// mDisplayPhones.setChecked(displayOnlyPhones);
+//
+// Editor editor = mPrefs.edit();
+// editor.putBoolean(Prefs.DISPLAY_ONLY_PHONES, displayOnlyPhones);
+// editor.apply();
+//
+// mAdapter.setChildDescripWithPhones(displayOnlyPhones);
+// mAdapter.notifyDataSetChanged();
+// }
+//
+// /**
+// * Handle any clicks on {@link ExpandableListAdapter} children, which
+// * usually mean toggling its visible state.
+// */
+// @Override
+// public boolean onChildClick(ExpandableListView parent, View view, int groupPosition,
+// int childPosition, long id) {
+// final CheckBox checkbox = (CheckBox)view.findViewById(android.R.id.checkbox);
+//
+// final AccountDisplay account = (AccountDisplay)mAdapter.getGroup(groupPosition);
+// final GroupDelta child = (GroupDelta)mAdapter.getChild(groupPosition, childPosition);
+// if (child != null) {
+// checkbox.toggle();
+// child.putVisible(checkbox.isChecked());
+// } else {
+// // Open context menu for bringing back unsynced
+// this.openContextMenu(view);
+// }
+// return true;
+// }
+//
+// // TODO: move these definitions to framework constants when we begin
+// // defining this mode through <sync-adapter> tags
+// private static final int SYNC_MODE_UNSUPPORTED = 0;
+// private static final int SYNC_MODE_UNGROUPED = 1;
+// private static final int SYNC_MODE_EVERYTHING = 2;
+//
+// protected int getSyncMode(AccountDisplay account) {
+// // TODO: read sync mode through <sync-adapter> definition
+// if (GoogleSource.ACCOUNT_TYPE.equals(account.mType)) {
+// return SYNC_MODE_EVERYTHING;
+// } else {
+// return SYNC_MODE_UNSUPPORTED;
+// }
+// }
+//
+// @Override
+// public void onCreateContextMenu(ContextMenu menu, View view,
+// ContextMenu.ContextMenuInfo menuInfo) {
+// super.onCreateContextMenu(menu, view, menuInfo);
+//
+// // Bail if not working with expandable long-press, or if not child
+// if (!(menuInfo instanceof ExpandableListContextMenuInfo)) return;
+//
+// final ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuInfo;
+// final int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
+// final int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
+//
+// // Skip long-press on expandable parents
+// if (childPosition == -1) return;
+//
+// final AccountDisplay account = (AccountDisplay)mAdapter.getGroup(groupPosition);
+// final GroupDelta child = (GroupDelta)mAdapter.getChild(groupPosition, childPosition);
+//
+// // Ignore when selective syncing unsupported
+// final int syncMode = getSyncMode(account);
+// if (syncMode == SYNC_MODE_UNSUPPORTED) return;
+//
+// if (child != null) {
+// showRemoveSync(menu, account, child, syncMode);
+// } else {
+// showAddSync(menu, account, syncMode);
+// }
+// }
+//
+// protected void showRemoveSync(ContextMenu menu, final AccountDisplay account,
+// final GroupDelta child, final int syncMode) {
+// final CharSequence title = child.getTitle(this);
+//
+// menu.setHeaderTitle(title);
+// menu.add(R.string.menu_sync_remove).setOnMenuItemClickListener(
+// new OnMenuItemClickListener() {
+// public boolean onMenuItemClick(MenuItem item) {
+// handleRemoveSync(account, child, syncMode, title);
+// return true;
+// }
+// });
+// }
+//
+// protected void handleRemoveSync(final AccountDisplay account, final GroupDelta child,
+// final int syncMode, CharSequence title) {
+// final boolean shouldSyncUngrouped = account.mUngrouped.getShouldSync();
+// if (syncMode == SYNC_MODE_EVERYTHING && shouldSyncUngrouped
+// && !child.equals(account.mUngrouped)) {
+// // Warn before removing this group when it would cause ungrouped to stop syncing
+// final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+// final CharSequence removeMessage = this.getString(
+// R.string.display_warn_remove_ungrouped, title);
+// builder.setTitle(R.string.menu_sync_remove);
+// builder.setMessage(removeMessage);
+// builder.setNegativeButton(android.R.string.cancel, null);
+// builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+// public void onClick(DialogInterface dialog, int which) {
+// // Mark both this group and ungrouped to stop syncing
+// account.setShouldSync(account.mUngrouped, false);
+// account.setShouldSync(child, false);
+// mAdapter.notifyDataSetChanged();
+// }
+// });
+// builder.show();
+// } else {
+// // Mark this group to not sync
+// account.setShouldSync(child, false);
+// mAdapter.notifyDataSetChanged();
+// }
+// }
+//
+// protected void showAddSync(ContextMenu menu, final AccountDisplay account, final int syncMode) {
+// menu.setHeaderTitle(R.string.dialog_sync_add);
+//
+// // Create item for each available, unsynced group
+// for (final GroupDelta child : account.mUnsyncedGroups) {
+// if (!child.getShouldSync()) {
+// final CharSequence title = child.getTitle(this);
+// menu.add(title).setOnMenuItemClickListener(new OnMenuItemClickListener() {
+// public boolean onMenuItemClick(MenuItem item) {
+// // Adding specific group for syncing
+// if (child.mUngrouped && syncMode == SYNC_MODE_EVERYTHING) {
+// account.setShouldSync(true);
+// } else {
+// account.setShouldSync(child, true);
+// }
+// mAdapter.notifyDataSetChanged();
+// return true;
+// }
+// });
+// }
+// }
+// }
+//
+// /** {@inheritDoc} */
+// @Override
+// public void onBackPressed() {
+// doSaveAction();
+// }
+//
+// private void doSaveAction() {
+// mContactsPrefs.setSortOrder(mSortOrder);
+// mContactsPrefs.setDisplayOrder(mDisplayOrder);
+//
+// if (mAdapter == null || mAdapter.mAccounts == null) {
+// return;
+// }
+// setDisplayOnlyPhones(mDisplayPhones.isChecked());
+// new UpdateTask(this).execute(mAdapter.mAccounts);
+// }
+//
+// /**
+// * Background task that persists changes to {@link Groups#GROUP_VISIBLE},
+// * showing spinner dialog to user while updating.
+// */
+// public static class UpdateTask extends
+// WeakAsyncTask<AccountSet, Void, Void, Activity> {
+// private WeakReference<ProgressDialog> mProgress;
+//
+// public UpdateTask(Activity target) {
+// super(target);
+// }
+//
+// /** {@inheritDoc} */
+// @Override
+// protected void onPreExecute(Activity target) {
+// final Context context = target;
+//
+// mProgress = new WeakReference<ProgressDialog>(ProgressDialog.show(context, null,
+// context.getText(R.string.savingDisplayGroups)));
+//
+// // Before starting this task, start an empty service to protect our
+// // process from being reclaimed by the system.
+// context.startService(new Intent(context, EmptyService.class));
+// }
+//
+// /** {@inheritDoc} */
+// @Override
+// protected Void doInBackground(Activity target, AccountSet... params) {
+// final Context context = target;
+// final ContentValues values = new ContentValues();
+// final ContentResolver resolver = context.getContentResolver();
+//
+// try {
+// // Build changes and persist in transaction
+// final AccountSet set = params[0];
+// final ArrayList<ContentProviderOperation> diff = set.buildDiff();
+// resolver.applyBatch(ContactsContract.AUTHORITY, diff);
+// } catch (RemoteException e) {
+// Log.e(TAG, "Problem saving display groups", e);
+// } catch (OperationApplicationException e) {
+// Log.e(TAG, "Problem saving display groups", e);
+// }
+//
+// return null;
+// }
+//
+// /** {@inheritDoc} */
+// @Override
+// protected void onPostExecute(Activity target, Void result) {
+// final Context context = target;
+//
+// final ProgressDialog dialog = mProgress.get();
+// if (dialog != null) {
+// try {
+// dialog.dismiss();
+// } catch (Exception e) {
+// Log.e(TAG, "Error dismissing progress dialog", e);
+// }
+// }
+//
+// target.finish();
+//
+// // Stop the service that was protecting us
+// context.stopService(new Intent(context, EmptyService.class));
+// }
+// }
+//
+// @Override
+// public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
+// boolean globalSearch) {
+// if (globalSearch) {
+// super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
+// } else {
+// ContactsSearchManager.startSearch(this, initialQuery);
+// }
+// }
+}
diff --git a/src/com/android/contacts/ui/ContactsPreferences.java b/src/com/android/contacts/preference/ContactsPreferences.java
similarity index 94%
rename from src/com/android/contacts/ui/ContactsPreferences.java
rename to src/com/android/contacts/preference/ContactsPreferences.java
index 89f71fc..bfe7743 100644
--- a/src/com/android/contacts/ui/ContactsPreferences.java
+++ b/src/com/android/contacts/preference/ContactsPreferences.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.contacts.ui;
+package com.android.contacts.preference;
import com.android.contacts.R;
@@ -30,6 +30,10 @@
* Manages user preferences for contacts.
*/
public final class ContactsPreferences extends ContentObserver {
+
+ public static final String PREF_DISPLAY_ONLY_PHONES = "only_phones";
+ public static final boolean PREF_DISPLAY_ONLY_PHONES_DEFAULT = false;
+
private Context mContext;
private int mSortOrder = -1;
private int mDisplayOrder = -1;
@@ -46,7 +50,7 @@
return mContext.getResources().getBoolean(R.bool.config_sort_order_user_changeable);
}
- private int getDefaultSortOrder() {
+ public int getDefaultSortOrder() {
if (mContext.getResources().getBoolean(R.bool.config_default_sort_order_primary)) {
return ContactsContract.Preferences.SORT_ORDER_PRIMARY;
} else {
@@ -80,7 +84,7 @@
return mContext.getResources().getBoolean(R.bool.config_display_order_user_changeable);
}
- private int getDefaultDisplayOrder() {
+ public int getDefaultDisplayOrder() {
if (mContext.getResources().getBoolean(R.bool.config_default_display_order_primary)) {
return ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY;
} else {
diff --git a/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java b/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
new file mode 100644
index 0000000..db4a94e
--- /dev/null
+++ b/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.preference;
+
+import com.android.contacts.R;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+/**
+ * This fragment shows the preferences for the first header.
+ */
+public class DisplayOptionsPreferenceFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.preference_display_options);
+ }
+}
+
diff --git a/src/com/android/contacts/preference/DisplayOrderPreference.java b/src/com/android/contacts/preference/DisplayOrderPreference.java
new file mode 100644
index 0000000..b804660
--- /dev/null
+++ b/src/com/android/contacts/preference/DisplayOrderPreference.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.preference;
+
+import com.android.contacts.R;
+
+import android.content.Context;
+import android.preference.ListPreference;
+import android.provider.ContactsContract;
+import android.util.AttributeSet;
+
+/**
+ * Custom preference: view-name-as (first name first or last name first).
+ */
+public final class DisplayOrderPreference extends ListPreference {
+
+ private ContactsPreferences mPreferences;
+ private Context mContext;
+
+ public DisplayOrderPreference(Context context) {
+ super(context);
+ prepare();
+ }
+
+ public DisplayOrderPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ prepare();
+ }
+
+ private void prepare() {
+ mContext = getContext();
+ mPreferences = new ContactsPreferences(mContext);
+ setEntries(new String[]{
+ mContext.getString(R.string.display_options_view_given_name_first),
+ mContext.getString(R.string.display_options_view_family_name_first),
+ });
+ setEntryValues(new String[]{
+ String.valueOf(ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY),
+ String.valueOf(ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE),
+ });
+ setValue(String.valueOf(mPreferences.getDisplayOrder()));
+ }
+
+ @Override
+ protected boolean shouldPersist() {
+ return false; // This preference takes care of its own storage
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ switch (mPreferences.getSortOrder()) {
+ case ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY:
+ return mContext.getString(R.string.display_options_view_given_name_first);
+ case ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE:
+ return mContext.getString(R.string.display_options_view_family_name_first);
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean persistString(String value) {
+ int newValue = Integer.parseInt(value);
+ if (newValue != mPreferences.getSortOrder()) {
+ mPreferences.setDisplayOrder(newValue);
+ notifyChanged();
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/contacts/preference/SortOrderPreference.java b/src/com/android/contacts/preference/SortOrderPreference.java
new file mode 100644
index 0000000..81b034c
--- /dev/null
+++ b/src/com/android/contacts/preference/SortOrderPreference.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.preference;
+
+import com.android.contacts.R;
+
+import android.content.Context;
+import android.preference.ListPreference;
+import android.provider.ContactsContract;
+import android.util.AttributeSet;
+
+/**
+ * Custom preference: sort-by.
+ */
+public final class SortOrderPreference extends ListPreference {
+
+ private ContactsPreferences mPreferences;
+ private Context mContext;
+
+ public SortOrderPreference(Context context) {
+ super(context);
+ prepare();
+ }
+
+ public SortOrderPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ prepare();
+ }
+
+ private void prepare() {
+ mContext = getContext();
+ mPreferences = new ContactsPreferences(mContext);
+ setEntries(new String[]{
+ mContext.getString(R.string.display_options_sort_by_given_name),
+ mContext.getString(R.string.display_options_sort_by_family_name),
+ });
+ setEntryValues(new String[]{
+ String.valueOf(ContactsContract.Preferences.SORT_ORDER_PRIMARY),
+ String.valueOf(ContactsContract.Preferences.SORT_ORDER_ALTERNATIVE),
+ });
+ setValue(String.valueOf(mPreferences.getSortOrder()));
+ }
+
+ @Override
+ protected boolean shouldPersist() {
+ return false; // This preference takes care of its own storage
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ switch (mPreferences.getSortOrder()) {
+ case ContactsContract.Preferences.SORT_ORDER_PRIMARY:
+ return mContext.getString(R.string.display_options_sort_by_given_name);
+ case ContactsContract.Preferences.SORT_ORDER_ALTERNATIVE:
+ return mContext.getString(R.string.display_options_sort_by_family_name);
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean persistString(String value) {
+ int newValue = Integer.parseInt(value);
+ if (newValue != mPreferences.getSortOrder()) {
+ mPreferences.setSortOrder(newValue);
+ notifyChanged();
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/contacts/ui/ContactsPreferencesActivity.java b/src/com/android/contacts/ui/ContactsPreferencesActivity.java
deleted file mode 100644
index e32eb2a..0000000
--- a/src/com/android/contacts/ui/ContactsPreferencesActivity.java
+++ /dev/null
@@ -1,1087 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.ui;
-
-import com.android.contacts.ContactsSearchManager;
-import com.android.contacts.R;
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.GoogleSource;
-import com.android.contacts.model.Sources;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.EmptyService;
-import com.android.contacts.util.LocalizedNameResolver;
-import com.android.contacts.util.WeakAsyncTask;
-import com.google.android.collect.Lists;
-
-import android.accounts.Account;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.ExpandableListActivity;
-import android.app.ProgressDialog;
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.EntityIterator;
-import android.content.Intent;
-import android.content.OperationApplicationException;
-import android.content.SharedPreferences;
-import android.content.ContentProviderOperation.Builder;
-import android.content.SharedPreferences.Editor;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.preference.PreferenceManager;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Groups;
-import android.provider.ContactsContract.Settings;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.MenuItem.OnMenuItemClickListener;
-import android.widget.AdapterView;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.CheckBox;
-import android.widget.ExpandableListAdapter;
-import android.widget.ExpandableListView;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-
-/**
- * Shows a list of all available {@link Groups} available, letting the user
- * select which ones they want to be visible.
- */
-public final class ContactsPreferencesActivity extends ExpandableListActivity implements
- AdapterView.OnItemClickListener, View.OnClickListener {
- private static final String TAG = "DisplayGroupsActivity";
-
- public interface Prefs {
- public static final String DISPLAY_ONLY_PHONES = "only_phones";
- public static final boolean DISPLAY_ONLY_PHONES_DEFAULT = false;
-
- }
-
- private static final int DIALOG_SORT_ORDER = 1;
- private static final int DIALOG_DISPLAY_ORDER = 2;
-
- private ExpandableListView mList;
- private DisplayAdapter mAdapter;
-
- private SharedPreferences mPrefs;
- private ContactsPreferences mContactsPrefs;
-
- private CheckBox mDisplayPhones;
-
- private View mHeaderPhones;
- private View mHeaderSeparator;
-
- private View mSortOrderView;
- private TextView mSortOrderTextView;
- private int mSortOrder;
-
- private View mDisplayOrderView;
- private TextView mDisplayOrderTextView;
- private int mDisplayOrder;
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setContentView(R.layout.contacts_preferences);
-
- mList = getExpandableListView();
- mList.setHeaderDividersEnabled(true);
- mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- mContactsPrefs = new ContactsPreferences(this);
- mAdapter = new DisplayAdapter(this);
-
- final LayoutInflater inflater = getLayoutInflater();
-
- createWithPhonesOnlyPreferenceView(inflater);
- createSortOrderPreferenceView(inflater);
- createDisplayOrderPreferenceView(inflater);
- createDisplayGroupHeader(inflater);
-
- findViewById(R.id.btn_done).setOnClickListener(this);
- findViewById(R.id.btn_discard).setOnClickListener(this);
-
- // Catch clicks on the header views
- mList.setOnItemClickListener(this);
- mList.setOnCreateContextMenuListener(this);
-
- mSortOrder = mContactsPrefs.getSortOrder();
- mDisplayOrder = mContactsPrefs.getDisplayOrder();
- }
-
- private void createWithPhonesOnlyPreferenceView(LayoutInflater inflater) {
- // Add the "Only contacts with phones" header modifier.
- mHeaderPhones = inflater.inflate(R.layout.display_options_phones_only, mList, false);
- mHeaderPhones.setId(R.id.header_phones);
- mDisplayPhones = (CheckBox) mHeaderPhones.findViewById(android.R.id.checkbox);
- mDisplayPhones.setChecked(mPrefs.getBoolean(Prefs.DISPLAY_ONLY_PHONES,
- Prefs.DISPLAY_ONLY_PHONES_DEFAULT));
- {
- final TextView text1 = (TextView)mHeaderPhones.findViewById(android.R.id.text1);
- final TextView text2 = (TextView)mHeaderPhones.findViewById(android.R.id.text2);
- text1.setText(R.string.showFilterPhones);
- text2.setText(R.string.showFilterPhonesDescrip);
- }
- }
-
- private void createSortOrderPreferenceView(LayoutInflater inflater) {
- mSortOrderView = inflater.inflate(R.layout.preference_with_more_button, mList, false);
-
- View preferenceLayout = mSortOrderView.findViewById(R.id.preference);
-
- TextView label = (TextView)preferenceLayout.findViewById(R.id.label);
- label.setText(getString(R.string.display_options_sort_list_by));
-
- mSortOrderTextView = (TextView)preferenceLayout.findViewById(R.id.data);
- }
-
- private void createDisplayOrderPreferenceView(LayoutInflater inflater) {
- mDisplayOrderView = inflater.inflate(R.layout.preference_with_more_button, mList, false);
- View preferenceLayout = mDisplayOrderView.findViewById(R.id.preference);
-
- TextView label = (TextView)preferenceLayout.findViewById(R.id.label);
- label.setText(getString(R.string.display_options_view_names_as));
-
- mDisplayOrderTextView = (TextView)preferenceLayout.findViewById(R.id.data);
- }
-
- private void createDisplayGroupHeader(LayoutInflater inflater) {
- // Add the separator before showing the detailed group list.
- mHeaderSeparator = inflater.inflate(R.layout.list_separator, mList, false);
- {
- final TextView text1 = (TextView)mHeaderSeparator;
- text1.setText(R.string.headerContactGroups);
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mList.removeHeaderView(mHeaderPhones);
- mList.removeHeaderView(mSortOrderView);
- mList.removeHeaderView(mDisplayOrderView);
- mList.removeHeaderView(mHeaderSeparator);
-
- // List adapter needs to be reset, because header views cannot be added
- // to a list with an existing adapter.
- setListAdapter(null);
-
- mList.addHeaderView(mHeaderPhones, null, true);
- if (mContactsPrefs.isSortOrderUserChangeable()) {
- mList.addHeaderView(mSortOrderView, null, true);
- }
-
- if (mContactsPrefs.isSortOrderUserChangeable()) {
- mList.addHeaderView(mDisplayOrderView, null, true);
- }
-
- mList.addHeaderView(mHeaderSeparator, null, false);
-
- setListAdapter(mAdapter);
-
- bindView();
-
- // Start background query to find account details
- new QueryGroupsTask(this).execute();
- }
-
- private void bindView() {
- mSortOrderTextView.setText(
- mSortOrder == ContactsContract.Preferences.SORT_ORDER_PRIMARY
- ? getString(R.string.display_options_sort_by_given_name)
- : getString(R.string.display_options_sort_by_family_name));
-
- mDisplayOrderTextView.setText(
- mDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY
- ? getString(R.string.display_options_view_given_name_first)
- : getString(R.string.display_options_view_family_name_first));
- }
-
- @Override
- protected Dialog onCreateDialog(int id, Bundle args) {
- switch (id) {
- case DIALOG_SORT_ORDER:
- return createSortOrderDialog();
- case DIALOG_DISPLAY_ORDER:
- return createDisplayOrderDialog();
- }
-
- return null;
- }
-
- private Dialog createSortOrderDialog() {
- String[] items = new String[] {
- getString(R.string.display_options_sort_by_given_name),
- getString(R.string.display_options_sort_by_family_name),
- };
-
- return new AlertDialog.Builder(this)
- .setIcon(com.android.internal.R.drawable.ic_dialog_menu_generic)
- .setTitle(R.string.display_options_sort_list_by)
- .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- setSortOrder(dialog);
- dialog.dismiss();
- }
- })
- .setNegativeButton(android.R.string.cancel, null)
- .create();
- }
-
- private Dialog createDisplayOrderDialog() {
- String[] items = new String[] {
- getString(R.string.display_options_view_given_name_first),
- getString(R.string.display_options_view_family_name_first),
- };
-
- return new AlertDialog.Builder(this)
- .setIcon(com.android.internal.R.drawable.ic_dialog_menu_generic)
- .setTitle(R.string.display_options_view_names_as)
- .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- setDisplayOrder(dialog);
- dialog.dismiss();
- }
- })
- .setNegativeButton(android.R.string.cancel, null)
- .create();
- }
-
- @Override
- protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
- switch (id) {
- case DIALOG_SORT_ORDER:
- setCheckedItem(dialog,
- mSortOrder == ContactsContract.Preferences.SORT_ORDER_PRIMARY ? 0 : 1);
- break;
- case DIALOG_DISPLAY_ORDER:
- setCheckedItem(dialog,
- mDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY
- ? 0 : 1);
- break;
- }
- }
-
- private void setCheckedItem(Dialog dialog, int position) {
- ListView listView = ((AlertDialog)dialog).getListView();
- listView.setItemChecked(position, true);
- listView.setSelection(position);
- }
-
- protected void setSortOrder(DialogInterface dialog) {
- ListView listView = ((AlertDialog)dialog).getListView();
- int checked = listView.getCheckedItemPosition();
- mSortOrder = checked == 0
- ? ContactsContract.Preferences.SORT_ORDER_PRIMARY
- : ContactsContract.Preferences.SORT_ORDER_ALTERNATIVE;
-
- bindView();
- }
-
- protected void setDisplayOrder(DialogInterface dialog) {
- ListView listView = ((AlertDialog)dialog).getListView();
- int checked = listView.getCheckedItemPosition();
- mDisplayOrder = checked == 0
- ? ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY
- : ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE;
-
- bindView();
- }
-
- /**
- * Background operation to build set of {@link AccountDisplay} for each
- * {@link Sources#getAccounts(boolean)} that provides groups.
- */
- private static class QueryGroupsTask extends
- WeakAsyncTask<Void, Void, AccountSet, ContactsPreferencesActivity> {
- public QueryGroupsTask(ContactsPreferencesActivity target) {
- super(target);
- }
-
- @Override
- protected AccountSet doInBackground(ContactsPreferencesActivity target,
- Void... params) {
- final Context context = target;
- final Sources sources = Sources.getInstance(context);
- final ContentResolver resolver = context.getContentResolver();
-
- // Inflate groups entry for each account
- final AccountSet accounts = new AccountSet();
- for (Account account : sources.getAccounts(false)) {
- accounts.add(new AccountDisplay(resolver, account.name, account.type));
- }
-
- return accounts;
- }
-
- @Override
- protected void onPostExecute(ContactsPreferencesActivity target, AccountSet result) {
- target.mAdapter.setAccounts(result);
- }
- }
-
- private static final int DEFAULT_SHOULD_SYNC = 1;
- private static final int DEFAULT_VISIBLE = 0;
-
- /**
- * Entry holding any changes to {@link Groups} or {@link Settings} rows,
- * such as {@link Groups#SHOULD_SYNC} or {@link Groups#GROUP_VISIBLE}.
- */
- protected static class GroupDelta extends ValuesDelta {
- private boolean mUngrouped = false;
- private boolean mAccountHasGroups;
-
- private GroupDelta() {
- super();
- }
-
- /**
- * Build {@link GroupDelta} from the {@link Settings} row for the given
- * {@link Settings#ACCOUNT_NAME} and {@link Settings#ACCOUNT_TYPE}.
- */
- public static GroupDelta fromSettings(ContentResolver resolver, String accountName,
- String accountType, boolean accountHasGroups) {
- final Uri settingsUri = Settings.CONTENT_URI.buildUpon()
- .appendQueryParameter(Settings.ACCOUNT_NAME, accountName)
- .appendQueryParameter(Settings.ACCOUNT_TYPE, accountType).build();
- final Cursor cursor = resolver.query(settingsUri, new String[] {
- Settings.SHOULD_SYNC, Settings.UNGROUPED_VISIBLE
- }, null, null, null);
-
- try {
- final ContentValues values = new ContentValues();
- values.put(Settings.ACCOUNT_NAME, accountName);
- values.put(Settings.ACCOUNT_TYPE, accountType);
-
- if (cursor != null && cursor.moveToFirst()) {
- // Read existing values when present
- values.put(Settings.SHOULD_SYNC, cursor.getInt(0));
- values.put(Settings.UNGROUPED_VISIBLE, cursor.getInt(1));
- return fromBefore(values).setUngrouped(accountHasGroups);
- } else {
- // Nothing found, so treat as create
- values.put(Settings.SHOULD_SYNC, DEFAULT_SHOULD_SYNC);
- values.put(Settings.UNGROUPED_VISIBLE, DEFAULT_VISIBLE);
- return fromAfter(values).setUngrouped(accountHasGroups);
- }
- } finally {
- if (cursor != null) cursor.close();
- }
- }
-
- public static GroupDelta fromBefore(ContentValues before) {
- final GroupDelta entry = new GroupDelta();
- entry.mBefore = before;
- entry.mAfter = new ContentValues();
- return entry;
- }
-
- public static GroupDelta fromAfter(ContentValues after) {
- final GroupDelta entry = new GroupDelta();
- entry.mBefore = null;
- entry.mAfter = after;
- return entry;
- }
-
- protected GroupDelta setUngrouped(boolean accountHasGroups) {
- mUngrouped = true;
- mAccountHasGroups = accountHasGroups;
- return this;
- }
-
- @Override
- public boolean beforeExists() {
- return mBefore != null;
- }
-
- public boolean getShouldSync() {
- return getAsInteger(mUngrouped ? Settings.SHOULD_SYNC : Groups.SHOULD_SYNC,
- DEFAULT_SHOULD_SYNC) != 0;
- }
-
- public boolean getVisible() {
- return getAsInteger(mUngrouped ? Settings.UNGROUPED_VISIBLE : Groups.GROUP_VISIBLE,
- DEFAULT_VISIBLE) != 0;
- }
-
- public void putShouldSync(boolean shouldSync) {
- put(mUngrouped ? Settings.SHOULD_SYNC : Groups.SHOULD_SYNC, shouldSync ? 1 : 0);
- }
-
- public void putVisible(boolean visible) {
- put(mUngrouped ? Settings.UNGROUPED_VISIBLE : Groups.GROUP_VISIBLE, visible ? 1 : 0);
- }
-
- private String getAccountType() {
- return (mBefore == null ? mAfter : mBefore).getAsString(Settings.ACCOUNT_TYPE);
- }
-
- public CharSequence getTitle(Context context) {
- if (mUngrouped) {
- final String customAllContactsName =
- LocalizedNameResolver.getAllContactsName(context, getAccountType());
- if (customAllContactsName != null) {
- return customAllContactsName;
- }
- if (mAccountHasGroups) {
- return context.getText(R.string.display_ungrouped);
- } else {
- return context.getText(R.string.display_all_contacts);
- }
- } else {
- final Integer titleRes = getAsInteger(Groups.TITLE_RES);
- if (titleRes != null) {
- final String packageName = getAsString(Groups.RES_PACKAGE);
- return context.getPackageManager().getText(packageName, titleRes, null);
- } else {
- return getAsString(Groups.TITLE);
- }
- }
- }
-
- /**
- * Build a possible {@link ContentProviderOperation} to persist any
- * changes to the {@link Groups} or {@link Settings} row described by
- * this {@link GroupDelta}.
- */
- public ContentProviderOperation buildDiff() {
- if (isNoop()) {
- return null;
- } else if (isUpdate()) {
- // When has changes and "before" exists, then "update"
- final Builder builder = ContentProviderOperation
- .newUpdate(mUngrouped ? Settings.CONTENT_URI : addCallerIsSyncAdapterParameter(Groups.CONTENT_URI));
- if (mUngrouped) {
- builder.withSelection(Settings.ACCOUNT_NAME + "=? AND " + Settings.ACCOUNT_TYPE
- + "=?", new String[] {
- this.getAsString(Settings.ACCOUNT_NAME),
- this.getAsString(Settings.ACCOUNT_TYPE)
- });
- } else {
- builder.withSelection(Groups._ID + "=" + this.getId(), null);
- }
- builder.withValues(mAfter);
- return builder.build();
- } else if (isInsert() && mUngrouped) {
- // Only allow inserts for Settings
- mAfter.remove(mIdColumn);
- final Builder builder = ContentProviderOperation.newInsert(Settings.CONTENT_URI);
- builder.withValues(mAfter);
- return builder.build();
- } else {
- throw new IllegalStateException("Unexpected delete or insert");
- }
- }
- }
-
- private static Uri addCallerIsSyncAdapterParameter(Uri uri) {
- return uri.buildUpon()
- .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
- .build();
- }
-
- /**
- * {@link Comparator} to sort by {@link Groups#_ID}.
- */
- private static Comparator<GroupDelta> sIdComparator = new Comparator<GroupDelta>() {
- public int compare(GroupDelta object1, GroupDelta object2) {
- final Long id1 = object1.getId();
- final Long id2 = object2.getId();
- if (id1 == null && id2 == null) {
- return 0;
- } else if (id1 == null) {
- return -1;
- } else if (id2 == null) {
- return 1;
- } else if (id1 < id2) {
- return -1;
- } else if (id1 > id2) {
- return 1;
- } else {
- return 0;
- }
- }
- };
-
- /**
- * Set of all {@link AccountDisplay} entries, one for each source.
- */
- protected static class AccountSet extends ArrayList<AccountDisplay> {
- public ArrayList<ContentProviderOperation> buildDiff() {
- final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
- for (AccountDisplay account : this) {
- account.buildDiff(diff);
- }
- return diff;
- }
- }
-
- /**
- * {@link GroupDelta} details for a single {@link Account}, usually shown as
- * children under a single expandable group.
- */
- protected static class AccountDisplay {
- public String mName;
- public String mType;
-
- public GroupDelta mUngrouped;
- public ArrayList<GroupDelta> mSyncedGroups = Lists.newArrayList();
- public ArrayList<GroupDelta> mUnsyncedGroups = Lists.newArrayList();
-
- /**
- * Build an {@link AccountDisplay} covering all {@link Groups} under the
- * given {@link Account}.
- */
- public AccountDisplay(ContentResolver resolver, String accountName, String accountType) {
- mName = accountName;
- mType = accountType;
-
- final Uri groupsUri = Groups.CONTENT_URI.buildUpon()
- .appendQueryParameter(Groups.ACCOUNT_NAME, accountName)
- .appendQueryParameter(Groups.ACCOUNT_TYPE, accountType).build();
- EntityIterator iterator = ContactsContract.Groups.newEntityIterator(resolver.query(
- groupsUri, null, null, null, null));
- try {
- boolean hasGroups = false;
-
- // Create entries for each known group
- while (iterator.hasNext()) {
- final ContentValues values = iterator.next().getEntityValues();
- final GroupDelta group = GroupDelta.fromBefore(values);
- addGroup(group);
- hasGroups = true;
- }
- // Create single entry handling ungrouped status
- mUngrouped = GroupDelta.fromSettings(resolver, accountName, accountType, hasGroups);
- addGroup(mUngrouped);
- } finally {
- iterator.close();
- }
- }
-
- /**
- * Add the given {@link GroupDelta} internally, filing based on its
- * {@link GroupDelta#getShouldSync()} status.
- */
- private void addGroup(GroupDelta group) {
- if (group.getShouldSync()) {
- mSyncedGroups.add(group);
- } else {
- mUnsyncedGroups.add(group);
- }
- }
-
- /**
- * Set the {@link GroupDelta#putShouldSync(boolean)} value for all
- * children {@link GroupDelta} rows.
- */
- public void setShouldSync(boolean shouldSync) {
- final Iterator<GroupDelta> oppositeChildren = shouldSync ?
- mUnsyncedGroups.iterator() : mSyncedGroups.iterator();
- while (oppositeChildren.hasNext()) {
- final GroupDelta child = oppositeChildren.next();
- setShouldSync(child, shouldSync, false);
- oppositeChildren.remove();
- }
- }
-
- public void setShouldSync(GroupDelta child, boolean shouldSync) {
- setShouldSync(child, shouldSync, true);
- }
-
- /**
- * Set {@link GroupDelta#putShouldSync(boolean)}, and file internally
- * based on updated state.
- */
- public void setShouldSync(GroupDelta child, boolean shouldSync, boolean attemptRemove) {
- child.putShouldSync(shouldSync);
- if (shouldSync) {
- if (attemptRemove) {
- mUnsyncedGroups.remove(child);
- }
- mSyncedGroups.add(child);
- Collections.sort(mSyncedGroups, sIdComparator);
- } else {
- if (attemptRemove) {
- mSyncedGroups.remove(child);
- }
- mUnsyncedGroups.add(child);
- }
- }
-
- /**
- * Build set of {@link ContentProviderOperation} to persist any user
- * changes to {@link GroupDelta} rows under this {@link Account}.
- */
- public void buildDiff(ArrayList<ContentProviderOperation> diff) {
- for (GroupDelta group : mSyncedGroups) {
- final ContentProviderOperation oper = group.buildDiff();
- if (oper != null) diff.add(oper);
- }
- for (GroupDelta group : mUnsyncedGroups) {
- final ContentProviderOperation oper = group.buildDiff();
- if (oper != null) diff.add(oper);
- }
- }
- }
-
- /**
- * {@link ExpandableListAdapter} that shows {@link GroupDelta} settings,
- * grouped by {@link Account} source. Shows footer row when any groups are
- * unsynced, as determined through {@link AccountDisplay#mUnsyncedGroups}.
- */
- protected static class DisplayAdapter extends BaseExpandableListAdapter {
- private Context mContext;
- private LayoutInflater mInflater;
- private Sources mSources;
- private AccountSet mAccounts;
-
- private boolean mChildWithPhones = false;
-
- public DisplayAdapter(Context context) {
- mContext = context;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mSources = Sources.getInstance(context);
- }
-
- public void setAccounts(AccountSet accounts) {
- mAccounts = accounts;
- notifyDataSetChanged();
- }
-
- /**
- * In group descriptions, show the number of contacts with phone
- * numbers, in addition to the total contacts.
- */
- public void setChildDescripWithPhones(boolean withPhones) {
- mChildWithPhones = withPhones;
- }
-
- /** {@inheritDoc} */
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.display_child, parent, false);
- }
-
- final TextView text1 = (TextView)convertView.findViewById(android.R.id.text1);
- final TextView text2 = (TextView)convertView.findViewById(android.R.id.text2);
- final CheckBox checkbox = (CheckBox)convertView.findViewById(android.R.id.checkbox);
-
- final AccountDisplay account = mAccounts.get(groupPosition);
- final GroupDelta child = (GroupDelta)this.getChild(groupPosition, childPosition);
- if (child != null) {
- // Handle normal group, with title and checkbox
- final boolean groupVisible = child.getVisible();
- checkbox.setVisibility(View.VISIBLE);
- checkbox.setChecked(groupVisible);
-
- final CharSequence groupTitle = child.getTitle(mContext);
- text1.setText(groupTitle);
-
-// final int count = cursor.getInt(GroupsQuery.SUMMARY_COUNT);
-// final int withPhones = cursor.getInt(GroupsQuery.SUMMARY_WITH_PHONES);
-
-// final CharSequence descrip = mContext.getResources().getQuantityString(
-// mChildWithPhones ? R.plurals.groupDescripPhones : R.plurals.groupDescrip,
-// count, count, withPhones);
-
-// text2.setText(descrip);
- text2.setVisibility(View.GONE);
- } else {
- // When unknown child, this is "more" footer view
- checkbox.setVisibility(View.GONE);
- text1.setText(R.string.display_more_groups);
- text2.setVisibility(View.GONE);
- }
-
- return convertView;
- }
-
- /** {@inheritDoc} */
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.display_group, parent, false);
- }
-
- final TextView text1 = (TextView)convertView.findViewById(android.R.id.text1);
- final TextView text2 = (TextView)convertView.findViewById(android.R.id.text2);
-
- final AccountDisplay account = (AccountDisplay)this.getGroup(groupPosition);
-
- final ContactsSource source = mSources.getInflatedSource(account.mType,
- ContactsSource.LEVEL_SUMMARY);
-
- text1.setText(account.mName);
- text2.setText(source.getDisplayLabel(mContext));
- text2.setVisibility(account.mName == null ? View.GONE : View.VISIBLE);
-
- return convertView;
- }
-
- /** {@inheritDoc} */
- public Object getChild(int groupPosition, int childPosition) {
- final AccountDisplay account = mAccounts.get(groupPosition);
- final boolean validChild = childPosition >= 0
- && childPosition < account.mSyncedGroups.size();
- if (validChild) {
- return account.mSyncedGroups.get(childPosition);
- } else {
- return null;
- }
- }
-
- /** {@inheritDoc} */
- public long getChildId(int groupPosition, int childPosition) {
- final GroupDelta child = (GroupDelta)getChild(groupPosition, childPosition);
- if (child != null) {
- final Long childId = child.getId();
- return childId != null ? childId : Long.MIN_VALUE;
- } else {
- return Long.MIN_VALUE;
- }
- }
-
- /** {@inheritDoc} */
- public int getChildrenCount(int groupPosition) {
- // Count is any synced groups, plus possible footer
- final AccountDisplay account = mAccounts.get(groupPosition);
- final boolean anyHidden = account.mUnsyncedGroups.size() > 0;
- return account.mSyncedGroups.size() + (anyHidden ? 1 : 0);
- }
-
- /** {@inheritDoc} */
- public Object getGroup(int groupPosition) {
- return mAccounts.get(groupPosition);
- }
-
- /** {@inheritDoc} */
- public int getGroupCount() {
- if (mAccounts == null) {
- return 0;
- }
- return mAccounts.size();
- }
-
- /** {@inheritDoc} */
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- /** {@inheritDoc} */
- public boolean hasStableIds() {
- return true;
- }
-
- /** {@inheritDoc} */
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
- }
-
- /**
- * Handle any clicks on header views added to our {@link #mAdapter}, which
- * are usually the global modifier checkboxes.
- */
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Log.d(TAG, "OnItemClick, position=" + position + ", id=" + id);
- if (view == mHeaderPhones) {
- mDisplayPhones.toggle();
- return;
- }
- if (view == mDisplayOrderView) {
- Log.d(TAG, "Showing Display Order dialog");
- showDialog(DIALOG_DISPLAY_ORDER);
- return;
- }
- if (view == mSortOrderView) {
- Log.d(TAG, "Showing Sort Order dialog");
- showDialog(DIALOG_SORT_ORDER);
- return;
- }
- }
-
- /** {@inheritDoc} */
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.btn_done: {
- this.doSaveAction();
- break;
- }
- case R.id.btn_discard: {
- this.finish();
- break;
- }
- }
- }
-
- /**
- * Assign a specific value to {@link Prefs#DISPLAY_ONLY_PHONES}, refreshing
- * the visible list as needed.
- */
- protected void setDisplayOnlyPhones(boolean displayOnlyPhones) {
- mDisplayPhones.setChecked(displayOnlyPhones);
-
- Editor editor = mPrefs.edit();
- editor.putBoolean(Prefs.DISPLAY_ONLY_PHONES, displayOnlyPhones);
- editor.apply();
-
- mAdapter.setChildDescripWithPhones(displayOnlyPhones);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Handle any clicks on {@link ExpandableListAdapter} children, which
- * usually mean toggling its visible state.
- */
- @Override
- public boolean onChildClick(ExpandableListView parent, View view, int groupPosition,
- int childPosition, long id) {
- final CheckBox checkbox = (CheckBox)view.findViewById(android.R.id.checkbox);
-
- final AccountDisplay account = (AccountDisplay)mAdapter.getGroup(groupPosition);
- final GroupDelta child = (GroupDelta)mAdapter.getChild(groupPosition, childPosition);
- if (child != null) {
- checkbox.toggle();
- child.putVisible(checkbox.isChecked());
- } else {
- // Open context menu for bringing back unsynced
- this.openContextMenu(view);
- }
- return true;
- }
-
- // TODO: move these definitions to framework constants when we begin
- // defining this mode through <sync-adapter> tags
- private static final int SYNC_MODE_UNSUPPORTED = 0;
- private static final int SYNC_MODE_UNGROUPED = 1;
- private static final int SYNC_MODE_EVERYTHING = 2;
-
- protected int getSyncMode(AccountDisplay account) {
- // TODO: read sync mode through <sync-adapter> definition
- if (GoogleSource.ACCOUNT_TYPE.equals(account.mType)) {
- return SYNC_MODE_EVERYTHING;
- } else {
- return SYNC_MODE_UNSUPPORTED;
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view,
- ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, view, menuInfo);
-
- // Bail if not working with expandable long-press, or if not child
- if (!(menuInfo instanceof ExpandableListContextMenuInfo)) return;
-
- final ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuInfo;
- final int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
- final int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
-
- // Skip long-press on expandable parents
- if (childPosition == -1) return;
-
- final AccountDisplay account = (AccountDisplay)mAdapter.getGroup(groupPosition);
- final GroupDelta child = (GroupDelta)mAdapter.getChild(groupPosition, childPosition);
-
- // Ignore when selective syncing unsupported
- final int syncMode = getSyncMode(account);
- if (syncMode == SYNC_MODE_UNSUPPORTED) return;
-
- if (child != null) {
- showRemoveSync(menu, account, child, syncMode);
- } else {
- showAddSync(menu, account, syncMode);
- }
- }
-
- protected void showRemoveSync(ContextMenu menu, final AccountDisplay account,
- final GroupDelta child, final int syncMode) {
- final CharSequence title = child.getTitle(this);
-
- menu.setHeaderTitle(title);
- menu.add(R.string.menu_sync_remove).setOnMenuItemClickListener(
- new OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- handleRemoveSync(account, child, syncMode, title);
- return true;
- }
- });
- }
-
- protected void handleRemoveSync(final AccountDisplay account, final GroupDelta child,
- final int syncMode, CharSequence title) {
- final boolean shouldSyncUngrouped = account.mUngrouped.getShouldSync();
- if (syncMode == SYNC_MODE_EVERYTHING && shouldSyncUngrouped
- && !child.equals(account.mUngrouped)) {
- // Warn before removing this group when it would cause ungrouped to stop syncing
- final AlertDialog.Builder builder = new AlertDialog.Builder(this);
- final CharSequence removeMessage = this.getString(
- R.string.display_warn_remove_ungrouped, title);
- builder.setTitle(R.string.menu_sync_remove);
- builder.setMessage(removeMessage);
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- // Mark both this group and ungrouped to stop syncing
- account.setShouldSync(account.mUngrouped, false);
- account.setShouldSync(child, false);
- mAdapter.notifyDataSetChanged();
- }
- });
- builder.show();
- } else {
- // Mark this group to not sync
- account.setShouldSync(child, false);
- mAdapter.notifyDataSetChanged();
- }
- }
-
- protected void showAddSync(ContextMenu menu, final AccountDisplay account, final int syncMode) {
- menu.setHeaderTitle(R.string.dialog_sync_add);
-
- // Create item for each available, unsynced group
- for (final GroupDelta child : account.mUnsyncedGroups) {
- if (!child.getShouldSync()) {
- final CharSequence title = child.getTitle(this);
- menu.add(title).setOnMenuItemClickListener(new OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- // Adding specific group for syncing
- if (child.mUngrouped && syncMode == SYNC_MODE_EVERYTHING) {
- account.setShouldSync(true);
- } else {
- account.setShouldSync(child, true);
- }
- mAdapter.notifyDataSetChanged();
- return true;
- }
- });
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void onBackPressed() {
- doSaveAction();
- }
-
- private void doSaveAction() {
- mContactsPrefs.setSortOrder(mSortOrder);
- mContactsPrefs.setDisplayOrder(mDisplayOrder);
-
- if (mAdapter == null || mAdapter.mAccounts == null) {
- return;
- }
- setDisplayOnlyPhones(mDisplayPhones.isChecked());
- new UpdateTask(this).execute(mAdapter.mAccounts);
- }
-
- /**
- * Background task that persists changes to {@link Groups#GROUP_VISIBLE},
- * showing spinner dialog to user while updating.
- */
- public static class UpdateTask extends
- WeakAsyncTask<AccountSet, Void, Void, Activity> {
- private WeakReference<ProgressDialog> mProgress;
-
- public UpdateTask(Activity target) {
- super(target);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void onPreExecute(Activity target) {
- final Context context = target;
-
- mProgress = new WeakReference<ProgressDialog>(ProgressDialog.show(context, null,
- context.getText(R.string.savingDisplayGroups)));
-
- // Before starting this task, start an empty service to protect our
- // process from being reclaimed by the system.
- context.startService(new Intent(context, EmptyService.class));
- }
-
- /** {@inheritDoc} */
- @Override
- protected Void doInBackground(Activity target, AccountSet... params) {
- final Context context = target;
- final ContentValues values = new ContentValues();
- final ContentResolver resolver = context.getContentResolver();
-
- try {
- // Build changes and persist in transaction
- final AccountSet set = params[0];
- final ArrayList<ContentProviderOperation> diff = set.buildDiff();
- resolver.applyBatch(ContactsContract.AUTHORITY, diff);
- } catch (RemoteException e) {
- Log.e(TAG, "Problem saving display groups", e);
- } catch (OperationApplicationException e) {
- Log.e(TAG, "Problem saving display groups", e);
- }
-
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void onPostExecute(Activity target, Void result) {
- final Context context = target;
-
- final ProgressDialog dialog = mProgress.get();
- if (dialog != null) {
- try {
- dialog.dismiss();
- } catch (Exception e) {
- Log.e(TAG, "Error dismissing progress dialog", e);
- }
- }
-
- target.finish();
-
- // Stop the service that was protecting us
- context.stopService(new Intent(context, EmptyService.class));
- }
- }
-
- @Override
- public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
- boolean globalSearch) {
- if (globalSearch) {
- super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
- } else {
- ContactsSearchManager.startSearch(this, initialQuery);
- }
- }
-}