I'm building an android project that contains SharedPreferences.
My SharedPreferences works fine and I tested it in mutiple activity. but in a class that I defined for global variables, defining that SharedPreferences will cause force close (eclipse didn't show any error in codes).
public class Globals extends Application {
final SharedPreferences s = getSharedPreferences("Prefs", MODE_PRIVATE);
}
What is the problem ?
You should pass the Context and use
SharedPreferences prefs = Context.getSharedPreferences(
"Prefs", Context.MODE_PRIVATE);
Create a constructor and pass a Context variable as a parameter. Any activity that want to use this preference then you have to pass the activity. Here's the code given below:
public class Globals extends Application {
private Context context;
public Globals (Context context) {
this.context = context;
}
SharedPreferences myPref = context.getSharedPreferences("Prefs", Context.MODE_PRIVATE);
}
You can't run getSharedPreferences() in the actual class. Everything you do must be in the Application's onCreate method. If you try to run this in the class, it will fail since it has not been initialized yet. Think of it almost as an activity, since both the activity and the application have a lifecycle.
Try the following:
public class Globals extends Application {
#Override
public void onCreate() {
super.onCreate();
final SharedPreferences s = getSharedPreferences("Prefs", MODE_PRIVATE);
}
}
Related
I have a class A this class does not extend or implement any other classes. I then have an Class B, this class also does not extend or implement any other classes.
My Class B is solely used to manage SharedPreferences :
private static SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
Here is the problem method in Class B:
public static void setCurrentUsersEmail(String email){
sharedPreferences.edit().putString("userEmail",email).commit();
}
Now class A is a database manager and needs to store the users email in SharedPreferences for later use. I do this with the following code:`
MySharedPrefs.setCurrentUsersEmail(currentUsersEmail);
However, when i try run the code in Class A i get the error:
java.lang.ExceptionInInitializerError
at com.test.Android.MySharedPrefs.setCurrentUsersEmail(MySharedPrefs.java:0)
I am really confused as to why this happens I couldn't find a solution online after searching either, I use my sharedPreferences class in other activities perfectly fine. Is it an activity problem?
Any help is much appreciated.
You can use singleton for your requirement :
public class MyPrefs {
private static MyPrefs myPrefs;
private SharedPreferences sharedPreferences;
private MyPrefs(Context context){
sharedPreferences=context.getSharedPreferences("MyPREFERENCES", Context.MODE_PRIVATE);
}
public static MyPrefs getInstance(Context context){
if(myPrefs==null)
myPrefs=new MyPrefs(context);
return myPrefs;
}
public void setCurrentUsersEmail(String email){
sharedPreferences.edit().putString("userEmail",email).commit();
}
}
You can put email in this way :
MyPrefs.getInstance(context).setCurrentUsersEmail(currentUsersEmail);
You need to pass context at first time for the reference of sharedPreferences in your Class.
or
From Activity call MyPrefs.getInstance(context) at once
Then you can call without context
MyPrefs.getInstance().setCurrentUsersEmail(currentUsersEmail);
getInstance() method :
public static MyPrefs getInstance(){
if(myPrefs==null) throw new AssertionError("MyPrefs cannot be null");
else
return myPrefs;
}
You could do this , in any activity, dont need to create a new method:
To save:
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("email", "YOURUSEREMAIL#.email");
editor.commit();
To restore:
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String restoredText = prefs.getString("email", null);
You cant call MyPrefs.aFunctionYouCreated() !!!
I am using SharedPreferences in my asynctask but because of this the following line of code does not work:
SharedPreferences prefs = this.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
But if I remove the 'this.' it throws me this error:
09-04 10:16:49.184: E/AndroidRuntime(1883): at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:161)
Also, it is being called from a service if that complicates things anymore? So how do I provide proper context to this SharedPreferences?
You can set a parameter in the AsyncTask Constructor, that will be the base context, like it:
public class X extends AsyncTask {
private Context context;
public X(Context context) {
this.context = context;
}
#Override
doInBackground() {
SharedPreferences prefs = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// your code
}
Hugs.
Declare it globally in class which extends Activity
public static SharedPreferences prefs;
pref=PreferenceManager.getDefaultSharedPreferences(getBaseContext());
Now u can use pref as per your need.
I've kept a static shared preference to access the values from multiple activities.
Now, I've set an alarm to go off at a certain time. Now in that Broadcast Receiver, I'm trying to access the shared pref variable.
It has already been initialized in another activity and returns the proper value there.
But in this Broadcast Receiver it doesn't give the actual value. It gives the uninitialized value.
Since it is static shouldn't the value remain same?
Here is the shared preference class.
package com.footballalarm.invincibles;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
public class SessionManagement {
// Shared Preferences
public static SharedPreferences pref;
// Editor for Shared preferences
public static Editor editor;
// Context
Context _context;
// Shared pref mode
int PRIVATE_MODE = 0;
// Shared pref file name
private static final String PREF_NAME = "invincibles_alarm";
// All Shared Preferences Key
public static final String PREF_MATCH = "match";
// Constructor
public SessionManagement(Context context){
this._context = context;
pref = _context.getSharedPreferences(getPrefName(), PRIVATE_MODE);
editor = pref.edit();
editor.commit();
Log.e("Pref Match Value-constructor for pref", getValueMatch());
}
public static void fillValues(String match){
try{// Storing login value as TRUE
editor.putString(PREF_MATCH, match);
// commit changes
editor.commit();
Log.e("Pref Match Value-in fill values", getValueMatch());
}
catch(Exception e)
{Log.e("fillValues", e.toString());}
}
public static String getValueMatch(){
return pref.getString(PREF_MATCH, "Loading Match");
}
public static String getPrefName() {
return PREF_NAME;
}
}
I tried to log the output in other activities and it returns properly.
When I run the app and then close it before the alarm takes place, the program crashes with null-pointer exception since the Broadcast Receiver cannot access the shared pref.
I have tried this solution - SharedPreferences in BroadcastReceiver seems to not update? but I'm only using name in the manifest for the recievers.
This only happens if I close my app in ICS via the minimize menu.
Check this link:
Static variable loses value
Maybe static variables are loosing its value in your case .
static variables can loose value in the following cases:
1) Class is unloaded.
2) JVM shuts down.
3) The process dies.
Instead of using static variables and functions , try using a public class instead.
Hope it helps
EDIT 1:
Example code of using a public class for preferences instead of static methods
public class PreferenceForApp {
Context context;
SharedPreferences prefs;
public PreferenceForApp(Context context) {
this.context = context;
prefs = context.getSharedPreferences(AllConstants.PREFS_NAME, 0);
}
public Boolean getIsDeviceValidated() {
return prefs.getBoolean("Validated", false);
}
public void setIsDeviceValidated(Boolean value) {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("Validated", value);
editor.commit();
}
}
In your code add:
PreferenceForApp myPref = new PreferenceForApp(contxt);
myPref.getIsDeviceValidated();
Useful related links:
Android static object lifecycle
Why are static variables considered evil?
Android : Static variable null on low memory
EDIT 2
TEST when is your static variable loosing value :
You can test this with a few lines of code:
print the uninitialized static in onCreate of your activity -> should print null
initialize the static. print it -> value would be non null
Hit the back button and go to home screen. Note: Home screen is another activity.
Launch your activity again -> the static variable will be non-null
Kill your application process from DDMS(stop button in the devices window).
Restart your activity -> the static will have null value.
I referred to this link Android static object lifecycle
This is the save() method in my app:
public void save() {
Context context;
SharedPreferences sp = context.getSharedPreferences("gameSave",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("X", player.getX());
editor.putInt("Y", player.getY());
editor.putInt("level", player.getLevel());
editor.putFloat("xp", player.getXp());
editor.commit();
}
I have been trying to get this to work for a while now, but the getSharedPreferences (String name, int mode) has not been working for me. It doesn't come up on it's own, context.getSharedPreferences() works, but that yields a NullPointerException, I think because of my context. I have tried save(Context context){} as a constructor, but calling that from another method with context declared inside of that method does not work either. I've looked at many examples, but none of them have worked for me. So how can I get getSharedPreferences() to work?
EDIT: I have a class GameScreen and a class SaveManager. When I save in Gamescreen this is the code I use:
Savemanager savemanager;
savemanager.save();
state = GameState.Running;
And I have my class SaveManager:
package com.package.game;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
public class SaveManager extends Activity {
private Player player = GameScreen.getPlayer();
public void save() {
SharedPreferences sp = getSharedPreferences("gameSave",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("X", player.getX());
editor.putInt("Y", player.getY());
editor.putInt("level", player.getLevel());
editor.putFloat("xp", player.getXp());
}
}
And when I save in GameScreen my app crashes and I get this logcat:
02-20 01:39:31.979: E/AndroidRuntime(1368): FATAL EXCEPTION: Thread-119
02-20 01:39:31.979: E/AndroidRuntime(1368): java.lang.NullPointerException
02-20 01:39:31.979: E/AndroidRuntime(1368): at com.package.game.GameScreen.updateLevelUp(GameScreen.java:364)
Line 364 is the line savemanager.save();. I have no idea why this crashes my app.
getSharedPreferences() is a Context method. If save() is in a class that extends Context, such as Activity, you don't have to do context.getSharedPreferences(), so you can do, as you put it "the method by itself".
However, if save isn't in a class that extends Context, for it to be able to call getSharedPreferences(), it needs to have a Context variable passed off. This means that what you were doing by simply making a context variable isn't enough (and that code shouldn't compile, there would be an error thrown about how the context variable hasn't been initialized). And since Contexts aren't made using a constructor, your method hits a dead end.
However, you are close. For the sake of explanation, you can make a static method that accepts in a Context and does the saving. static since this method really shouldn't need an object instance, it can be self-contained:
public static void save(Context context) {
if (context == null)
throw new RuntimeException ("Context is null, what are you doing?");
SharedPreferences sp = context.getSharedPreferences("gameSave",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("X", player.getX());
editor.putInt("Y", player.getY());
editor.putInt("level", player.getLevel());
editor.putFloat("xp", player.getXp());
editor.commit();
}
Now if this method was part of a class for example named StaticUtils, you can call save:
Through an Activity: StaticUtils.save(YourActivityClass.this); or StaticUtils.save(this); depending on the scope (eg if inside an anonymous inner function, you'd use YourActivityClass.this).
Fragment: StaticUtils.save(getActivity());
BroadcastReceiver: StaticUtils.save(context);
A View (eg the View passed on when onClick() is called: StaticUtils.save(v.getContext());
Just keep in mind that the earilest you can do saving in an Activity is onCreate() anything before will fail and the Exception should clearly indicate that.
A simple demo. No extending anything, no fancy making of Context:
MainActivity.java:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StaticUtils.save(this);
SharedPreferences prefs = getSharedPreferences ("gameSave", Context.MODE_PRIVATE);
System.out.println ("X is " + prefs.getInt ("X",-1));
}
}
StaticUtils.java
public class StaticUtils {
public static void save(Context context) {
if (context == null)
throw new RuntimeException ("Context is null, what are you doing?");
SharedPreferences sp = context.getSharedPreferences("gameSave",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("X", 11);
editor.putInt("Y", 24);
editor.putInt("level", 3);
editor.putFloat("xp", 100);
editor.commit();
}
}
I have a problem with SharedPrefences and initializations.
My application has a login where you insert an user, and for that user, you have a specific preferences... so, I need to save preferences according to the user to load it later.
I though that SharedPrefences would be the solution, and it really is I think, but I have a problem to initialize they: I have an Activity class called Options. It has static functions that returns the value of the options... but I have a problem, I call that functions before I have create that activity (intent), so I think that the functions are returning the last value that the last user has selected on the options...
How can I load the options before that calls?
I though to use first of all an Intent sending extra data with the user and in onCreate() of the Options, initialize they, but if I make an intent, then the Options will appear (xml will load).
Any help pls?
Try something like this.... adding methods for each variable you want to save.
public class PreferenceManager {
private static PreferenceManager self;
private SharedPreferences preferences = null;
private SharedPreferences.Editor editor = null;
private boolean isInitialised = false;
private static final String MY_PREFERENCE = "mypreferencekey";
private String myPreference = null;
public void initialise(Context context) {
if (!isInitialised) {
preferences = context.getSharedPreferences("MyPreferencePlace", Context.MODE_PRIVATE);
editor = preferences.edit();
loadPreferences();
isInitialised = true;
}
}
public static PreferenceManager getInstance() {
if (self == null) {
self = new PreferenceManager();
}
return self;
}
private PreferenceManager() {
}
public void setPreference(String newPreferenceValue) {
this.myPreference = newPreferenceValue;
savePreferences();
}
public String getPreference(){
return myPreference;
}
private void savePreferences() {
editor.putString(MY_PREFERENCE, myPreference);
editor.commit();
}
private void loadPreferences() {
myPreference = preferences.getString(MY_PREFERENCE, null);
}
}
All the SharedPreferences need is a context and it can be initialized. As your application always opens an Activity to start with, you always have a context to work with.
I would advise you to wrap the SharedPreferences in a Singleton class and just pass a context as parameter at the getInstance method. You should be able to access your shared preferences at all Activities this way.
I work on the dependency injector for android, and content of shared preferences is already injectable into annotated fields ( see: https://github.com/ko5tik/andject , PreferenceInjector). Patches and improvements are welcome. Saving of preferences comes soon