Make ContactPreferences use SharedPreferences instead of System settings (3/5)
* Move constants that originally lived in the framework into ContactsCommon
* Use SharedPreferences instead of System settings to persist preferences
* Use a SharedPreferenceListener to monitor changes instead of a content observer
on system settings
* Move DisplayOrderPreference and SortOrderPreference into ContactsCommon so that
it can be used by Dialer
* Create base DialerSettingsActivity in Dialer, and make GoogleDialerSettingsActivity
extend it
Bug: 16153186
Change-Id: Ib3500b82b03960a30b565f1024f20f78879d3ce3
diff --git a/src/com/android/contacts/common/list/ContactListAdapter.java b/src/com/android/contacts/common/list/ContactListAdapter.java
index e158238..5826025 100644
--- a/src/com/android/contacts/common/list/ContactListAdapter.java
+++ b/src/com/android/contacts/common/list/ContactListAdapter.java
@@ -31,6 +31,7 @@
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.common.R;
+import com.android.contacts.common.preference.ContactsPreferences;
/**
* A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type.
@@ -360,13 +361,13 @@
protected final String[] getProjection(boolean forSearch) {
final int sortOrder = getContactNameDisplayOrder();
if (forSearch) {
- if (sortOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ if (sortOrder == ContactsPreferences.DISPLAY_ORDER_PRIMARY) {
return ContactQuery.FILTER_PROJECTION_PRIMARY;
} else {
return ContactQuery.FILTER_PROJECTION_ALTERNATIVE;
}
} else {
- if (sortOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ if (sortOrder == ContactsPreferences.DISPLAY_ORDER_PRIMARY) {
return ContactQuery.CONTACT_PROJECTION_PRIMARY;
} else {
return ContactQuery.CONTACT_PROJECTION_ALTERNATIVE;
diff --git a/src/com/android/contacts/common/list/DefaultContactListAdapter.java b/src/com/android/contacts/common/list/DefaultContactListAdapter.java
index fba285c..b47608e 100644
--- a/src/com/android/contacts/common/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/common/list/DefaultContactListAdapter.java
@@ -86,7 +86,7 @@
}
String sortOrder;
- if (getSortOrder() == ContactsContract.Preferences.SORT_ORDER_PRIMARY) {
+ if (getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY) {
sortOrder = Contacts.SORT_KEY_PRIMARY;
} else {
sortOrder = Contacts.SORT_KEY_ALTERNATIVE;
diff --git a/src/com/android/contacts/common/list/PhoneNumberListAdapter.java b/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
index 135ea58..cde25da 100644
--- a/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
@@ -39,6 +39,7 @@
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.common.extensions.ExtendedPhoneDirectoriesManager;
import com.android.contacts.common.extensions.ExtensionsFactory;
+import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.util.Constants;
import java.util.ArrayList;
@@ -181,14 +182,13 @@
loader.setUri(builder.build());
// TODO a projection that includes the search snippet
- if (getContactNameDisplayOrder() ==
- ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ if (getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY) {
loader.setProjection(PhoneQuery.PROJECTION_PRIMARY);
} else {
loader.setProjection(PhoneQuery.PROJECTION_ALTERNATIVE);
}
- if (getSortOrder() == ContactsContract.Preferences.SORT_ORDER_PRIMARY) {
+ if (getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY) {
loader.setSortOrder(Phone.SORT_KEY_PRIMARY);
} else {
loader.setSortOrder(Phone.SORT_KEY_ALTERNATIVE);
diff --git a/src/com/android/contacts/common/preference/ContactsPreferences.java b/src/com/android/contacts/common/preference/ContactsPreferences.java
index 56390fd..311d007 100644
--- a/src/com/android/contacts/common/preference/ContactsPreferences.java
+++ b/src/com/android/contacts/common/preference/ContactsPreferences.java
@@ -18,6 +18,9 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.ContactsContract;
@@ -29,21 +32,48 @@
/**
* Manages user preferences for contacts.
*/
-public final class ContactsPreferences extends ContentObserver {
+public final class ContactsPreferences implements OnSharedPreferenceChangeListener {
+
+ /**
+ * The value for the DISPLAY_ORDER key to show the given name first.
+ */
+ public static final int DISPLAY_ORDER_PRIMARY = 1;
+
+ /**
+ * The value for the DISPLAY_ORDER key to show the family name first.
+ */
+ public static final int DISPLAY_ORDER_ALTERNATIVE = 2;
+
+ public static final String DISPLAY_ORDER_KEY = "android.contacts.DISPLAY_ORDER";
+
+ /**
+ * The value for the SORT_ORDER key corresponding to sort by given name first.
+ */
+ public static final int SORT_ORDER_PRIMARY = 1;
+
+ public static final String SORT_ORDER_KEY = "android.contacts.SORT_ORDER";
+
+ /**
+ * The value for the SORT_ORDER key corresponding to sort by family name first.
+ */
+ public static final int SORT_ORDER_ALTERNATIVE = 2;
public static final String PREF_DISPLAY_ONLY_PHONES = "only_phones";
public static final boolean PREF_DISPLAY_ONLY_PHONES_DEFAULT = false;
- private Context mContext;
+ private final Context mContext;
private int mSortOrder = -1;
private int mDisplayOrder = -1;
private ChangeListener mListener = null;
private Handler mHandler;
+ private final SharedPreferences mPreferences;
public ContactsPreferences(Context context) {
- super(null);
mContext = context;
mHandler = new Handler();
+ mPreferences = mContext.getSharedPreferences(context.getPackageName(),
+ Context.MODE_PRIVATE);
+ maybeMigrateSystemSettings();
}
public boolean isSortOrderUserChangeable() {
@@ -52,9 +82,9 @@
public int getDefaultSortOrder() {
if (mContext.getResources().getBoolean(R.bool.config_default_sort_order_primary)) {
- return ContactsContract.Preferences.SORT_ORDER_PRIMARY;
+ return SORT_ORDER_PRIMARY;
} else {
- return ContactsContract.Preferences.SORT_ORDER_ALTERNATIVE;
+ return SORT_ORDER_ALTERNATIVE;
}
}
@@ -62,22 +92,17 @@
if (!isSortOrderUserChangeable()) {
return getDefaultSortOrder();
}
-
if (mSortOrder == -1) {
- try {
- mSortOrder = Settings.System.getInt(mContext.getContentResolver(),
- ContactsContract.Preferences.SORT_ORDER);
- } catch (SettingNotFoundException e) {
- mSortOrder = getDefaultSortOrder();
- }
+ mSortOrder = mPreferences.getInt(SORT_ORDER_KEY, getDefaultSortOrder());
}
return mSortOrder;
}
public void setSortOrder(int sortOrder) {
mSortOrder = sortOrder;
- Settings.System.putInt(mContext.getContentResolver(),
- ContactsContract.Preferences.SORT_ORDER, sortOrder);
+ final Editor editor = mPreferences.edit();
+ editor.putInt(SORT_ORDER_KEY, sortOrder);
+ editor.commit();
}
public boolean isDisplayOrderUserChangeable() {
@@ -86,9 +111,9 @@
public int getDefaultDisplayOrder() {
if (mContext.getResources().getBoolean(R.bool.config_default_display_order_primary)) {
- return ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY;
+ return DISPLAY_ORDER_PRIMARY;
} else {
- return ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE;
+ return DISPLAY_ORDER_ALTERNATIVE;
}
}
@@ -96,22 +121,17 @@
if (!isDisplayOrderUserChangeable()) {
return getDefaultDisplayOrder();
}
-
if (mDisplayOrder == -1) {
- try {
- mDisplayOrder = Settings.System.getInt(mContext.getContentResolver(),
- ContactsContract.Preferences.DISPLAY_ORDER);
- } catch (SettingNotFoundException e) {
- mDisplayOrder = getDefaultDisplayOrder();
- }
+ mDisplayOrder = mPreferences.getInt(DISPLAY_ORDER_KEY, getDefaultDisplayOrder());
}
return mDisplayOrder;
}
public void setDisplayOrder(int displayOrder) {
mDisplayOrder = displayOrder;
- Settings.System.putInt(mContext.getContentResolver(),
- ContactsContract.Preferences.DISPLAY_ORDER, displayOrder);
+ final Editor editor = mPreferences.edit();
+ editor.putInt(DISPLAY_ORDER_KEY, displayOrder);
+ editor.commit();
}
public void registerChangeListener(ChangeListener listener) {
@@ -120,35 +140,33 @@
mListener = listener;
// Reset preferences to "unknown" because they may have changed while the
- // observer was unregistered.
+ // listener was unregistered.
mDisplayOrder = -1;
mSortOrder = -1;
- final ContentResolver contentResolver = mContext.getContentResolver();
- contentResolver.registerContentObserver(
- Settings.System.getUriFor(
- ContactsContract.Preferences.SORT_ORDER), false, this);
- contentResolver.registerContentObserver(
- Settings.System.getUriFor(
- ContactsContract.Preferences.DISPLAY_ORDER), false, this);
+ mPreferences.registerOnSharedPreferenceChangeListener(this);
}
public void unregisterChangeListener() {
if (mListener != null) {
- mContext.getContentResolver().unregisterContentObserver(this);
mListener = null;
}
+
+ mPreferences.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
- public void onChange(boolean selfChange) {
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key) {
// This notification is not sent on the Ui thread. Use the previously created Handler
// to switch to the Ui thread
mHandler.post(new Runnable() {
@Override
public void run() {
- mSortOrder = -1;
- mDisplayOrder = -1;
+ if (DISPLAY_ORDER_KEY.equals(key)) {
+ mDisplayOrder = getDisplayOrder();
+ } else if (SORT_ORDER_KEY.equals(key)) {
+ mSortOrder = getSortOrder();
+ }
if (mListener != null) mListener.onChange();
}
});
@@ -157,4 +175,31 @@
public interface ChangeListener {
void onChange();
}
+
+ /**
+ * If there are currently no preferences (which means this is the first time we are run),
+ * check to see if there are any preferences stored in system settings (pre-L) which can be
+ * copied into our own SharedPreferences.
+ */
+ private void maybeMigrateSystemSettings() {
+ if (!mPreferences.contains(SORT_ORDER_KEY)) {
+ int sortOrder = getDefaultSortOrder();
+ try {
+ sortOrder = Settings.System.getInt(mContext.getContentResolver(),
+ SORT_ORDER_KEY);
+ } catch (SettingNotFoundException e) {
+ }
+ setSortOrder(sortOrder);
+ }
+
+ if (!mPreferences.contains(DISPLAY_ORDER_KEY)) {
+ int displayOrder = getDefaultDisplayOrder();
+ try {
+ displayOrder = Settings.System.getInt(mContext.getContentResolver(),
+ DISPLAY_ORDER_KEY);
+ } catch (SettingNotFoundException e) {
+ }
+ setDisplayOrder(displayOrder);
+ }
+ }
}
diff --git a/src/com/android/contacts/common/preference/DisplayOptionsPreferenceFragment.java b/src/com/android/contacts/common/preference/DisplayOptionsPreferenceFragment.java
new file mode 100644
index 0000000..e49f38a
--- /dev/null
+++ b/src/com/android/contacts/common/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.common.preference;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+import com.android.contacts.common.R;
+
+/**
+ * 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/common/preference/DisplayOrderPreference.java b/src/com/android/contacts/common/preference/DisplayOrderPreference.java
new file mode 100644
index 0000000..6a182c5
--- /dev/null
+++ b/src/com/android/contacts/common/preference/DisplayOrderPreference.java
@@ -0,0 +1,92 @@
+/*
+ * 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.common.preference;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.preference.ListPreference;
+import android.provider.ContactsContract;
+import android.util.AttributeSet;
+
+import com.android.contacts.common.R;
+import com.android.contacts.common.preference.ContactsPreferences;
+
+/**
+ * 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(ContactsPreferences.DISPLAY_ORDER_PRIMARY),
+ String.valueOf(ContactsPreferences.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.getDisplayOrder()) {
+ case ContactsPreferences.DISPLAY_ORDER_PRIMARY:
+ return mContext.getString(R.string.display_options_view_given_name_first);
+ case ContactsPreferences.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.getDisplayOrder()) {
+ mPreferences.setDisplayOrder(newValue);
+ notifyChanged();
+ }
+ return true;
+ }
+
+ @Override
+ // UX recommendation is not to show cancel button on such lists.
+ protected void onPrepareDialogBuilder(Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ builder.setNegativeButton(null, null);
+ }
+}
diff --git a/src/com/android/contacts/common/preference/SortOrderPreference.java b/src/com/android/contacts/common/preference/SortOrderPreference.java
new file mode 100644
index 0000000..dfd9550
--- /dev/null
+++ b/src/com/android/contacts/common/preference/SortOrderPreference.java
@@ -0,0 +1,91 @@
+/*
+ * 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.common.preference;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.preference.ListPreference;
+import android.util.AttributeSet;
+
+import com.android.contacts.common.R;
+import com.android.contacts.common.preference.ContactsPreferences;
+
+/**
+ * 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(ContactsPreferences.SORT_ORDER_PRIMARY),
+ String.valueOf(ContactsPreferences.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 ContactsPreferences.SORT_ORDER_PRIMARY:
+ return mContext.getString(R.string.display_options_sort_by_given_name);
+ case ContactsPreferences.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;
+ }
+
+ @Override
+ // UX recommendation is not to show cancel button on such lists.
+ protected void onPrepareDialogBuilder(Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ builder.setNegativeButton(null, null);
+ }
+}
diff --git a/tests/src/com/android/contacts/common/list/ContactListItemViewTest.java b/tests/src/com/android/contacts/common/list/ContactListItemViewTest.java
index 9c69f24..222863c 100644
--- a/tests/src/com/android/contacts/common/list/ContactListItemViewTest.java
+++ b/tests/src/com/android/contacts/common/list/ContactListItemViewTest.java
@@ -26,6 +26,7 @@
import com.android.contacts.common.format.SpannedTestUtils;
import com.android.contacts.common.list.ContactListItemView;
+import com.android.contacts.common.preference.ContactsPreferences;
/**
* Unit tests for {@link com.android.contacts.common.list.ContactListItemView}.
@@ -56,7 +57,7 @@
Cursor cursor = createCursor("John Doe", "Doe John");
ContactListItemView view = createView();
- view.showDisplayName(cursor, 0, ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+ view.showDisplayName(cursor, 0, ContactsPreferences.DISPLAY_ORDER_PRIMARY);
assertEquals(view.getNameTextView().getText().toString(), "John Doe");
}
@@ -66,7 +67,7 @@
ContactListItemView view = createView();
view.setUnknownNameText("unknown");
- view.showDisplayName(cursor, 0, ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+ view.showDisplayName(cursor, 0, ContactsPreferences.DISPLAY_ORDER_PRIMARY);
assertEquals(view.getNameTextView().getText().toString(), "unknown");
}
@@ -76,7 +77,7 @@
ContactListItemView view = createView();
view.setHighlightedPrefix("DOE");
- view.showDisplayName(cursor, 0, ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+ view.showDisplayName(cursor, 0, ContactsPreferences.DISPLAY_ORDER_PRIMARY);
CharSequence seq = view.getNameTextView().getText();
assertEquals("John Doe", seq.toString());
@@ -88,7 +89,7 @@
ContactListItemView view = createView();
view.setHighlightedPrefix("DOE");
- view.showDisplayName(cursor, 0, ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE);
+ view.showDisplayName(cursor, 0, ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE);
CharSequence seq = view.getNameTextView().getText();
assertEquals("John Doe", seq.toString());