I am trying to write a code in Android to get context for SharedPrefrences from my parent class without extending to Super Class.
My Code :
public class TestClass
{
static Context mContext; //class variable
TestClass(Context context)
{
mContext = context;
}
String text = null;
SharedPreferences pref = mContext.getApplicationContext().getSharedPreferences("Status", 0);
text = pref.getString("Number",null);
Log.d(" Text Result : ", text);
}
I am getting error in getApplicationContext() that no able to find getApplicationContext() in TestClass.
Please let me know how can I get the context and I will use it SharedPreferences.
If this really is your code it can't work at all. Because the global fields will be initialized before the constructor is called. That's why
SharedPreferences pref = mContext.getApplicationContext().getSharedPreferences("Status", 0);
is called before the constructor init the mContext.
Init your fields in the constructor after you have init the mContext field by passing it from a class which derives from Context (Activity, Service...)
public class TestClass
{
static Context mContext; //class variable
String text;
SharedPreferences pref;
TestClass(Context context)
{
mContext = context;
pref = mContext.getApplicationContext().getSharedPreferences("Status", 0);
text = pref.getString("Number",null);
Log.d(" Text Result : ", text);
}
}
Call this in your Activity:
TestClass tc = new TestClass(this);
First of all you cannot do this(cannot get application context of a context):
SharedPreferences pref = mContext.getApplicationContext().getSharedPreferences("Status", 0);
you should use it like this:
SharedPreferences pref = mContext.getSharedPreferences("Status",Context.MODE_PRIVATE);
Additionally makes no sense to use this without an Activity?
Related
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 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
}
I have an app on Android 4.0. It uses the PreferenceManager class to -- among other things -- let the user specify how many decimal places of a number to show.
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Generally I have no problem getting the app context in order to access the Preference Manager. My problem is that I have a class (let's call it Record) that isn't subclassing anything that has the app context; it's just a storage class, but it does have a field "NumDecPlaces". Right now, when I instantiate the class from within my app I just pass in the user's #dec places preference. It would be nice if Record could access the Preference manager directly. I suppose I could always instantiate Record with a pointer to the context from which it was created, but that's a lot to remember ;-)
So right now Record subclasses nothing. Any recommendations on what I can do to it to allow it to see the app context?
Thanks!
You could pass the Context object in the constructor. So whenever you try to use that class it will ask you pass a Context object and then use that to get SharedPreferences
For eg.
public Record(Context context)
{
mContext = context;
mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext)
}
You can also extend a class with Application, which will be global to the whole application and you can set the context in that class as a member variable and that context will be global to the whole application
Eg. class A extends Application{......}
You can do #Apoorv's suggestion or you can create another class that specifically stores the application context.
public class ContextResolver {
private static Context context;
public static void setContext(Context context) {
if (context == null) {
throw new IllegalArgumentException("Context must not be null");
} else if (context instanceof android.app.Activity) {
context = androidContext.getApplicationContext();
} else if (context instanceof android.content.Context) {
context = androidContext;
}
}
public Context getContext() {
return context;
}
}
Now you need to call setContext() in the first activity that will be launched once.
public class MyFirstActivity extends Activity {
public void onCreate() {
ContextResolver.setContext(this);
}
}
Now you can retrieve the Context from any part of your code. So in your Record class you can just do this:
mPreferences = PreferenceManager.getDefaultSharedPreferences(ContextResolver.getContext());
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.
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.