How to use sharedpreference from its class? - android

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());

Related

How to access sharedpreference value in non-Activity Java class?

I want to get Shared preference values in non-Activity Url Constants class where I need to check url which will come from a previous Activity. I am using common Shared Preference Utility class where I am using Shared Preference Manager to put and get values through shared preferences; however whenever I try to access shared preference value in Url constants class, I cannot access the common shared preference utility class. How can I get the value ? Please help.
My Shared Preference class is:
public class Preference {
private static final String PREFIX = "json";
public static void setString(String key, String value, Context context) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(key, value);
editor.apply();
}
public static String getString(String key, Context context) {
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(key, null);
}
You should pass context, instead doing any hacks with context
Ideally, we should get this done once and access it anywhere. What I mean is we can create a single instance of Sharedpreference when starting Application class and make any calls on this object.
public class AppController extends Application {
static AppController appController;
public static AppController getInstance(){
return appController;
}
#Override
public void onCreate() {
super.onCreate();
Fabric.with(this, new Crashlytics());
appController = this;
}
}
get it named in manifest first before use in application tag with name attribute.
<application
android:name=".AppController"
......
......
</application>
So we can initialize here our SharedPreference or get application instance like this. We can also use Dagger for this and do much more.
AppController.getInstance().getApplicationContext().getSharedPreferences("userdetails", MODE_PRIVATE);
OR
we can just pass context to some constructor of a non-actvitiy/fragment class.
AS show your code you pass context that's not problem but the problem with your class name Preference it should be similar to java inbuilt class like java.android.preference and java.util.pref so make sure you are pointing your project class not android java default calss. or you may try to change your util class with other

Referencing a non-static method in a static class in Android - getSharedPref

I have following code :
Context context = Activity.getApplicationContext();
SharedPreferences settings = context.getSharedPreferences("AutoMsgSharedPrefs", MODE_PRIVATE);
// Writing data to SharedPreferences
SharedPreferences.Editor editor = settings.edit();
editor.putString("key", "some value");
editor.commit();
I have been trying to use SharedPrefs to store messages given in - "Conversation" class as in sample - https://developer.android.com/samples/MessagingService/index.html. But, I get "can not reference non-static method from a static class if I try to achieve it in constructor of "Conversation" class. So How do I resolve this?
Here is the screenshot of error if I update as suggested :
Here
Context context = Activity.getApplicationContext();
This line not return a valid Context for your application to call getSharedPreferences.
To call getSharedPreferences from non Activity,Service,... classes you should need to pass valid context from application component like from Activity,Service,..
To get Context in Conversation use Conversation class constructor which is already created in given example you will need to add one more parameter:
Context mContext;
public Conversation(int conversationId, String participantName,
List<String> messages,Context mContext) {
.....
this.mContext=mContext;
}
Now use mContext to call getSharedPreferences method from Conversation class :
SharedPreferences settings = mContext.getSharedPreferences("AutoMsgSharedPrefs",
Context.MODE_PRIVATE);
To get the context no need to use Activity class. Change this code
Context context = Activity.getApplicationContext();
to
Context context = getApplicationContext();
Explanation: Activity class does not have a static method getApplicationContext(), because this method is non static, so you need to have an object instance. So call this method on Activity on Context instance.
As #ρяσѕρєя K already pointed out you have to somehow grant your non-Context class access to your Context instance. For example through introducing a new parameter.
public Conversation(int conversationId, String participantName,
List<String> messages, Context context) {
.....
}
But keep in mind:
It is discouraged to save references to long-life and heavy weight components like Contexts in your classes because this strong reference will exclude the context from the garbage collection and thus causing memory leaks.
So instead of storing your Context you can use it to initialize your Conversation object as you like and let the scope of the constructor take care of discarding the short-term reference to your Context.
If you should need a Context multiple times though, you could write a method which takes a Context instance as a parameter and call it to do the dirty work:
public void doStuff(Context context) {
// do your work here
}

Initialization of static variables in a class of utility functions

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.

Android using sharedpreferences in BaseAdapter class

In activity I load preferences like:
public void LoadFontSize(){
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
loadedFontSize = sharedPreferences.getString("fontsize", "font3");
}
And SharedPreferences sharedPreferences; is declared globally.
I have an ExpandBaseAdapter class operating an ExpandableListView. I want to handle fontsizes in this class, but it shows me
The method getApplicationContext() is undefined for the type
ExpandBaseAdapter
error.
I tried to add sharedPreferences = context.getSharedPreferences("PREF_NAME", Context.MODE_PRIVATE);
but then I get only the default value.
If I add sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ExpandBaseAdapter.this);
I get
The method getDefaultSharedPreferences(Context) in the type
PreferenceManager is not applicable for the arguments
(ExpandBaseAdapter)
What should I do?
You have to pass the application context when you create the instance of this base adapter in your activity.
and declare context as attribute in the base adapter constructer.
You have to use YourActivity.this instead of getApplicationContext(), both in general, and especially in your Adapter.
Best regards.
(Edit below)
Try this then:
class ExpandBaseAdapter {
Context mContext;
void ExpandBaseAdapter(Context context) {
mContext = context;
}
}
and use mContext.getSharedPreferences() where you need it.
Pass a Context object into LoadFontSize() as a parameter and use that to get to shared prefs.

Accessing SharedPreferences through static methods

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);
}

Categories

Resources