Terminology
settings_header.xml
This file that's used to generate a list of settings the end user can access. If you're using a tablet, this is basically a list of the itemsstrings.xml
Good old strings.xml. Basically a key/value array of public static final strings. We'll be keeping titles for settings in this file.your_settings.xml
This file holds information about all the different preferences you want to store. Name it something memorable. If you're on a tablet, it's basically the list of individual preferences on the right hand side. In this particular example, it's called sip_settings.xmlYourSettings.java
You'll be creating a class that extends SettingsPreferenceFragment. The most simple implementation of this class is very bare-bones yet extensible. Here, we'll be implementing an OnPreferenceChangeListener to update the keys held in Settings.System. In this example, it's called SipPhoneSettings.java.Now; Let's get coding!
I'm going to use my implementation of SIP Settings as an example.Step 1. Navigate to the settings app in your android source folder. For me it's:
cd ~/android/system/packages/apps/Settings/
From here on out, any files I refer to are relative from this location.
Step 2. Open the settings_header.xml file.
vim ./res/xml/settings_headers.xml
Here, I'll add a bunch of <header>s.
After editing, my settings_header.xml looks like this:
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> <!--4Com Settings Header --> <header android:id="@+id/four_com_setting" android:title="@string/four_com_settings_title" /> <!-- SIP Settings --> <header android:id="@+id/sip_settings" android:fragment="com.android.settings.SipPhoneSettings" android:icon="@drawable/ic_settings_date_time" android:title="@string/sip_settings_title" /> <!-- WIRELESS and NETWORKS --> <header android:id="@+id/wireless_section" android:title="@string/header_category_wireless_networks" /> ...
You'll notice that I've added 2 headers. One is with icon and and fragment and one is without. This is so that we have this effect:
The header tag without fragment/icon created a simple label whereas the one with said properties created a clickable one.
Step 3.
Create your settings file like so:
touch ./res/xml/sip_settings.xml
and edit it so that it looks something like this:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/sip_phone_setting">
<EditTextPreference
android:key="sip_extension_number"
android:title="@string/extension_number"
android:digits="0123456789"/>
<EditTextPreference
android:key="sip_server_host"
android:title="@string/server_host"
android:digits=".0123456789"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/sip_credentials_setting">
<EditTextPreference
android:key="sip_credentials_username"
android:title="@string/sip_username"/>
<EditTextPreference
android:key="sip_credentials_password"
android:title="@string/sip_password"/>
</PreferenceCategory>
</PreferenceScreen>
touch ./res/xml/sip_settings.xml
and edit it so that it looks something like this:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/sip_phone_setting"> <EditTextPreference android:key="sip_extension_number" android:title="@string/extension_number" android:digits="0123456789"/> <EditTextPreference android:key="sip_server_host" android:title="@string/server_host" android:digits=".0123456789"/> </PreferenceCategory> <PreferenceCategory android:title="@string/sip_credentials_setting"> <EditTextPreference android:key="sip_credentials_username" android:title="@string/sip_username"/> <EditTextPreference android:key="sip_credentials_password" android:title="@string/sip_password"/> </PreferenceCategory> </PreferenceScreen>
Step 4.
You may have noticed that we are referring to a lot of @strings in the XML files above. I've added the following entries to my strings.xml file:<string name="sip_phone_setting">SIP Phone Settings</string> <string name="extension_number">Extension number</string> <string name="sip_credentials_setting">SIP Credentials</string> <string name="server_host">Server Host</string> <string name="sip_username">Username</string> <string name="sip_password">Password</string> <string name="sip_contact_server">SIP Contact Server</string>
which can be found here:
cd ./res/values/strings.xml
Step 5.
Finally, we want to create and edit the SipPhoneSettings.java file.touch ./src/com/android/settings/SipPhoneSettings.java
vim ./src/com/android/settings/SipPhoneSettings.java
Mine ended up looking like this:
public class SipPhoneSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { //Define the keys that will be stored in Settings.System public static final String EXCHANGE_KEY = "sip_extension_number"; public static final String HOST_KEY = "sip_server_host"; public static final String USERNAME_KEY = "sip_credentials_username"; public static final String PASSWORD_KEY = "sip_credentials_password"; //Have references to the different preferences that you want stored private EditTextPreference mExchangePreference; private EditTextPreference mHostPreference; private EditTextPreference mUsernamePreference; private EditTextPreference mPasswordPreference; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource addPreferencesFromResource(R.xml.sip_settings); //Fetch the preferences mExchangePreference = (EditTextPreference) findPreference(EXCHANGE_KEY); mHostPreference = (EditTextPreference) findPreference(HOST_KEY); mUsernamePreference = (EditTextPreference) findPreference(USERNAME_KEY); mPasswordPreference = (EditTextPreference) findPreference(PASSWORD_KEY); //Set their onPreferenceChange listeners mExchangePreference.setOnPreferenceChangeListener(this); mHostPreference.setOnPreferenceChangeListener(this); mUsernamePreference.setOnPreferenceChangeListener(this); mPasswordPreference.setOnPreferenceChangeListener(this); } public boolean onPreferenceChange(Preference preference, Object newValue){ final String key = preference.getKey(); // Get the key for the change String putVal = (String) newValue; //All changes will be string //in my page. //Add the new value to the corresponding key. if(EXCHANGE_KEY.equals(key)) { Settings.System.putString(getContentResolver(), EXCHANGE_KEY, putVal); } else if(HOST_KEY.equals(key)) { Settings.System.putString(getContentResolver(), HOST_KEY, putVal); } else if(USERNAME_KEY.equals(key)) { Settings.System.putString(getContentResolver(), USERNAME_KEY, putVal); } else if(PASSWORD_KEY.equals(key)) { Settings.System.putString(getContentResolver(), PASSWORD_KEY, putVal); } return true; } }
Further Reading
1. Check out the subclasses for Preference for EditTextPreference alternatives. http://developer.android.com/reference/android/preference/Preference.html2. You can do a lot of cool things with the settings_header your settings XML. Check this link for a detailed list: http://developer.android.com/reference/android/preference/PreferenceActivity.html
Modifying the Settings app by Can Orhan is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.