Introduction
Every app involves data. Most data are supplied by users through the various input controls, such as text field, check box, radio group, spinner, and button. While some data is transient, most will require to stay or persist even after the app has stopped running. Android provides many ingenious technologies for storing persistent data locally.
In this article, you will start by learning how to implement and handle input controls of text field, check box, radio group, spinner, and button. You will then learn to store and retrieve data using Shared Preferences.
Setting the Stage
On your favorite Android IDE, start a new Android app project. Let’s give it an application name of “AndroidInputNStorage” and a domain name of “peterleowblog.com“. The resulting package name of your project will be “com.peterleowblog.androidinputnstorage“.
In the “res” folder of the project, replace the content of the “strings.xml” with the following string resources that will be used in the project.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Android Input and Storage</string>
<string name="action_settings">Settings</string>
<string name="shared_preferences">Shared Preferences</string>
<string name="email">Email</string>
<string name="gender">Gender</string>
<string name="female">Female</string>
<string name="male">Male</string>
<string name="hobbies">Hobbies</string>
<string name="coding">Coding</string>
<string name="writing">Writing</string>
<string name="jogging">Jogging</string>
<string name="zodiac">Zodiac</string>
<string name="save_me">Save Me</string>
<string name="retrieve">Get Me</string>
<string-array name="zodiac">
<item>Aries</item>
<item>Taurus</item>
<item>Gemini</item>
<item>Cancer</item>
<item>Leo</item>
<item>Virgo</item>
<item>Libra</item>
<item>Scorpio</item>
<item>Sagittarius</item>
<item>Capricorn</item>
<item>Aquarius</item>
<item>Pisces</item>
</string-array>
</resources>
Handling Input
Create a new activity called “SharedPreferencesActivity” with its layout file “activity_shared_preferences.xml”. Replace the content in the “activity_shared_preferences.xml” with the following XML code:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="@string/shared_preferences"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:ems="10"
android:id="@+id/txtEmail"
android:layout_below="@+id/textView4"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/email"
android:id="@+id/textView4"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/gender"
android:id="@+id/textView5"
android:layout_below="@+id/txtEmail"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView5"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/radioGroupGender">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/male"
android:id="@+id/radMale"
android:checked="false" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/female"
android:id="@+id/radFemale"
android:checked="false" />
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/hobbies"
android:id="@+id/textView6"
android:layout_below="@+id/radioGroupGender"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/coding"
android:id="@+id/chkCoding"
android:onClick="onCheckboxClicked"
android:checked="false"
android:layout_below="@+id/textView6"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/writing"
android:id="@+id/chkWriting"
android:onClick="onCheckboxClicked"
android:layout_below="@+id/chkCoding"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:checked="false" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/jogging"
android:id="@+id/chkJogging"
android:onClick="onCheckboxClicked"
android:layout_below="@+id/chkWriting"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:checked="false" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/zodiac"
android:id="@+id/textView7"
android:layout_below="@+id/chkJogging"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/spinnerZodiac"
android:layout_below="@+id/textView7"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save_me"
android:id="@+id/btnSave"
android:onClick="save"
android:layout_below="@+id/spinnerZodiac"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/retrieve"
android:onClick="retrieve"
android:id="@+id/btnRetrieve"
android:layout_alignParentBottom="true"
android:layout_alignRight="@+id/spinnerZodiac"
android:layout_alignEnd="@+id/spinnerZodiac" />
</RelativeLayout>
</ScrollView>
The “activity_shared_preferences.xml” will render a UI page as shown in Figure 1:
The user interface (UI) comprises the following controls:
- One “EditText” text field for email input.
- One “RadioGroup” control with two “RadioButtons” for gender selection.
- Three “CheckBox” controls for hobbies selection.
- One “Spinner” control for zodiac selection.
- Two “Button” controls – one each for saving and retrieving data respectively.
The subsequent sections of this chapter will guide you to complete the code for the “SharedPreferencesActivity.java”:
Initialization
In the “SharedPreferencesActivity.java”, add the following code to import the necessary Android packages, and declare and initialize class variables:
package com.peterleowblog.androidinputnstorage;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Toast;
public class SharedPreferencesActivity extends Activity {
private String email;
private String gender;
private String hobbies;
private String zodiac;
public static final String STORAGE_NAME = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shared_preferences);
email = "";
gender = "";
hobbies = "";
zodiac = "";
}
}
Handling “EditText” Field
In order to capture input value in the “Email” “EditText” field, you will must first find out the value of the “android:id” attribute from its “<EditText>” node in the “activity_shared_preferences.xml” , which is:
android:id="@+id/txtEmail"
This “Email” “EditText” field can then be reference in Java code as:
R.id.txtEmail
Similarly, you can access all Android UI controls in Java code using the approach above.
The Java code to get the value from this “Email” “EditText” field is:
((EditText)findViewById(R.id.txtEmail)).getText().toString();
The Java code to set a value to this “Email” “EditText” field is:
((EditText)findViewById(R.id.txtEmail)).setText("blahblah@gmail.com");
You will add the code to get and set the value of “Email” “EditText” field to “SharedPreferencesActivity.java” later on.
Handling RadioGroup
In order to capture the item selected in the Gender “RadioGroup” for further processing, set the “SharedPreferencesActivity” class as an “OnCheckedChangeListener“ to it. The process is as follows:
First, implement the “OnCheckedChangeListener” interface on the “SharedPreferencesActivity” class.
public class SharedPreferencesActivity extends Activity implements RadioGroup.OnCheckedChangeListener {
}
Next, add the method for the “OnCheckedChangeListener” interface to the “SharedPreferencesActivity” class.
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
int radioButtonId = radioGroup.getCheckedRadioButtonId();
RadioButton radioButton = (RadioButton)radioGroup.findViewById(radioButtonId);
gender = radioButton.getText().toString();
}
Lastly, inside the “onCreated()” method, add the code to set the “SharedPreferencesActivity” class as an “OnCheckedChangeListener“ to the “RadioGroup” object.
RadioGroup radioGroupGender = (RadioGroup) findViewById(R.id.radioGroupGender);
radioGroupGender.setOnCheckedChangeListener(this);
You have completed the code for the “RadioGroup” control. Whenever the user makes a selection on the Gender “RadioGroup”, it will trigger the “onCheckedChanged()” event handler method which contains code to assign the selected gender item to the “gender” variable.
Handling CheckBox
To capture the item selected in the Hobbies “CheckBox” controls for further processing, the app have to implement an “onClick()” event handler on all the “CheckBox” controls. The process is as follows:
First, notice that an ‘android:onClick=”onCheckboxClicked”‘ attribute has been added to all the “<checkbox>” nodes in the “activity_shared_preferences.xml” to bind them to a method called “onCheckboxClicked()” that will handle the click event.
android:onClick="onCheckboxClicked"
Next, add the “onCheckboxClicked()” method to the “SharedPreferencesActivity” class to handle the “onClick()” event on all the “CheckBox” controls.
public void onCheckboxClicked(View view) {
CheckBox chkJogging = (CheckBox) findViewById(R.id.chkJogging);
CheckBox chkCoding = (CheckBox) findViewById(R.id.chkCoding);
CheckBox chkWriting = (CheckBox) findViewById(R.id.chkWriting);
StringBuilder sb = new StringBuilder();
if (chkJogging.isChecked()) {
sb.append(", " + chkJogging.getText());
}
if (chkCoding.isChecked()) {
sb.append(", " + chkCoding.getText());
}
if (chkWriting.isChecked()) {
sb.append(", " + chkWriting.getText());
}
if (sb.length() > 0) {
hobbies = sb.deleteCharAt(sb.indexOf(",")).toString();
} else {
hobbies = "";
}
}
You have completed the code for the “CheckBox” controls. Whenever the user checks or unchecked any of the hobbies “CheckBox” controls, it will trigger the “onCheckboxClicked()” method that contains the code to concatenate selected hobbies and assign them to the “hobbies” variable.
Handling Spinner
To populate the “Spinner” with the zodiac data, create an “ArrayAdapter“, a subclass of “Adapter” class, to bridge the data source, i.e. the string array resource called “zodiac” in the “strings.xml” referenced to in code as “R.array.zodiac”, and the “View”, i.e. the “Spinner”. “ArrayAdapter” is also responsible for making a “TextView” to contain each item in the data source. To achieve this, add the following code to the “onCreated()” method:
Spinner spinnerZodiac = (Spinner) findViewById(R.id.spinnerZodiac);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.zodiac, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerZodiac.setAdapter(adapter);
In order to capture the item selected in the Zodiac “Spinner” for further processing, set the “SharedPreferencesActivity” class as an “OnItemSelectedListener“ to it. The process is as follows:
First, implement the “OnItemSelectedListener” interface on the “SharedPreferencesActivity” class.
public class SharedPreferencesActivity extends Activity implements RadioGroup.OnCheckedChangeListener, AdapterView.OnItemSelectedListener {
}
Next, add the methods for the “OnItemSelectedListener” interface to the “SharedPreferencesActivity” class.
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
zodiac = parent.getItemAtPosition(position).toString();
}
public void onNothingSelected(AdapterView<?> parent) {
}
Lastly, go back to the “onCreated()” method, add the code to set the “SharedPreferencesActivity” class as an “OnItemSelectedListener“ to the “Spinner” object.
spinnerZodiac.setOnItemSelectedListener(this);
You have completed the code for the “Spinner” control. Whenever the user makes a selection on the Zodiac “Spinner”, it will trigger the “onItemSelected()” event handler method which contains code to assign the selected zodiac item to the “zodiac” variable.
Handling “Save Me” Button
When the user clicks on the “Save Me” button, the app will save the user’s input data to some storage. In order to do this, the app have to implement an “onClick()” event handler on the “Save Me” button. The process is as follows:
First, notice that an ‘android:onClick=”save”‘ attribute has been added to the “Save Me” “<Button>” nodes in the “activity_shared_preferences.xml” to bind the “Save Me” button to a method called “save()” that will handle its click event.
android:onClick="save"
Next, add the “save()” method to the “SharedPreferencesActivity” class to handle the “onClick()” event on the “Save Me” button. Note that the code for getting value from the “Email” “EditText” field is included.
public void save(View view) {
email = ((EditText)findViewById(R.id.txtEmail)).getText().toString();
}
You have completed the code for the “Save Me” button. Whenever the user click on this button, it will trigger the “save()” method that contains code to capture the Email input in the “EditText” text field using the “getText()“ method and assign it to the “email” variable before saving to some storage. The actual code for saving to storage will differ depending on the storage types.
Handling “Get Me” Button
When the user clicks on the “Get Me” button, the app will retrieve stored data and populate the UI controls with the data. Similar to the “Save Me” button, in order to do this, the app have to implement an “onClick()” event handler on the “Get Me” button. The process is as follows:
First, notice that an ‘android:onClick=”retrieve”‘ attribute has been added to the “Get Me” “<Button>” nodes in the “activity_shared.xml” to bind the “Get Me” button to a method called “retrieve()” that will handle its click event.
android:onClick="retrieve"
Next, add the “retrieve()” method to the “SharedPreferencesActivity” class to handle the “onClick()” event on the “Get Me” button.
public void retrieve(View view) {
setupUI();
}
You have completed the code for the “Get Me” button. Whenever the user click on this button, it will trigger the “retrieve()” method that contains code to retrieve stored data from some storage, assign the data to the respective class variables, i.e. “email”, “gender”, “hobbies”, and “zodiac”, and call a method “setupUI()” to display the data on the respective UI controls.
Writing “setupUI()” Method
First, insert the “setupUI()” method into the “SharedPreferencesActivity” class:
protected void setupUI(){
}
Start to add the code bit by bit to the “setupUI()” method. First is the code to set the retrieved email value assigned to the “email” variable to the “Email” “EditText” field using “setText()“ method.
((EditText)findViewById(R.id.txtEmail)).setText(email);
Continue to add this code to select the “Gender” “RadioButton” control that corresponds to the retrieved gender value assigned to the “gender” variable.
RadioButton radMale = (RadioButton)findViewById(R.id.radMale);
RadioButton radFemale = (RadioButton)findViewById(R.id.radFemale);
if (gender.equals("Male")){
radMale.setChecked(true);
} else if (gender.equals("Female")){
radFemale.setChecked(true);
} else {
radMale.setChecked(false);
radFemale.setChecked(false);
}
Continue to add this code to check the “Hobbies” “CheckBox” controls that corresponds to the retrieved hobbies contained in the “hobbies” variable.
CheckBox chkCoding = (CheckBox)findViewById(R.id.chkCoding);
CheckBox chkWriting = (CheckBox)findViewById(R.id.chkWriting);
CheckBox chkJogging = (CheckBox)findViewById(R.id.chkJogging);
chkCoding.setChecked(false);
chkWriting.setChecked(false);
chkJogging.setChecked(false);
if (hobbies.contains("Coding")) {
chkCoding.setChecked(true);
}
if (hobbies.contains("Writing")) {
chkWriting.setChecked(true);
}
if (hobbies.contains("Jogging")) {
chkJogging.setChecked(true);
}
Finally, set the selected item of the “Zodiac” “Spinner” to the retrieved zodiac value assigned to the “zodiac” variable.
Resources resource = getResources();
String[] zodiacArray = resource.getStringArray(R.array.zodiac);
for(int i = 0; i < zodiacArray.length; i++){
if(zodiacArray[i].equals(zodiac)){
((Spinner)findViewById(R.id.spinnerZodiac)).setSelection(i);
}
}
Congratulation! You have created an activity called “SharedPreferencesActivity” and learned the different ways of handling input types. You are now ready to implement the shared preferences storage.
Shared Preferences
Android provides the “SharedPreferences“ class that allows an app to persist primitive type of data, such as string, int, long, float, and boolean, in the form of key-value pairs. For example,
KEY | VALUE |
“email” | “xyz@gmail.com” |
“gender” | “Male” |
Learning the Basics
To start using “SharedPreferences”, an app must first obtain an instance of it by calling either one of these two methods—”getPreferences()“ or “getSharedPreferences()“ .
- “getPreferences()” method returns one “SharedPreferences” file that is private to the current activity. For example,
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
- “getSharedPreferences()” method returns one of the multiple “SharedPreferences” files identified by a name which is passed as the first parameter. If the named preferences file does not exist, it will be created when you write and commit changes to it. For example,
String STORAGE_NAME = "mySharedPreferences";
SharedPreferences sharedPreferences = getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE);
The”MODE_PRIVATE“ parameter, which is the default, restricts the access to the “SharedPreferences” file to the calling app or apps that share the same user ID.
To write values to a “SharedPreferences” file, follow these steps:
- Call the “edit()“ method of the “SharedPreferences” instance to get a “SharedPreferences.Editor“ object. For example,
SharedPreferences.Editor editor = sharedPreferences.edit();
- Add values to the “SharedPreferences” using the appropriate “put<DataType>“ methods of the “SharedPreferences.Editor” object, such as “putBoolean()”, “putFloat()”, “putInt()”, “putLong()“, “putString()”, and “putStringSet()”. These methods take two parameters—the first parameter is the key while the second parameter the value of the preference. For example,
editor.putString("email", email);
- Call either “commit()“ or “apply()“ method of the “SharedPreferences.Editor” object to copy the changes made in the “SharedPreferences.Editor” to the “SharedPreferences“. For example,
editor.apply();
To read values from a “SharedPreferences”, simply call the appropriate “get<DataType>“ methods of the “SharedPreferences” instance, such as “getBoolean()”, “getFloat()”, “getInt()”, “getLong()”, “getString()”, and “getStringSet()”. These methods take two parameters—the first parameter is the key of the preference, and the second parameter the default value to return if the preference does not exist. For example,
email = sharedPreferences.getString("email", "");
Having learned the basic of “SharedPreferences”, you will now add a “SharedPreferences” storage type to the project.
Making It Happen
To implement shared preferences storage on “SharedPreferencesActivity”, follow these steps:
- Assign “MySharedPreferences” to the “STORAGE_NAME” variable which will be the name of the “SharedPreferences” file.
public static final String STORAGE_NAME = "MySharedPreferences";
- Add the code for writing to the “SharedPreferences” file to the “save()” method.
public void save(View view) {
email = ((EditText)findViewById(R.id.txtEmail)).getText().toString();
SharedPreferences sharedPreferences = getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("email", email);
editor.putString("gender", gender);
editor.putString("hobbies", hobbies);
editor.putString("zodiac", zodiac);
editor.apply();
Toast.makeText(getApplicationContext(), "You have been saved!", Toast.LENGTH_SHORT).show();
}
- Add the code for reading from the “SharedPreferences” file to the “retrieve()” method.
public void retrieve(View view) {
SharedPreferences sharedPreferences = getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE);
email = sharedPreferences.getString("email", "");
gender = sharedPreferences.getString("gender", "");
hobbies = sharedPreferences.getString("hobbies", "");
zodiac = sharedPreferences.getString("zodiac", "");
setupUI();
}
Testing 1, 2, 3, …
Launch the app on a real device or an AVD, you should see the “Shared Preferences” page shown in Figure 1. On this page, enter an email, make some selections, and then click the “Save Me” button to save the input values to the “SharedPreferences” storage. Navigate away from the app, then navigate back to the “Shared Preferences” page again, click the “Get Me” button to retrieve and display the previously saved values. If you make changes on the “Shared Preferences” page, then click on the “Save Me” button without saving the changes, it will revert back to the saved values. It should work. Give yourself a pat on the back.
Homework
Do not stop here! Challenge yourself to add a delete button and the code to the “SharedPreferencesActivity” to delete all values from the shared preferences that you have saved. I shall leave it as your homework.
Follow-up
Congratulation! You have completed an app that handles different input types and stores the input data on shared preferences storage. I hope you will attempt the homework provided in this article as it will help to enhance your knowledge and enrich your learning experience.
The post Android Input and Shared Preferences appeared first on Peter Leow's Code Blog.