diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1b80ce8fed9..7f04228fdb4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -118,6 +118,10 @@ android:value="com.android.settings.wifi.WifiSettings" /> + + + + + + + + + + + + + + @@ -518,6 +546,10 @@ android:value="com.android.settings.applications.ManageApplications" /> + + @@ -535,6 +567,10 @@ android:value="com.android.settings.applications.ManageApplications" /> + + + + @@ -927,6 +967,10 @@ android:value="com.android.settings.fuelgauge.PowerUsageSummary" /> + + Wireless & networks - Wireless & network settings + Wireless & networks Manage Wi-Fi, Bluetooth, airplane mode, mobile networks, & VPNs @@ -2180,7 +2180,7 @@ found in the list of installed applications. Language & input - Language & keyboard settings + Language & input Language settings diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 00706ad0466..b91c7ee0096 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -16,12 +16,17 @@ package com.android.settings; +import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.preference.PreferenceActivity; +import android.preference.PreferenceActivity.Header; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; import java.util.HashMap; import java.util.List; @@ -35,10 +40,20 @@ public class Settings extends PreferenceActivity { "com.android.settings.TOP_LEVEL_HEADER_ID"; private static final String META_DATA_KEY_FRAGMENT_CLASS = "com.android.settings.FRAGMENT_CLASS"; + private static final String META_DATA_KEY_PARENT_TITLE = + "com.android.settings.PARENT_FRAGMENT_TITLE"; + private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS = + "com.android.settings.PARENT_FRAGMENT_CLASS"; + + private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER"; + private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER"; private String mFragmentClass; private int mTopLevelHeaderId; private Header mFirstHeader; + private Header mCurrentHeader; + private Header mParentHeader; + private boolean mInLocalHeaderSwitch; // TODO: Update Call Settings based on airplane mode state. @@ -47,7 +62,9 @@ public class Settings extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { getMetaData(); + mInLocalHeaderSwitch = true; super.onCreate(savedInstanceState); + mInLocalHeaderSwitch = false; if (!onIsHidingHeaders() && onIsMultiPane()) { highlightHeader(); @@ -55,6 +72,84 @@ public class Settings extends PreferenceActivity { // a specific settings screen. setTitle(R.string.settings_label); } + + // Retrieve any saved state + if (savedInstanceState != null) { + mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER); + mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER); + } + + // If the current header was saved, switch to it + if (savedInstanceState != null && mCurrentHeader != null) { + //switchToHeaderLocal(mCurrentHeader); + showBreadCrumbs(mCurrentHeader.title, null); + } + + if (mParentHeader != null) { + setParentTitle(mParentHeader.title, null, new OnClickListener() { + public void onClick(View v) { + switchToParent(mParentHeader.fragment); + } + }); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + // Save the current fragment, if it is the same as originally launched + if (mCurrentHeader != null) { + outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader); + } + if (mParentHeader != null) { + outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader); + } + } + + private void switchToHeaderLocal(Header header) { + mInLocalHeaderSwitch = true; + switchToHeader(header); + mInLocalHeaderSwitch = false; + } + + @Override + public void switchToHeader(Header header) { + if (!mInLocalHeaderSwitch) { + mCurrentHeader = null; + mParentHeader = null; + } + super.switchToHeader(header); + } + + /** + * Switch to parent fragment and store the grand parent's info + * @param class name of the activity wrapper for the parent fragment. + */ + private void switchToParent(String className) { + final ComponentName cn = new ComponentName(this, className); + try { + final PackageManager pm = getPackageManager(); + final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA); + + if (parentInfo != null && parentInfo.metaData != null) { + String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS); + CharSequence fragmentTitle = parentInfo.loadLabel(pm); + Header parentHeader = new Header(); + parentHeader.fragment = fragmentClass; + parentHeader.title = fragmentTitle; + mCurrentHeader = parentHeader; + + switchToHeaderLocal(parentHeader); + + mParentHeader = new Header(); + mParentHeader.fragment + = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS); + mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE); + } + } catch (NameNotFoundException nnfe) { + Log.w("Settings", "Could not find parent activity : " + className); + } } @Override @@ -64,7 +159,7 @@ public class Settings extends PreferenceActivity { // If it is not launched from history, then reset to top-level if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0 && mFirstHeader != null) { - switchToHeader(mFirstHeader); + switchToHeaderLocal(mFirstHeader); } } @@ -126,7 +221,9 @@ public class Settings extends PreferenceActivity { if (fragmentClass != null) { Header header = new Header(); header.fragment = fragmentClass; + header.title = getTitle(); header.fragmentArguments = getIntent().getExtras(); + mCurrentHeader = header; return header; } return super.onGetInitialHeader(); @@ -178,6 +275,17 @@ public class Settings extends PreferenceActivity { if (ai == null || ai.metaData == null) return; mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID); mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS); + + // Check if it has a parent specified and create a Header object + final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE); + String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS); + if (parentFragmentClass != null) { + mParentHeader = new Header(); + mParentHeader.fragment = parentFragmentClass; + if (parentHeaderTitleRes != 0) { + mParentHeader.title = getResources().getString(parentHeaderTitleRes); + } + } } catch (NameNotFoundException nnfe) { } } diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java index ea16f9d2b26..c11b2fd6876 100644 --- a/src/com/android/settings/vpn/VpnSettings.java +++ b/src/com/android/settings/vpn/VpnSettings.java @@ -196,6 +196,17 @@ public class VpnSettings extends SettingsPreferenceFragment super.onDestroyView(); } + @Override + public void onDestroy() { + super.onDestroy(); + // Remove any onClick listeners + if (mVpnListContainer != null) { + for (int i = 0; i < mVpnListContainer.getPreferenceCount(); i++) { + mVpnListContainer.getPreference(i).setOnPreferenceClickListener(null); + } + } + } + @Override public Dialog onCreateDialog (int id) { switch (id) { @@ -1050,6 +1061,7 @@ public class VpnSettings extends SettingsPreferenceFragment changeState(p, VpnState.IDLE); } } + if (getActivity() == null) return; getActivity().unbindService(this); showPreferences(); } @@ -1058,6 +1070,7 @@ public class VpnSettings extends SettingsPreferenceFragment cv.open(); setDefaultState(list); + if (getActivity() == null) return; getActivity().unbindService(this); showPreferences(); }