Use PreferenceActivity and FragmentBreadCrumbs as they offer the same capabilities now.
Also fix: 2997438 and a similar bug in Tether Settings
Show + menu item for User Dictionary
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 287e312..dacc19f 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -106,6 +106,8 @@
private LockPatternUtils mLockPatternUtils;
private ListPreference mLockAfter;
+ private SettingsObserver mSettingsObserver;
+
private final class SettingsObserver implements Observer {
public void update(Observable o, Object arg) {
updateToggles();
@@ -125,14 +127,24 @@
createPreferenceHierarchy();
updateToggles();
+ }
+ @Override
+ public void onStart() {
+ super.onStart();
// listen for Location Manager settings changes
Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null,
"(" + Settings.System.NAME + "=?)",
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
- mContentQueryMap.addObserver(new SettingsObserver());
+ mContentQueryMap.addObserver(mSettingsObserver = new SettingsObserver());
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ mContentQueryMap.deleteObserver(mSettingsObserver);
}
private PreferenceScreen createPreferenceHierarchy() {
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 224aa53..738acc3 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,354 +16,61 @@
package com.android.settings;
-import android.app.Activity;
import android.app.Fragment;
-import android.content.Context;
-import android.content.Intent;
import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceScreen;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
-import android.widget.TextView;
+import android.preference.PreferenceActivity;
-import java.util.ArrayList;
+import java.util.List;
/**
* Top-level settings activity to handle single pane and double pane UI layout.
*/
-public class Settings extends Activity
- implements PreferenceFragment.OnPreferenceStartFragmentCallback,
- SettingsPreferenceFragment.OnStateListener,
+public class Settings extends PreferenceActivity implements
SettingsPreferenceFragment.FragmentStarter {
- private static final boolean DBG = false;
+ // TODO: Update Call Settings based on airplane mode state.
- private static final String TAG = "Settings";
-
- private static final String KEY_PARENT = "parent";
- private static final String KEY_CALL_SETTINGS = "call_settings";
- private static final String KEY_SYNC_SETTINGS = "sync_settings";
- private static final String KEY_SEARCH_SETTINGS = "search_settings";
- private static final String KEY_DOCK_SETTINGS = "dock_settings";
-
- private static final String KEY_OPERATOR_SETTINGS = "operator_settings";
- private static final String KEY_MANUFACTURER_SETTINGS = "manufacturer_settings";
-
- public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
-
- public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
-
- private static final String BACK_STACK_PREFS = ":settings:prefs";
-
- private View mPrefsPane;
- private View mMainPane;
- private boolean mSinglePane;
-
- private BreadCrumbs mBreadCrumbs;
-
+ /**
+ * Populate the activity with the top-level headers.
+ */
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.settings_top_level);
- mPrefsPane = findViewById(R.id.prefs);
- mMainPane = findViewById(R.id.top_level);
- mSinglePane = mMainPane == null;
- if (mSinglePane) mMainPane = mPrefsPane;
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.settings_headers, target);
- final Intent intent = getIntent();
- String initialFragment = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
- Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+ updateHeaderList(target);
+ }
- createActionBar();
-
- if (mSinglePane) {
- if (initialFragment != null) {
- showFragment(initialFragment, initialArguments);
- } else {
- // Intent#getCompontent() lets us get Fragment name, even when the Intent is
- // given via <activity-alias>.
- //
- // e.g. When we reach here via "ChildSetting" activity-alias,
- // we should get the name here instead of targetActivity ("Settings").
- if (intent.getComponent().getClassName().equals(this.getClass().getName())) {
- showFragment(TopLevelSettings.class.getName(), null);
- } else {
- showFragment(intent.getComponent().getClassName(), intent.getExtras());
- }
+ private void updateHeaderList(List<Header> target) {
+ int i = 0;
+ while (i < target.size()) {
+ Header header = target.get(i);
+ long id = header.id;
+ if (id == R.id.dock_settings) {
+ if (!needsDockSettings())
+ target.remove(header);
+ } else if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
+ Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
+ } else if (id == R.id.call_settings) {
+ if (!Utils.isVoiceCapable(this))
+ target.remove(header);
}
- } else {
- if (!intent.getComponent().getClassName().equals(this.getClass().getName())) {
- if (showFragment(intent.getComponent().getClassName(), intent.getExtras())) {
- mMainPane.setVisibility(View.GONE);
- }
- } else {
- Fragment topLevel = getFragmentManager().findFragmentById(R.id.top_level);
- if (topLevel != null) {
- ((TopLevelSettings) topLevel).selectFirst();
- }
- }
+ if (target.get(i) == header)
+ i++;
}
}
- private void createActionBar() {
- LayoutInflater inflater = (LayoutInflater)
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View customNavBar = inflater.inflate(R.layout.settings_actionbar, null, false);
- getActionBar().setCustomNavigationMode(customNavBar);
- mBreadCrumbs = (BreadCrumbs) customNavBar.findViewById(R.id.bread_crumbs);
- mBreadCrumbs.setActivity(this);
+ private boolean needsDockSettings() {
+ return getResources().getBoolean(R.bool.has_dock_settings);
}
- boolean showFragment(Preference preference) {
- if (mSinglePane) {
- startWithFragment(preference.getFragment(), preference.getExtras());
- return false;
- } else {
- mBreadCrumbs.clear();
- return showFragment(preference.getFragment(), preference.getExtras());
- }
- }
-
- private void startWithFragment(String fragmentName, Bundle args) {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClass(this, getClass());
- intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
- intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
- startActivity(intent);
- }
-
- private boolean showFragment(String fragmentClass, Bundle extras) {
- if (DBG) Log.d(TAG, "showFragment");
- Fragment f = Fragment.instantiate(this, fragmentClass, extras);
- if (f instanceof SettingsPreferenceFragment) {
- SettingsPreferenceFragment spf = (SettingsPreferenceFragment) f;
- spf.setOnStateListener(this);
- spf.setFragmentStarter(this);
- }
- mBreadCrumbs.clear();
- getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
- getFragmentManager().openTransaction().replace(R.id.prefs, f).commit();
- return true;
- }
-
- private void addToBreadCrumbs(Fragment fragment) {
- final CharSequence title = ((PreferenceFragment) fragment)
- .getPreferenceScreen().getTitle();
- if (mSinglePane) {
- mBreadCrumbs.clear();
- }
- mBreadCrumbs.push(title);
- }
-
- private void removeFromBreadCrumbs(Fragment fragment) {
- mBreadCrumbs.pop(((PreferenceFragment) fragment).getPreferenceScreen().getTitle());
- mBreadCrumbs.update();
- }
-
- public void onCreated(SettingsPreferenceFragment fragment) {
- if (DBG) Log.d(TAG, "Fragment created " + fragment);
- addToBreadCrumbs(fragment);
- }
-
- public void onDestroyed(SettingsPreferenceFragment fragment) {
- Log.d(TAG, "Fragment destroyed " + fragment + " (name: " + fragment.getClass() + ")");
- }
-
- public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
- if (DBG) Log.d(TAG, "onPreferenceStartFragment");
- return startFragment(caller, pref.getFragment(), -1, pref.getExtras());
- }
-
- public boolean startFragment(
- Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
+ public boolean startFragment(Fragment caller, String fragmentClass, int requestCode,
+ Bundle extras) {
Fragment f = Fragment.instantiate(this, fragmentClass, extras);
caller.setTargetFragment(f, requestCode);
if (f instanceof SettingsPreferenceFragment) {
SettingsPreferenceFragment spf = (SettingsPreferenceFragment) f;
- spf.setOnStateListener(this);
spf.setFragmentStarter(this);
}
- getFragmentManager().openTransaction().replace(R.id.prefs, f)
- .addToBackStack(BACK_STACK_PREFS).commit();
return true;
}
-
- @Override
- public void onBackPressed() {
- mBreadCrumbs.pop();
- mBreadCrumbs.update();
- super.onBackPressed();
- }
-
- public static class TopLevelSettings extends PreferenceFragment {
-
- private IconPreferenceScreen mHighlightedPreference;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Load the preferences from an XML resource
- addPreferencesFromResource(R.xml.settings);
-
- updatePreferenceList();
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- updateCallSettings();
- }
-
- private void updateCallSettings() {
- Preference callSettings = findPreference(KEY_CALL_SETTINGS);
- // Might have been removed in non-voice-capable devices
- if (callSettings != null) {
- callSettings.setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(getActivity()));
- }
- }
-
- private void updatePreferenceList() {
- final Activity activity = getActivity();
- PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
- Preference dockSettings = parent.findPreference(KEY_DOCK_SETTINGS);
- if (activity.getResources().getBoolean(R.bool.has_dock_settings) == false
- && dockSettings != null) {
- parent.removePreference(dockSettings);
- }
-
- Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
- KEY_OPERATOR_SETTINGS);
- Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
- KEY_MANUFACTURER_SETTINGS);
-
- Preference callSettings = parent.findPreference(KEY_CALL_SETTINGS);
- if (!Utils.isVoiceCapable(activity) && callSettings != null) {
- parent.removePreference(callSettings);
- }
- }
-
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
- // If it is a fragment preference, replace the prefs pane in the 2 pane UI.
- final String fragmentClass = preference.getFragment();
- if (fragmentClass != null) {
- boolean showed = ((Settings) getActivity()).showFragment(preference);
- if (showed) {
- highlight(preference);
- }
- return showed;
- }
- return false;
- }
-
- void highlight(Preference preference) {
- if (mHighlightedPreference != null) {
- mHighlightedPreference.setHighlighted(false);
- }
- mHighlightedPreference = (IconPreferenceScreen) preference;
- mHighlightedPreference.setHighlighted(true);
- }
-
- void selectFirst() {
- Preference first = getPreferenceScreen().getPreference(0);
- onPreferenceTreeClick(getPreferenceScreen(), first);
- }
- }
-
- public static class BreadCrumbs extends LinearLayout implements OnClickListener {
-
- private ArrayList<CharSequence> mTitles = new ArrayList<CharSequence>();
- private TextView mLevelUpTitle;
- private TextView mCurrentLevelTitle;
- private View mDivider;
- private Activity mActivity;
-
- public BreadCrumbs(Context context) {
- this(context, null);
- }
-
- public BreadCrumbs(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void push(CharSequence title) {
- if (mTitles.size() == 0
- || !TextUtils.equals(title, mTitles.get(mTitles.size() - 1))) {
- mTitles.add(title);
- update();
- }
- }
-
- public void pop() {
- if (mTitles.size() > 0) {
- mTitles.remove(mTitles.size() - 1);
- }
- }
-
- public void pop(CharSequence title) {
- if (mTitles.size() > 1) {
- mTitles.remove(title);
- }
- }
-
- public void clear() {
- mTitles.clear();
- }
-
- private void initNavViews() {
- if (mLevelUpTitle == null) {
- mLevelUpTitle = (TextView) findViewById(R.id.level_up_title);
- mCurrentLevelTitle = (TextView) findViewById(R.id.level_current_title);
- mDivider = findViewById(R.id.level_divider);
- if (mLevelUpTitle != null) {
- mLevelUpTitle.setOnClickListener(this);
- }
- if (mCurrentLevelTitle != null) {
- mCurrentLevelTitle.setOnClickListener(this);
- }
- }
- }
-
- public void update() {
- initNavViews();
- if (mLevelUpTitle == null) return;
-
- final int titleCount = mTitles.size();
- if (titleCount > 1) {
- mLevelUpTitle.setText(mTitles.get(titleCount - 2));
- mLevelUpTitle.setVisibility(VISIBLE);
- mDivider.setVisibility(VISIBLE);
- } else {
- mLevelUpTitle.setVisibility(GONE);
- mDivider.setVisibility(GONE);
- }
- if (titleCount > 0) {
- mCurrentLevelTitle.setText(mTitles.get(titleCount - 1));
- } else {
- mCurrentLevelTitle.setText("");
- }
- }
-
- public void setActivity(Activity activity) {
- mActivity = activity;
- }
-
- public void onClick(View v) {
- if (mActivity == null)
- return;
- if (v == mLevelUpTitle) {
- mActivity.onBackPressed();
- }
- }
- }
}
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 87726c1..f632a02 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -35,7 +35,6 @@
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
-import android.util.Log;
import android.webkit.WebView;
import java.io.InputStream;
@@ -220,8 +219,8 @@
}
@Override
- public void onResume() {
- super.onResume();
+ public void onStart() {
+ super.onStart();
final Activity activity = getActivity();
@@ -244,8 +243,8 @@
}
@Override
- public void onPause() {
- super.onPause();
+ public void onStop() {
+ super.onStop();
getActivity().unregisterReceiver(mTetherChangeReceiver);
mTetherChangeReceiver = null;
mWifiApEnabler.pause();
diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java
index 488e117..dc3a96b 100644
--- a/src/com/android/settings/TextToSpeechSettings.java
+++ b/src/com/android/settings/TextToSpeechSettings.java
@@ -37,9 +37,9 @@
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
+import android.preference.Preference.OnPreferenceClickListener;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.speech.tts.TextToSpeech;
@@ -126,6 +126,7 @@
mDefaultLocVariant = currentLocale.getVariant();
mTts = new TextToSpeech(activity, this);
+ initClickers();
}
@@ -136,7 +137,6 @@
// whenever we return to this screen, we don't know the state of the
// system, so we have to recheck that we can play the demo, or it must be disabled.
// TODO make the TTS service listen to "changes in the system", i.e. sd card un/mount
- initClickers();
updateWidgetState();
checkVoiceData();
}
@@ -357,7 +357,6 @@
mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry, mDefaultLocVariant));
mTts.setSpeechRate(mDefaultRate/100.0f);
initDefaultSettings();
- initClickers();
updateWidgetState();
checkVoiceData();
mTtsStarted = true;
diff --git a/src/com/android/settings/UserDictionarySettings.java b/src/com/android/settings/UserDictionarySettings.java
index f1e74ac..6386c86 100644
--- a/src/com/android/settings/UserDictionarySettings.java
+++ b/src/com/android/settings/UserDictionarySettings.java
@@ -31,7 +31,6 @@
import android.text.InputType;
import android.util.Log;
import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -39,7 +38,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AlphabetIndexer;
import android.widget.EditText;
import android.widget.ListAdapter;
@@ -47,6 +46,7 @@
import android.widget.SectionIndexer;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
import java.util.Locale;
@@ -198,8 +198,10 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
+ MenuItem actionItem =
+ menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
.setIcon(R.drawable.ic_menu_add);
+ actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
@Override
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 4c43712..d635403 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -20,8 +20,8 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
@@ -29,9 +29,9 @@
import android.os.SystemProperties;
import android.preference.Preference;
import android.preference.PreferenceGroup;
+import android.preference.PreferenceActivity.Header;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.Log;
import java.util.List;
@@ -203,6 +203,66 @@
return false;
}
+ public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
+ List<Header> target, Header header) {
+
+ Intent intent = header.intent;
+ if (intent != null) {
+ // Find the activity that is in the system image
+ PackageManager pm = context.getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+ int listSize = list.size();
+ for (int i = 0; i < listSize; i++) {
+ ResolveInfo resolveInfo = list.get(i);
+ if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+ != 0) {
+ Drawable icon = null;
+ String title = null;
+ String summary = null;
+
+ // Get the activity's meta-data
+ try {
+ Resources res = pm.getResourcesForApplication(
+ resolveInfo.activityInfo.packageName);
+ Bundle metaData = resolveInfo.activityInfo.metaData;
+
+ if (res != null && metaData != null) {
+ icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
+ title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
+ summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
+ }
+ } catch (NameNotFoundException e) {
+ // Ignore
+ } catch (NotFoundException e) {
+ // Ignore
+ }
+
+ // Set the preference title to the activity's label if no
+ // meta-data is found
+ if (TextUtils.isEmpty(title)) {
+ title = resolveInfo.loadLabel(pm).toString();
+ }
+
+ // Set icon, title and summary for the preference
+ // TODO:
+ //header.icon = icon;
+ header.title = title;
+ header.summary = summary;
+ // Replace the intent with this specific activity
+ header.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
+
+ return true;
+ }
+ }
+ }
+
+ // Did not find a matching activity, so remove the preference
+ if (target.remove(header)) System.err.println("Removed " + header.id);
+
+ return false;
+ }
+
/**
* Returns true if Monkey is running.
*/