The Problem
You have configuration variables and data that you want to share globally in your Android app. You want all Activities to be able to access and edit the same instance of application specific data.
Generic Solution
You could create a Configuration class loaded with static members or as a Singleton. Now you’ve got a shared, single instance of your configuration that can be accessed anywhere in your application. But there are 2 minor drawbacks to this method in the context of Android development.
- You now have to initialize your configuration in a separate class, in this case, your startup Activity.
- You’ll need to carry this new Configuration class around in all your projects.
Neither of these problems are critical, but let’s see if we can do better.
Android Solution
In Android it is possible to extend the Application class in order to store additional application specific information… like say configuration data. These additional members are then accessible in any Activity via the getApplicationContext() method.
The first step in this process is extending your app’s Application object. Android gives your app a generic Application object by default, so you may have never even had to look at this class directly. But as you’ll see below, its pretty simple to extend.
SampleApplication.java
public class SampleApplication extends Application { private String mStringValue; @Override public void onCreate() { // Here you could pull values from a config file in res/raw or somewhere else // but for simplicity's sake, we'll just hardcode values mStringValue = "SavageLook.com"; super.onCreate(); } public String getStringValue() { return mStringValue; } public void setStringValue(String value) { mStringValue = value; } }
As you can see above, extending the Application class as SampleApplication is quite simple. You add class members for each bit of configuration data you would like to share throughout your application. In this example, we are simply saving a String value (mStringValue) that can then be accessed and modified in any Activity in SampleApplication.
After you’ve added your members and any necessary getters/setters, you need to override the onCreate() method. In the onCreate() method you can then initialize your class members with your configuration data. You can do this any way you want. To keep the example simple, I hardcoded the configuration value (mStringValue), but I commonly store configuration data in JSON files in res/raw and load them into my extended Application object. I won’t get into those details, though, as that will likely be a whole other blog post. Make sure you call super.onCreate() when you are finished.
NOTE: It’s not necessary to initialize your members in the onCreate(). For application-wide configuration data you would likely always do it in onCreate(), but you are technically free to manipulate the extended Application object anywhere in your app code.
AndroidManifest.xml
version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yourdomain"
android:versionCode="1"
android:versionName="1.0">
android:icon="@drawable/icon"
android:label="@string/app_name"
android:name=".SampleApplication">
android:name=".SampleActivity">
>
android:name="android.intent.action.MAIN" />
android:name="android.intent.category.LAUNCHER" />
>
>
>
>
The final modification to make our Android app use the new SampleApplication class is setting it in the
OK, so now your app is using your new SampleApplication class. How do we access the stored data in its members? See the basic usage below.
Sample usage in any Activity
public class SampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SampleApplication sampleApp = (SampleApplication)getApplicationContext(); String localStr = sampleApp.getStringValue(); // perform operations on localStr sampleApp.setStringValue(localStr); // The rest of your Activity code... } }
All you have to do is call getApplicationContext() and cast it to the type of your new Application object (SampleApplication). The resulting SampleApplication object can now be used the get/set any of the members you defined for it in SampleApplication.java.
Summary
Now you have a solid, Android native way to share data globally in your app code. While I’m a big fan of portable solutions, I feel this Android specific one is worth to have a clear distinction between the onCreate() of my Application versus my Activities. Hopefully this walkthrough was clear because this is something you will likely do very frequently when developing Android apps.
One final note. I can already envision some lazy developers’ minds churning, “I can use this instead of Intent extras!”… Don’t! Intent extras have a specific interaction context which is important not only to functionality, but also to readability of your code. Don’t undo this by just feeding them into the global Application object. Extending your Application object is a complement to Intent extras, not a replacement.
[...] In case anyone wants a more detailed account of how to do this: SavageLook.com Handling Global Configuration in Android [...]
Nice tutorial. I have been trying to implement it in a slightly different manner, unfortunately without much success. I am attempting to set the global variable from the spinners in one java file and then call it in the others in the application. I am using an intent to pass the value from the spinner to the other java file in question. I then use something similar to your Sample usage in any Activity above to get the string.
No errors in Eclipse but the application force closes upon opening the Activity that calls for the string.
Thought maybe you would have some future suggestions
Solved, I give it below if any of your readers are interested:
Spinner spinnerIterations = (Spinner) findViewById(R.id.spinnerIterations);
int positerations = spinnerIterations.getLastVisiblePosition();
if (positerations == 0){
localIterationString = “10″;
}else if (positerations == 1){
localIterationString = “30″;
}else if (positerations == 2){
localIterationString = “50″;
}else if (positerations == 3){
localIterationString = “75″;
}else{
localIterationString = “100″;
}
MyApplication sampleAppIterations = (MyApplication)getApplicationContext();
sampleAppIterations.setIterationStringValue(localIterationString);
And in another Activity:
MyApplication sampleAppIterations = (MyApplication)getApplicationContext();
jString = sampleAppIterations.getIterationStringValue();
I’m trying this
private String mStringValue=”nul or NOT Data I want”;
@Override
public void onCreate() {
mStringValue = “Data I want”;
super.onCreate();
}
and although I can change the value from my other class, The initial value I read is
“nul or NOT Data I want”. I can’t get a variable from the onCreate method! any ideas where I’ve gone wrong? Thanks.
I realise in my last post the code fragment may be insufficient to demonstrate the problem I’m encountering so I’ve written it up in more detail here.
http://stackoverflow.com/questions/7294790/oncreate-method-variables-unaccessible
can anyone help?
Thanks.
Which one is better to use Extending Application class for sharing data across activities or using static variables or singleton.
Thanks for a great article, really helpful to a newbie like me!
This was the clearest article I found. You made it easy. Thanks.