I have a DialogView which stores settings in shared preferences. It is located in package A and i have another activity which is located in package B, which should be able to read these preferences.
So I created a wrapper class, which takes context and shared preference name and retrive these settings. When shared preferences are set at the first time everything works great, but when I change it, I got the same result, which was set at first time.
Problem is I save preference in one process and need to be able to read them in another.
So it seems like Context has changed and I am not able to retrive new context. What should I do to get up to-date shared preference?
Thank you on advance.
Please take a look at my wrapper class
public class PhotoAppWidgetSettingsProxy extends Proxy {
private final static String PREFERENCES_NAME = PhotoAppWidgetSettingsProxy.class.getName();
private final static int PREFERENCES_MODE = Context.MODE_PRIVATE;
private Context mCtx = null;
private SharedPreferences pref = null;
private SharedPreferences.Editor editor = null;
public PhotoAppWidgetSettingsProxy(String name, Context context) {
super(name, context);
mCtx = context;
pref = context.getSharedPreferences(PREFERENCES_NAME, PREFERENCES_MODE);
editor = pref.edit();
}
private final static String FRAME = "FRAME";
/**
* Sets selected frame mode
* #param frame id
*/
public void setFrameMode(int frameId){
editor.putInt(FRAME, frameId);
Log.d(PREFERENCES_NAME, "SET MODE="+frameId);
boolean success = editor.commit();
Log.d(PREFERENCES_NAME, "SET MODE="+success);
}
/**
* Gets selected frame mode
* #return frame id
*/
public int getFrameMode(){
Log.d(PREFERENCES_NAME, "GET MODE="+pref.getInt(FRAME, 0));
return pref.getInt(FRAME, 0);
}
SOLVED:
private final static int PREFERENCES_MODE = Context.MODE_MULTI_PROCESS;
private final static int PREFERENCES_MODE = Context.MODE_MULTI_PROCESS;
When accessing shared preferences/values, I have found it useful to write a CustomApplication class extending Application. I can place any necessary fields/methods in there, and easily acquire them from any of the other Android classes by using:
CustomApplication app = (CustomApplication) getApplication();
int x = app.getX();
Does that help you at all?
Related
I have a service in my app that is always running but the global static variables seem to get reset when the phone is idle for a while (possibly the app is getting closed). Please let me know the optimal way to store a value for repeated use, maybe once in 2-5 mins.
Will using a SharedPreference cause high overhead if accessed once in 2-5 mins ?
Appreciate your help.
SharedPreference is best option.
public class AppPreference {
public static final String APP_NAME_KEY= "your_app_name";
public static final String SAMPLE_KEY = "sample";
public SharedPreferences preferences;
private SharedPreferences.Editor editor;
private String sample;
public AppPreference(Context context) {
preferences = context.getSharedPreferences(APP_NAME_KEY, Context.MODE_PRIVATE);
editor = preferences.edit();
}
public void setSample(String sample) {
this.sample= sample;
editor.putString(SAMPLE_KEY , this.sample);
editor.commit();
}
public String getSample() {
return preferences.getString(SAMPLE_KEY, null);
}
}
You can use Integer, Float, boolean values according to your requirement.
I store a value in Activity class from a spinner , is it possible to get the value without context ?
SharedPreference.class
public static int getPreferencedCurrency(){
SharedPreferences prefs = getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,Context.MODE_PRIVATE);
return prefs.getInt(Constants.CURRENCY_PREFERRED,0);
}
Error on getSharedPreferences
What exactly do you mean by storing a value in the SP class? What exactly do you need to do with that value?
You can easily store a value in the SP of your app, and it will always be accessable.
I sounds like you should pass a Context into the constructor of your class, preferably the Application Context to avoid a memory leak, and use it when you need to access the SharedPreferences.
Something like this:
public class SomeClass{
private Context con;
public SomeClass(Context c){
this.con = c;
}
public static int getPreferencedCurrency(){
SharedPreferences prefs = con.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,Context.MODE_PRIVATE);
return prefs.getInt(Constants.CURRENCY_PREFERRED,0);
}
}
Use the Application Context when initializing an instance of the class:
SomeClass sc = new SomeClass(getApplicationContext());
I want to have a list of certain important things(which I am fetching from server every 15 seconds) which I want to have constant(or common) in my entire application. So when I move to next activity by Intents(or any other methods) I should have the list all the time. Is it possible in android ??
I want different solutions which requires as less work as possible.
Please Help..
EDIT: I think I havent made myself clear. I am not worried about how to store data..I am asking as to how can I achieve a view in which only half of the screen changes(as we move from activity to activity) while other half remains constant(doesnt move). Can it be possible ??
Your application class instance is always accesible from any activity.
All you need to do is create the application class like this:
public class YourApp extends Application {
....
}
And then modify the following line in your app AndroidManifest.xml :
<application
android:name="your.package.YourApp"
Now you can access this class everywhere:
YourApp appInstance = (YourApp)getApplication();
Use the PreferencesManager like the one below, create your POJO to access the PreferencesManager.
// TODO: Auto-generated Javadoc
/**
* The Class PreferenceManager.
*/
public class PreferenceManager {
/** The Constant TAG. */
private static final String TAG = PreferenceManager.class.getSimpleName();
/** The default shared preferences. */
private static SharedPreferences defaultSharedPreferences = null;
/**
* Inits the.
*
* #param context the context
*/
public static final void init(Context context){
defaultSharedPreferences = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
log("Initialize PreferenceManager!");
UserSettings.init(context);
}
/**
* Save.
*
* #param name the name
* #param value the value
*/
static final void save(String name,String value){
if( value != null ){
Editor edit = defaultSharedPreferences.edit();
edit.remove(name);
edit.putString(name, value);
edit.commit();
}else{
Editor edit = defaultSharedPreferences.edit();
edit.remove(name);
edit.commit();
}
}
/**
* Gets the.
*
* #param name the name
* #param defaultValue the default value
* #return the string
*/
public static final String get(String name,String defaultValue){
return defaultSharedPreferences.getString(name, defaultValue);
}
/**
* Save state.
*
* #param name the name
* #param state the state
*/
public static final void saveState(String name,Bundle state){
if( state != null && state.size() > 0 ){
Parcel parcel = Parcel.obtain();
parcel.writeBundle(state);
String encodeToString = Base64.encodeToString(parcel.marshall(), Base64.DEFAULT);
PreferenceManager.save(name, encodeToString);
}else{
PreferenceManager.save(name, null);
}
log("Saved state "+name);
}
/**
* Gets the state.
*
* #param name the name
* #return the state
*/
public static final Bundle getState(String name){
log("Get state "+name);
String encryptedValue = "";
try {
encryptedValue = PreferenceManager.get(name, "");
} catch (NullPointerException e) {
return new Bundle();
}
if( "".equals(encryptedValue) ){
return new Bundle();
}else{
byte[] decode = Base64.decode(encryptedValue, Base64.DEFAULT);
Parcel parcel = Parcel.obtain();
parcel.unmarshall(decode, 0, decode.length);
parcel.setDataPosition(0);
return parcel.readBundle();
}
}
/**
* Log.
*
* #param msg the msg
*/
private static final void log(String msg){
Log.d(TAG, msg);
}
}
/**
* The Class Settings.
*/
public class UserSettings {
/** The settings bundle. */
private final Bundle settingsBundle = new Bundle(1);
/**
* Save.
*/
public final void save() {
PreferenceManager.saveState(SETTINGS_STATE_NAME, settingsBundle);
}
/**
* Restore.
*/
final public void restore() {
settingsBundle.clear();
Bundle state = PreferenceManager.getState(SETTINGS_STATE_NAME);
if (state.size() == 0) {
settingsBundle.putAll(getDefaultValuesSettings());
} else {
settingsBundle.putAll(state);
}
}
final void reset() {
settingsBundle.clear();
}
/**
* Gets the settings.
*
* #return the settings
*/
public static UserSettings getSettings() {
return settings;
}
/**
* Inits the.
*
* #param ctx the ctx
*/
public static final void init(Context ctx) {
settings.restore();
setDeviceUniqueId(ctx, settings);
}
}
Example usage:
public class YourApplication extends Application {
....
onCreate(){
....
PreferenceManager.init(getBaseContext());
}
}
Where you need your data to be stored and retrieved use the methods like below.
UserSettings.getSettings().setUser(responseVal);
UserSettings.getSettings().save();
String response = UserSettings.getSettings().getUser();
If it's large amount of data, you can store your data using Shared Preferences or SQLite DB. If it is less amount of data then you can go for static variables. If you use static variables, when any crash occurs in the app that data may lost. Hence static variables usage is less preferable.
There are lot of ways to do this :
You can store them and put in your application's SQLite database (Data is Persistent till you delete the application or delete through your application code )
See the SQLite usage here
You use Cache them in the phone memory till the time your app runs.
See Cache usage here here
You can use SQLite database to store this data and then create singleton helper to read it.
Or you can use save your data in XML or JSON format as files, then parse them to read.
Or you can create class-container for one entity of your data, make it serializable and store in SharedPreferences as ArrayList<YourDataContainer>
For my Android application, I have written a class which is composed of utility functions which are needed at various activites in the application.In this class, I need a context variable(for working with files) and an instance of preference manager and preference editor.Also, a long integer represnting the current date as a timestamp is needed:
private static long today;
private static Context myContext;
private static SharedPreferences sharedPrefs;
private static Editor editor;
Which is correct way to initialize these variables. I have tried doing it via a private constructor as shown below, but I am getting errrors.
private NetworkController()
{
//Getting the Unix timestamp for today
GregorianCalendar aDate = new GregorianCalendar();
GregorianCalendar tDate = new
GregorianCalendar(aDate.get(Calendar.YEAR),aDate.get(Calendar.MONTH),
aDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
today = (tDate.getTimeInMillis())/1000;
//The preferences manager for reading in the preferences
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(myContext);
//The preferences editor for modifying the preferences values
editor = sharedPrefs.edit();
}
One approach would be to create an instance of this class in every activity where its used but I don,t want to do that.Any other approach is possible?
If you have a set of things that you use everywhere and only want one instance of, you can use what's called a singleton. For example, here is a very simple one that holds an integer called level:
public class Utility {
private static Utility theInstance;
public int level;
private Utility() {
level = 1;
}
public static getUtility() {
if (theInstance == null) {
theInstance = new Utility();
}
return theInstance;
}
}
Then you can use this like:
Utility u = Utility.getUtility();
u.level++;
However, many people discourage the use of singletons, since they can lead to confusing program behaviour. A good article on this topic is Singletons are Pathological Liars. Singletons can be useful in some situations, but you should be aware of the traps involved in using them.
#Greg is right, just don't use any static stuff for what you want to do. There is no reason you don't want to have normal objects here. Pass the context as parameter and instanciate you objects when you need them to serve you :
private long today;
private Context myContext;
private SharedPreferences sharedPrefs;
private Editor editor;
public NetworkController( Context context )
{
this.context = context;
//Getting the Unix timestamp for today
GregorianCalendar aDate = new GregorianCalendar();
GregorianCalendar tDate = new
GregorianCalendar(aDate.get(Calendar.YEAR),aDate.get(Calendar.MONTH),
aDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
today = (tDate.getTimeInMillis())/1000;
//The preferences manager for reading in the preferences
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.context);
//The preferences editor for modifying the preferences values
editor = sharedPrefs.edit();
}
Singletons are a bad way of programming things, it makes things very hard to test. Even you don't yet use tests, don't use singletons, there lead to very poor quality code and real ball of muds when things get more complicated.
Here you can do this:
public class NetworkController {
SharedPreferences settings;
SharedPreferences.Editor editor;
public NetworkController(Context context){
settings = PreferenceManager.getDefaultSharedPreferences(context);
editor = settings.edit();
}
public void saveName(String name){
editor.putString("name", name).commit();
}
public String getName(){
return settings.getString("name");
}
public static long getTimeStamp(){
return System.currentTimeMillis();
}
}
You can use the class like below:
NetworkController prefs = new NetworkController(context); // Context being an Activity or Application
prefs.saveName("blundell");
System.out.println(prefs.getName()); // Prints 'blundell';
System.out.println(NetworkController.getTimeStamp()); // Prints 1294931209000
If you don't want to create an instance in every class you could create on instance in your Application and always reference that:
public class MyApplication extends Application {
private NetworkController myPrefs;
public NetworkController getPrefs(){
if(myPrefs == null){ // This is called lazy initialization
myPrefs = new NetworkController(this); // This uses the Application as the context, so you don't have issues when Activitys are closed or destroyed
}
return myPrefs;
}
}
You need to add the MyApplication to your manifest:
<application
android:name="com.your.package.MyApplication"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
To use this single instance you would do this:
public class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState){
super(savedInstanceState);
NetworkController prefs = ((NetworkController) getApplicationContext()).getPrefs();
// use this object just like shown above
prefs.saveName("blundell"); // etc
}
}
There's already a bunch of good suggestions posted here, but I suppose another approach for these kind of 'utility'/'helper' functions is to simply pass in the parameters you need the logic to work on. In your case, in stead of trying to make the logic work on a local Context reference, you could simply pass it in:
public static void NetworkController(Context context) {
//Getting the Unix timestamp for today
GregorianCalendar aDate = new GregorianCalendar();
GregorianCalendar tDate = new
GregorianCalendar(aDate.get(Calendar.YEAR),aDate.get(Calendar.MONTH),
aDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
long today = (tDate.getTimeInMillis())/1000;
//The preferences editor for modifying the preferences values
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
...
}
The other variables you can calculate/deduce on the fly. It'll probably mean a bit more garbage collection, but should be relatively safe in terms of memory management.
I have some information stored as SharedPreferences. I need to access that information from outsite an Activity (in from a domain model class). So I created a static method in an Activity which I only use to get the shared preferences.
This is giving me some problems, since apparently it is not possible to call the method "getSharedPreferences" from a static method.
Here's the message eclipse is giving me:
Cannot make a static reference to the non-static method
getSharedPreferences(String, int) from the type ContextWrapper
I tried to work around this by using an Activity instance, like this:
public static SharedPreferences getSharedPreferences () {
Activity act = new Activity();
return act.getSharedPreferences("FILE", 0);
}
This code gives a null point exception.
Is there a work-around? Am I going into an android-code-smell by trying to do this?
Thanks in advance.
Cristian's answer is good, but if you want to be able to access your shared preferences from everywhere the right way would be:
Create a subclass of Application, e.g. public class MyApp extends Application {...
Set the android:name attribute of your <application> tag in the AndroidManifest.xml to point to your new class, e.g. android:name="MyApp" (so the class is recognized by Android)
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp(). You then can use this method later to get a context of your application and therefore get your shared preferences. :-)
That's because in this case, act is an object that you just create. You have to let Android do that for you; getSharedPreferences() is a method of Context, (Activity, Service and other classes extends from Context). So, you have to make your choice:
If the method is inside an activity or other kind of context:
getApplicationContext().getSharedPreferences("foo", 0);
If the method is outside an activity or other kind of context:
// you have to pass the context to it. In your case:
// this is inside a public class
public static SharedPreferences getSharedPreferences (Context ctxt) {
return ctxt.getSharedPreferences("FILE", 0);
}
// and, this is in your activity
YourClass.this.getSharedPreferences(YourClass.this.getApplicationContext());
I had a similar problem and I solved it by simply passing the current context to the static function:
public static void LoadData(Context context)
{
SharedPreferences SaveData = context.getSharedPreferences(FILENAME, MODE_PRIVATE);
Variable = SaveData.getInt("Variable", 0);
Variable1 = SaveData.getInt("Variable1", 0);
Variable2 = SaveData.getInt("Variable2", 0);
}
Since you are calling from outside of an activity, you'll need to save the context:
public static Context context;
And inside OnCreate:
context = this;
Storing the context as a static variable, can cause problems because when the class is destroyed so are the static variables. This sometimes happens when the app is interrupted and becomes low on memory. Just make sure that the context is always set before you attempt to use it even when the class setting the context is randomly destroyed.
Here's a better alternative to storing your shared preferences in static fields.
Similar to what has been suggested here, create a class that extends Application
Make the constructor for your class take Context as a parameter.
Use your context to get shared preferences and store them in private variables.
Create public variables to return the retrieved data.
e.g
public class UserInfo extends Application{
private String SAVED_USERID;
private String SAVED_USERNAME;
public UserInfo(Context context) {
SharedPreferences prefs = context.getSharedPreferences(FILE, MODE_PRIVATE);
SAVED_USERNAME = prefs.getString("UserName", null);
SAVED_USERID = prefs.getString("UserID", null);
}
public String getSavedUserName() {
return SAVED_USERNAME;
}
public String getSavedUserID() {
return SAVED_USERID;
}
}
usage in your activity
UserInfo user = new UserInfo(this.getApplicationContext());
String SAVED_USERNAME = user.getSavedUserName();
String SAVED_USERID = user.getSavedUserID();
I had the same need - some of my preferences need to be accessed often, and efficiently. I also imagine that reading and writing a string from SharedPreferences is slightly slower than getting and setting a static variable (but likely to an insignificant degree). I also just kind of got used to using static fields, retrieving Preference values only at startup, and saving them on close.
I didn't love my options for keeping static references to the SharedPreferences/contexts directly, but so far this workaround has sufficed.
My solution:
Create a Settings class with all the static variables you need.
When the application initializes, retrieve SharedPreferences fields and immediately set all Settings fields (I call a "loadSharedPrefs()" method at the end of MainActivity's onCreate method).
In the SettingsActivity's preferenceChangeListener's initialization, set the appropriate static field in the Settings class. (I call a "setAppropriateSetting(key, value)" method at the beginning of SettingsActivity's onPreferenceChange()).
Use your static preferences wherever, whenever!
public static String getPreferenceValue(Context context) {
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(context);
String key = context.getString(R.string.pref_key);
String defaultVal = context.getString(R.string.pref_default);
return sharedPreferences.getString(key,defaulVal);
}