In PSLab android app, we have included sensor instruments which use either inbuilt sensor of smartphone or external sensor to record sensor data. For example, Lux Meter uses the light sensor to record lux data but the problem is that these instruments doesn’t contain settings option to configure the sensor record-setting like which sensor to use, change the update period etc.
Therefore, we need to create a settings page for the Lux Meter instrument which allows the user to modify the properties of the sensor instrument. For that I will use Android Preference APIs to build a settings interface that is similar to setting activity in any other android app.
The main building block of the settings activity is the Preference object. Each preference appears as a single setting item in an activity and it corresponds to key-value pair which stores the settings in default Shared Preferences file. Every time any setting is changed by the user the Android will store the updated value of the setting in the default shared preferences which we can read in any other activity across the app.
In the following steps I will describe instruction on how to create the setting interface in Android app:
Step1 Include the dependency
First, we need to include the dependency for v7 Preference Support Library by including the following code:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:preference-v7:23.1.1'
}
Step 2 Creating the preferences screen in XML
For this step, I have created a preference screen which will be inflated when the settings fragment is being created.
I created a file named “lux_meter_settings.xml” and place it in the res/xml/ directory.
The root node for the XML file must be a <PreferenceScreen> element. We have to add each Preference within this element. Each child I added within the <PreferenceScreen> element appears as a single item in the list of settings.
The preference which I have used are:
<EdittextPreference> This preference opens up a dialog box with edit text and stores whatever value is written by the user in the edit text. I have used this preference for inputting update period and high limit of data during recording.
<CheckboxPreference> shows an item with a checkbox for a setting that is either enabled or disabled. The saved value is a boolean (true if it’s checked). I have used this preference for enabling or disabling location data with the recorded data.
<ListPreference> opens a dialog with a list of radio buttons. The saved value can be any one of the supported value types. I have used this preference to allow the user to choose between multiple sensor types.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference
android:key="setting_lux_update_period"
android:title="@string/update_period"
android:dialogTitle="@string/update_period"
android:defaultValue="1000"
android:dialogMessage="Please provide time interval(in ms) at which data will be updated"
android:summary="Update period is 900ms"/>
<EditTextPreference
android:key="setting_lux_high_limit"
android:title="High Limit"
android:dialogTitle="High Limit"
android:defaultValue="2000"
android:dialogMessage="Please provide maximum limit of LUX value to be recorded"
android:summary="High Limit is 2000 Lux"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="include_location_sensor_data"
android:summary="Include the location data in the logged file"
android:title="Include Location Data" />
</PreferenceScreen>
The above XML file will produce a layout as shown in Figure 1 below:
Step 3 Implementing the backend of setting interface
As android Documentation clearly states:
As your app’s settings UI is built using Preference objects instead of View objects, you need to use a specialized Activity or Fragment subclass to display the list settings:
|
Therefore, I first created an Activity named “SettingsActivity” which will act as a host for a Fragment. This gist contains code for SettingsActivity which I defined in the PSLab android app which will show the Setting Fragment.
Now, for setting fragment I have created a new fragment and name it “LuxMeterSettingsFragment” and make that fragment class extends the PreferenceFragmentCompat class and for which I needed to add this import statement.
import android.support.v7.preference.PreferenceFragmentCompat;
And then inside the SettingsFragment, I overridden the following method like this:
@Override
public void onCreatePreferences(Bundle savedInstanceState,
String rootKey) {
setPreferencesFromResource(R.xml.lux_meter_settings, rootKey);
}
This method is called when the Android is creating the Preferences that is when we need to call the method ‘setPreferencesFromResource()’ and pass the resource file in which we have defined our preferences along with the root key which comes as a parameter. Here, the Android will create preferences referred by the key which we have provided and initialize it to the default value in the default SharedPreferences file.
Step 4 Providing setting option to navigate to setting activity
First I included a setting option in the menu file which is getting inflated in the Lux Meter Activity toolbar as shown in below code.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
...
<item
android:id="@+id/settings"
android:title="@string/lux_meter_settings"
app:showAsAction="never" />
</menu>
Then, heading over to Lux Meter Activity in the onOptionItemSelected() method I added below code in which I created intent to open Setting Activity when the setting option is selected.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
case R.id.settings:
Intent settingIntent = new Intent(this, SettingsActivity.class);
settingIntent.putExtra("title", "Lux Meter Settings");
startActivity(settingIntent);
break;
}
After this step, we can see the settings option in Lux Meter Activity as shown in Figure 2
To see if its working opens the app -> open Lux Meter Instrument-> Open Overflow Menu -> click on Lux Meter Setting Option to open settings.
Here we can the Lux Meter Setting as shown by the Figure 3.
Step 5 Implementing listener for change in Preferences item
Now we can also implement a listener by making SettingsFragment class implement SharedPreference.OnSharedPreferenceChangeListener interface and then overriding the onSharedPreferenceChanged() method.
Now, to register this listener with the Preference Screen which we will do it in the onResume() method of the fragment and deregister the listener in the onPause() method to correspond with the lifecycle of the fragment.
@Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
Thus we have successfully implemented settings for the Lux Meter Instrument.
Resources
- Adding Settings to an App – Google Developer Fundamental Course Article on how to add settings.
- Gist – Setting Activity implementation – The gist used for setting activity in the app