Archive
Writing and Reading from SharedPreferences
SharedPreferences class allows you to save and retrieve primitive data types in key-value pairs. The data saved using SharedPreferences will be available even after your application is killed. This capability makes SharedPreferences suitable in different situations when user settings needs to be saved for example, or store data that can be used in different activities.
The data types that can be saved are booleans, floats, ints, longs, and strings.
To get an instance of SharedPreferences use the getSharedPreferences(String, int) method. The method takes 2 parameters: the name of the preference settings and the mode. (0 or MODE_PRIVATE for the default operation, MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE to control permissions)
To write values:
- Call edit() to get a SharedPreferences.Editor instance
- Add values with methods such as putInt() and putString().
- Call commit() to save values.
To read values use such methods as getString() and getInt() of SharedPreferences instance.
Here’s a simple usage of SharedPreferences class:
public class SharedPrefsActivity extends Activity {
public static final String PREFS_NAME = "MyApp_Settings";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
// Writing data to SharedPreferences
Editor editor = settings.edit();
editor.putString("key", "some value");
editor.commit();
// Reading from SharedPreferences
String value = settings.getString("key", "");
Log.d(TAG, value);
}
}
Please visit the Android Tutorials page for more tutorials.
How to verify an RSS Feed if New Articles have been published.
Recently I built an rss app for a site that publishes daily IT News – ITMoldova.com. The main feature of application is to launch a service in background (at a given interval of time), and check if new articles have been published on http://itmoldova.com site. If it turns out that new articles have been published, then fire a notification message and notify the user about this, something like this: “4 New Articles Published on ITMoldova.com”.
The mechanism to identify if new articles have been published on the site (and how many) is pretty straightforward: when the application is installed and launched for the first time, it parses the Rss Feed and creates a new entry in the SharedPreferences with the value of <pubDate> element, of the first item from the rss list (pubDate = publication date). Then, everytime the service starts, it parses the RSS Feed and checks the value of first item from the rss list against the value stored in SharedPreferences, if the value stored in SharedPreferences is less than value returned by the service, then it means that there are new articles and it’s time to notify the user! Lastly, update the SharedPreferences with the most recent pubDate.
For the sake of simplicity and keeping things consistent, I will post here only snippets of most relevant code, but this will be good enough to give you an idea about how things works.
To compare the dates we need to convert them to milliseconds. The getTime() method of Date class can help us return the number of milliseconds of a given date:
Date date=new Date(); int timeMilliseconds=date.getTime();
Below is the implementation of verifyDates(String, String) method that will be used by the Service. The method takes 2 string parameters, the pubDate of rss item, and the pubDate stored in SharedPreferences.
public class Tools {
public int newArticles;
public boolean hasMoreArticles = true;
public void verifyDates(String rssPubDate, String sharedPrefLastPubDate) {
if (hasMoreArticles) {
SimpleDateFormat df = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
Date dLastPubDate = null;
Date dRssPubDate = null;
try {
dLastPubDate = df.parse(sharedPrefLastPubDate.substring(5));
dRssPubDate = df.parse(rssPubDate.substring(5));
} catch (ParseException e) {
Log.d("GREC", "Exception in verifayDates: " + e.getMessage());
e.printStackTrace();
}
//We want to count how many new articles were published.
if (dRssPubDate.getTime() > dLastPubDate.getTime()) {
newArticles++;
} else {
hasMoreArticles = false;
}
}
}
}
The service will parse the Rss Feed and do the comparison. Also, it will launch a status bar notification if it turns out that new articles were published.
public class RssService extends IntentService {
public RssService() {
super("ITMoldovaRssService");
}
@Override
protected void onHandleIntent(Intent intent) {
// Retrieve the date from SharedPreferences
String lastPubDate = getDateFromSharedPrefs();
// The AndroidFeedParser class helps us parse the Rss Feed.
AndroidFeedParser parser;
try {
parser = new AndroidFeedParser(new URL("http://itmoldova.com/feed/"));
List<Message> list = parser.parse();
if (list != null) {
for (int i = 0; i < list.size(); i++) {
// Verify the pubDate of each item, against pubDate stored in SharedPreferences
tools.verifyDates(list.get(i).getDate(), lastPubDate);
}
// Get the last pubDate and save it to SharedPreferences.
lastPubDate = list.get(0).getDate();
saveToSharedPreferences(lastPubDate);
}
} catch (MalformedURLException e) {
Log.d("GREC", "Malformed URL Exception: " + e.getMessage());
e.printStackTrace();
}
if (tools.newArticles > 0) {
displayNotification();
} else {
Log.d("GREC", "No new articles ");
}
}
}
The service begins with parsing the Rss Feed and return the list of items:
List<Message> list = parser.parse();
then iterate through it comparing the publication date:
for (int i = 0; i < list.size(); i++) {
// Verify the pubDate of each item, against pubDate stored in SharedPreferences
tools.verifyDates(list.get(i).getDate(), lastPubDate);
}
and then ends getting the most recent publication date and saving it to SharedPreferences:
// Get the last pubDate and save it to SharedPreferences. lastPubDate = list.get(0).getDate(); saveToSharedPreferences(lastPubDate);
If it turns out that new articles were published, display a status bar notification.
if (tools.newArticles > 0) {
displayNotification();
}
How to parse an XML feed and how to display a status bar notification are some helper topics you may need to take a look in order to fully complete this task.
Drawing Shapes in Android
In this post I would like to share my findings about defining and using shapes. A shape is an XML file that defines a geometric shape, including strokes, colors and gradients
To define a shape:
1. Create a new Android XML file in the folder res/drawable
2. Make sure the root element of the file is <shape >. (If it’s not, then change it manually)
3. Inside the <shape> element, press CTRL + Space to reveal all the available elements you can use to define a shape:
As you can see, the elements are pretty self explanatory. To reveal the attributes of an element, put the cursor inside that element and press CTRL + Space:
4. Once the shape is defined, you can specify it as a background resource to any view: android:background=”@drawable/myshape”
res/drawable/boxbg.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <stroke android:width="2dp" android:color="#FFFFFF" /> <corners android:radius="5dp" /> <gradient android:angle="270" android:centerColor="#6E7FFF" android:endColor="#142FFC" android:startColor="#BAC2FF" /> </shape>
res/drawable/box2bg.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#4D9611" /> <stroke android:width="4dp" android:color="#FFFB00" /> </shape>
res/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!-- First box, boxbg.xml -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_margin="20dp"
android:background="@drawable/boxbg"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
android:textColor="#000"
android:textSize="20dp" />
</LinearLayout>
<!-- Second box, box2bg.xml -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_margin="20dp"
android:background="@drawable/box2bg"
android:orientation="vertical"
android:padding="7dp" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
android:textColor="#FFF"
android:textSize="20dp" />
</LinearLayout>
</LinearLayout>
The final output should look like this:
Defining Global Variables in Android
At some point in your development process you may need to have several variables across application.
In this post I want to describe 2 ways through you can define global variables in Android: using a singleton class, and by extending the Android’s Application class.
One of the simplest ways (it does not mean that is one of the best) to have global variables is to declare a singleton class:
public class Globals{
private static Globals instance;
// Global variable
private int data;
// Restrict the constructor from being instantiated
private Globals(){}
public void setData(int d){
this.data=d;
}
public int getData(){
return this.data;
}
public static synchronized Globals getInstance(){
if(instance==null){
instance=new Globals();
}
return instance;
}
}
To use this class you get an instance first, and then do what you want with data:
Globals g = Globals.getInstance(); g.setData(100); .... int data=g.getData();
Notice that we do not instantiate the object by calling “new”, in fact this wouldn’t be allowed as we declared the constructor private, so its not visible. Instead we call the getInstance() method and return our static object.
The second way to define global variables is by extending the Application class. This is the base class for maintaining global application state.
a) Create a new class that extends Application.
public class Globals extends Application{
private int data=200;
public int getData(){
return this.data;
}
public void setData(int d){
this.data=d;
}
}
b) Add the class to the AndroidManifest file as an attribute of <application> tag:
<application android:name=".Globals" .... />
c) Then you can access your global data from any Activity by calling getApplication()
Globals g = (Globals)getApplication(); int data=g.getData();
I said that using the Singleton pattern it’s one of the simplest ways to define global variables, but I mentioned also that it does not mean that it’s one of the best ways to do it. In fact this is quite a controversial subject.
You may believe that when a static variable is initialized it stays so for the entire life of the application, however this does not seem to be true everytime. Sometimes, there are situations when some static variables bound to activities happens to be uninitialized even they have been initialized.
This makes the static singleton approach not one of the best for keeping global variables, though the official Android documentation seems to encourage using them: “There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way.”
Understanding AsyncTask – Once and Forever
This article describes the usage of AsyncTask class in Android.
Android modifies the user interface via one thread, the so called UI Thread. If you perform a long running operation directly on the UI Thread, for example downloading a file from the internet, the user interface of your application will “freeze” until the corresponding task is finished. When this happens it is very easy for the user to perceive your application as slow.
As a concrete example of a bad implementation and what happens when a long running operation is done on the UI Thread, I want to refer to one of my previous tutorials: Creating A Simple RSS Application in Android. Well, that application is working fine, and it does what it is supposed to do – parse an XML feed and display the headlines in a ListView. The “vulnerability” of that application is that the network access is done directly on the UI Thread which makes the application to “freeze” while the XML feed is downloaded (take a look at point number 5 to see).
When I created that tutorial I wanted to make it as simple as possible without dealing with more advanced topics like asynchronous tasks. The intent of tutorial was to show the working process with feeds on a high level. But I promise you, by the end of this article you will be able to fix it and have a Cool Rss App that runs smoothly!
To provide a good user experience all long running operations in an Android application should run asynchronously. To achieve this we will be using the AsyncTask class.
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
In order to use the AsyncTask class, you must extend it and override at least the doInBackground() method.
The most common methods you will need to implement are these:
1. onPreExecute() – called on the UI thread before the thread starts running. This method is usually used to setup the task, for example by displaying a progress bar.
2. doInBackground(Params…) – this is the method that runs on the background thread. In this method you should put all the code you want the application to perform in background. Referring to our Simple RSS Aplication, you would put here the code that downloads the XML feed and does the parsing. The doInBackground() is called immediately after onPreExecute(). When it finishes, it sends the result to the onPostExecute().
3. onProgressUpdate() - called when you invoke publishProgress() in the doInBackground().
4. onPostExecute(Result) – called on the UI thread after the background thread finishes. It takes as parameter the result received from doInBackground().
AsyncTask is a generic class, it uses 3 types: AsyncTask<Params, Progress, Result>.
Params– the input. what you pass to the AsyncTaskProgress– if you have any updates, passed to onProgressUpdate()Result– the output. what returns doInBackground()
Once a task is created, it can be executed like this:
new DownloadTast().execute(url1, url2, urln);
This is a simple skeleton of an AsyncTask implementation.
public class AsyncTaskTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Starting the task. Pass an url as the parameter.
new PostTask().execute("http://feeds.pcworld.com/pcworld/latestnews");
}
// The definition of our task class
private class PostTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
displayProgressBar("Downloading...");
}
@Override
protected String doInBackground(String... params) {
String url=params[0];
// Dummy code
for (int i = 0; i <= 100; i += 5) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return "All Done!";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
updateProgressBar(values[0]);
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dismissProgressBar();
}
}
}
AsyncTasks are great for performing tasks in a separate thread, they have however one weakness. While the AsyncTask is in the middle of the work and the screen of device is rotated, you’ll notice that the application crashes. This happens because when rotating the device screen a configuration change occurs, which will trigger the Activity to restart. The AsyncTask reference to the Activity is invalid, an onPostExecute() will have no effect on the new Activity. How to handle this sort of issues is described in: Dealing with AsyncTask and Screen Orientation, which I highly recommend reading it if you are concerned to deliver stable Android applications.
Creating a Preference Activity in Android
In this tutorial we will build a preference screen using the PreferenceActivity class. Our main activity will contain 2 Buttons and a TextView. One of the buttons will open the preference screen, and the other will display the values stored in SharedPreferences.
The final output should look like this:
And here’s what happens when clicking on the Username/Password fields (left screenshot), and the List Preference field (right screenshot):
At a first glance it may look a bit intimidating, but as you will see later, actually it’s quite easy to define a preference screen. Trust me, I’m an engineer! (c)
To put all this things together in a fashionable way, we will be using the PreferenceActivity class. The good thing about this class is that the definition of layout file it’s very simple. It provides custom controls specially designed for preference screens. Another good thing is that you don’t need to write code to save the values from preference screen to SharedPreferences. All this work is done automatically by the activity.
So, lets begin creating our preference screen
1. Create a new project in Eclipse:
Project: PreferenceDemoTest
Activity: PreferenceDemoActivity
2. Create a new Android XML file prefs.xml in the folder res/xml/. This file will contain the layout for our preference screen:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:summary="Username and password information"
android:title="Login information" >
<EditTextPreference
android:key="username"
android:summary="Please enter your login username"
android:title="Username" />
<EditTextPreference
android:key="password"
android:summary="Enter your password"
android:title="Password" />
</PreferenceCategory>
<PreferenceCategory
android:summary="Username and password information"
android:title="Settings" >
<CheckBoxPreference
android:key="checkBox"
android:summary="On/Off"
android:title="Keep me logged in" />
<ListPreference
android:entries="@array/listOptions"
android:entryValues="@array/listValues"
android:key="listpref"
android:summary="List preference example"
android:title="List preference" />
</PreferenceCategory>
</PreferenceScreen>
Notice that the root element of prefs.xml is the <PreferenceScreen> element, and not a RelativeLayout or LinearLayout for example. When a PreferenceActivity points to this layout file, the <PreferenceScreen> is used as the root, and the contained preferences are shown.
<PreferenceCategory> – defines a preference category. In our example the preference screen is split in two categories: “Login Information” and “Settings”
<EditTextPreference> – defines a text field for storing text information.
<CheckBoxPreference> – defines a checkbox.
<ListPreference> – defines a list of elements. The list appears as group of radio buttons.
3. At this stage the prefs.xml might complain that the @array/listOptions and @array/listValues resources cannot be found.
To fix this create a new XML file array.xml in the folder res/values/. This file will contain the elements of the ListPreference.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="listOptions">
<item>Option 1</item>
<item>Option 2</item>
<item>Option 3</item>
</string-array>
<string-array name="listValues">
<item>1 is selected</item>
<item>2 is selected</item>
<item>3 is selected</item>
</string-array>
</resources>
The “listOptions” array defines the elements of the list, or with other words, the labels.
The “listValues” array defines the values of each element. These are the values that will be stored in the SharedPreferences. The number of list options and list values should match. The first list value is assinged to the first list option, the second value to the second option,… and so on.
4. Create a new class PrefsActivity.java that extends PreferenceActivity:
public class PrefsActivity extends PreferenceActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
Notice that instead of the traditional setContentView(), we use here addPreferencesFromResource() method. This inflates our prefs.xml file and uses it as the Activity’s current layout.
5. Add the PrefsActivity.java to the AndroidManifest file:
<application
......./>
<activity
android:name=".PrefsActivity"
android:theme="@android:style/Theme.Black.NoTitleBar" >
</activity>
</application>
6. Now, to test our preference activity lets modify the main.xml layout file by adding 2 Buttons and 1 TextView. One of the buttons will open the preference screen, and the other will display the values stored in SharedPreferences.
main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/btnPrefs" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Preferences Screen" /> <Button android:id="@+id/btnGetPreferences" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Display Shared Preferences" /> <TextView android:id="@+id/txtPrefs" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
7. Finally, modify the PreferenceDemoActivity to handle our logic implementation:
public class PreferenceDemoActivity extends Activity {
TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnPrefs = (Button) findViewById(R.id.btnPrefs);
Button btnGetPrefs = (Button) findViewById(R.id.btnGetPreferences);
textView = (TextView) findViewById(R.id.txtPrefs);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnPrefs:
Intent intent = new Intent(PreferenceDemoActivity.this,
PrefsActivity.class);
startActivity(intent);
break;
case R.id.btnGetPreferences:
displaySharedPreferences();
break;
default:
break;
}
}
};
btnPrefs.setOnClickListener(listener);
btnGetPrefs.setOnClickListener(listener);
}
private void displaySharedPreferences() {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(PreferenceDemoActivity.this);
String username = prefs.getString("username", "Default NickName");
String passw = prefs.getString("password", "Default Password");
boolean checkBox = prefs.getBoolean("checkBox", false);
String listPrefs = prefs.getString("listpref", "Default list prefs");
StringBuilder builder = new StringBuilder();
builder.append("Username: " + username + "\n");
builder.append("Password: " + passw + "\n");
builder.append("Keep me logged in: " + String.valueOf(checkBox) + "\n");
builder.append("List preference: " + listPrefs);
textView.setText(builder.toString());
}
}
Here we attach 2 listeners for each button and display the values retrieved from SharedPreferences in a TextView.
By this time you should compile and run successfully the application.
Working With Services In Android – IntentService
A service is an application component that can perform long-running operations in the background and it does not provide an user interface. For example, a service might handle network transactions, play music, perform file I/O, etc., all from the background.
Usually, there are two classes you can extend to create a service: you extend the Service class and override some callback methods, or extend the IntentService class and all you need to do is implement the onHandleIntent() method where you put all the code that should run in the background.
Extending the IntentService class is the simplest way to create a service. If you don’t need to handle multiple requests simultaneously, then this probably is the best option to choose.
In this post we will create a service using the IntentService class.
Well, our service won’t do much. This would be a proof-of-concept application, showing the creation process of a service. The mission of our service would be just to print a message in the LogCat, (pretty simple for a service
), but in a real application you would write of course more advanced code, like playing music, or performing some I/O operations for example.
1. Create a new project in Eclipse:
Project: ServiceTest
Activity: ServiceTestActivity
2. Create a new class, say MyService, and do as follows:
- Extend the IntentService
- Provide a constructor with no arguments that calls the super constructor, with a name as an argument.
- Override the onHandleIntent(Intent intent); method.
public class MyService extends IntentService{
// No-arg constructor is required
public MyService() {
super("MyService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("TAG", "Service started");
//....
// The rest of the code that needs to run in the background
//....
}
}
Note that it’s important that you provide a no-arg constructor, otherwise you may get an exception: InstantiationException
3. Register your service
Open the AndroidManifest file and add the following line as a child of <application> tag:
<application ...... <service android:name=".MyService" /> </application>
4. Start the service
To start a service the startService(intent) method is used, which takes as an argument an intent with the specified service.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Starting the service
Intent intent =new Intent(this, MyService.class);
startService(intent);
}












