I currently have a service that loads preferences upon startup, stores them as fields, then registers an OnSharedPreferenceChangeListener to update the fields when a preference is modified. Currently, my code looks like this:
public class MyService extends Service {
private int _prefA;
private boolean _prefB;
private String _prefC;
private boolean _prefD;
private SharedPreferences _preferences;
private SharedPreferences.OnSharedPreferenceChangeListener _prefChangeListener;
#Override
public void onCreate() {
super.onCreate();
_preferences = PreferenceManager.getDefaultSharedPreferences(this);
_prefA = Integer.parseInt(_preferences.getString(PREF_A_KEY, "0"));
_prefB = _preferences.getBoolean(PREF_B_KEY, false);
_prefC = _preferences.getString(PREF_C_KEY, null);
_prefD = _preferences.getBoolean(PREF_D_KEY, false);
_prefChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(PREF_A_KEY)) {
_prefA = Integer.parseInt(sharedPreferences.getString(key, "0"));
} else if (key.equals(PREF_B_KEY)) {
_prefB = sharedPreferences.getBoolean(key, false);
} else if (key.equals(PREF_C_KEY)) {
_prefC = sharedPreferences.getString(key, null);
} else if (key.equals(PREF_D_KEY)) {
_prefD = sharedPreferences.getBoolean(key, false);
}
}
};
_preferences.registerOnSharedPreferenceChangeListener(_prefChangeListener);
}
}
It works as expected, but adding more preferences is becoming tedious, since I have to update the code in both onCreate() and OnSharedPreferenceChangeListener. Is there any way to change this so that the code to load the preferences only needs to be written once?
This is rather ideal. However, it reduced the overhead a little:
Create initializer functions:
private void initializeAccounts() {
...
Resources res = getResources();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String User = preferences.getString(res.getString(R.string.username), null);
String Pass = preferences.getString(res.getString(R.string.password), null);
...
}
And then group the preferences :
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (getString(R.string.prefkey_password).equals(key) || getString(R.string.prefkey_username).equals(key)) {
initializeAccounts();
}
}
In the onCreate:
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
initializeAccounts();
}
The reason why I group the preferences together is that the other preferences don't change when I edit one of them. However, when I for instance want to change the password of my account, I also require the other preferences like username or the server URI to reconnect to the server. So, it more or less doesn't matter if I reset them.
Hope this helps.
Related
I want to get a string from my shared preference file and use for more classes, but I don't know why not work.
My reader class is:
import android.app.Activity;
import android.content.SharedPreferences;
public class A {
public static String url2;
public void execute() {
String URLPref = "URL";
SharedPreferences prefs = getSharedPreferences("com.exam.search_preferences",Activity.MODE_PRIVATE);
url2 = prefs.getString(URLPref , "");
}
private SharedPreferences getSharedPreferences(String string,
int modePrivate) {
return null;
}
}
And the second class that uses the string
public class SearchHome extends Activity {
static String url2;
A cls2= new A();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_activity);
cls2.execute();
url2 = A.url2;
Toast.makeText(getApplicationContext(),"URL:" + url2 ,
Toast.LENGTH_LONG).show();
...
Sorry for my bad english, I never learned.But I'm trying!
You need to pass the Context to your class A, because you can get the SharedPreferences from a Context object. NOTE, an Activity is a Context to some extend
public class A {
public static String url2;
/** #param context used to get the SharedPreferences */
public void execute(Context context) {
String URLPref = "URL";
SharedPreferences prefs = context.getSharedPreferences("com.exam.search_preferences",Activity.MODE_PRIVATE);
url2 = prefs.getString(URLPref , "");
}
}
And then pass the Context to your execute method
public class SearchHome extends Activity {
static String url2;
A cls2= new A();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_activity);
// pass context 'this' to the execute function
// This works, because SearchHome extends Activity
cls2.execute(this);
url2 = A.url2;
...
if your data is not confidential it would be a lot easier if you can make a class specially for shared preference and have other activities access it. you will save a lot of time and code will be a lot simpler to follow up
public class HelperShared {
public static final String score = "Score";
public static final String tag_User_Machine = "tag_User_Machine",
tag_Machine_Machine = "tag_Machine_Machine",
tag_Draw_Machine = "tag_Draw_Machine",
tag_Total_Machine = "tag_Total_Machine";
public static SharedPreferences preferences;
public static Editor editor;
public HelperShared(Context context) {
this.preferences = context.getSharedPreferences(score,
Activity.MODE_PRIVATE);
this.editor = preferences.edit();
}
/*
* Getter and Setter methods for Machine
*/
public void setUserMachine(int UserMachine) {
editor.putInt(tag_User_Machine, UserMachine);
editor.commit();
}
public void setMachineMachine(int MachineMachine) {
editor.putInt(tag_Machine_Machine, MachineMachine);
editor.commit();
}
public void setDrawMachine(int DrawMachine) {
editor.putInt(tag_Draw_Machine, DrawMachine);
editor.commit();
}
public void setTotalMachine(int TotalMachine) {
editor.putInt(tag_Total_Machine, TotalMachine);
editor.commit();
}
public int getUserMachine() {
return preferences.getInt(tag_User_Machine, 0);
}
public int getMachineMachine() {
return preferences.getInt(tag_Machine_Machine, 0);
}
public int getDrawMachine() {
return preferences.getInt(tag_Draw_Machine, 0);
}
public int getTotalMachine() {
return preferences.getInt(tag_Total_Machine, 0);
}
}
private SharedPreferences getSharedPreferences(String string,
int modePrivate) {
return null;
}
problem is here.
return null;
you have to return valid SharedPreferences object. otherwise you will always get NullPointerException.
Call this when you want to put a pref:
putPref("myKey", "mystring", getApplicationContext());
Call this when you want to get a pref:
getPref("myKey", getApplicationContext());
You can use SharedPreferences to save any primitive data: booleans, floats, ints, longs, and strings. This data will persist across user sessions (even if your application is killed).
Different Modes:
1 MODE_APPEND
This will append the new preferences with the already exisiting preferences
2 MODE_ENABLE_WRITE_AHEAD_LOGGING
Database open flag. When it is set , it would enable write ahead logging by default
3 MODE_MULTI_PROCESS
This method will check for modification of preferences even if the sharedpreference instance has already been loaded
4 MODE_PRIVATE
By setting this mode , the file can only be accessed using calling application
5 MODE_WORLD_READABLE
This mode allow other application to read the preferences
6 MODE_WORLD_WRITEABLE
This mode allow other application to write the preferences
Read More
You just need to make shared prefrences object in class where you want to have data
SharedPreferences prefrences = getSharedPreferences("my prefs",MODE_PRIVATE)
Editor editor = prefrences.edit();
String s = edit.getString("your key",value);
hope it helps !
When using a thread/task within an android service that implements the OnSharedPreferenceChangeListener interface, the changes made in the preference screen aren't reflected back to the thread/task object within the android service.
I want to accomplish two things:
SharedPreference data should be loaded when MyTask is constructed and initialized.
When preference change occurs, MyTask object must be updated with the new preference values set in the preference screen.
The problem is: preference initialization and preference changes are not reflected to the MyTask object.
This is my setup (only essential parts are mentioned):
MyService.class:
public class MyService extends Sevice {
private MyTask myTask;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!serviceStarted) {
serviceStarted = true;
myTask = new MyTask(this);
Thread t = new Thread(myTask);
t.start();
}
return Service.START_STICKY;
}
#Override
public void onDestroy() {
myTask.cancel();
super.onDestroy();
}
}
MyTask.class:
public MyTask implements Runnable, OnSharedPreferenceChangeListener {
private Context mContext;
private boolean mCancelled;
public MyTask(Context context) {
mContext = context;
}
#Override
public void run() {
while(!mCancelled) {
// do something
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// FIXME: DOESN'T GET CALLED after change in preference!!!!
Log.d(TAG, "Key= " + key);
}
public void cancel() {
mCancelled = true;
}
}
preference_devices.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="pref_category_devices"
android:title="#string/pref_category_devices_title" >
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_devices_server"
android:title="#string/pref_devices_server_title" />
</PreferenceCategory>
</PreferenceScreen>
I have tried coding a SharedPreferences listener object as a member field of the MyTask class and register/unregister the listener from the provided context, but that didn't work either. These changes also didn't work:
MyTask.class (using SharedPreference listener as field member of class):
public MyTask implements Runnable {
private Context mContext;
private boolean mCancelled;
private boolean mServerEnabled;
private SharedPreferences mPrefs;
private SharedPreferences.OnSharedPreferenceChangeListener
mPreferenceListener;
public MyTask(Context context) {
mContext = context;
mPrefs = mContext.getSharedPreferences("pref_category_devices",
Context.MODE_PRIVATE);
mPreferenceListener = new OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
// FIXME: DOESN'T GET CALLED after change in preference!!!!
Log.d(TAG, "Key= " + key);
}
};
mPrefs.registerOnSharedPreferenceChangeListener(mPreferenceListener);
// set the initial value of the preference setting
mServerEnabled = mPrefs.getBoolean("pref_devices_server", false);
}
#Override
public void run() {
while(!mCancelled) {
// do something
}
}
public void cancel() {
mCancelled = true;
}
}
I have now reached the point of throwing my computer out of the window :(
Any help in the right direction is highly appreciated :)
EDIT: In the code
mPrefs = mContext.getSharedPreferences("pref_category_devices", Context.MODE_PRIVATE);
I assumed that the first argument should be the preference category name of the preference file, like: "pref_category_devices". THIS IS INCORRECT! The first argument must be a shared preference file name. That didn't solve the problem, but at least now you know to not fall for this pitfall.
=== SOLUTION: === See answer of Mr_and_Mrs_D + code below this line:
Change in MyTask:
mPrefs = mContext.getSharedPreferences("pref_category_devices",
Context.MODE_PRIVATE);
into:
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
mPreferenceListener = new OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("preference_name_here")) {
mPrefValue = sharedPreferences.getBoolean(key, false);
// do something with boolean pref value
}
}
};
mPrefs.registerOnSharedPreferenceChangeListener(myPreferenceListener);
Where mPrefValue is a field member of type boolean in MyTask that needs to be set when the "preference_name_here" preference changes.
Change :
private volatile boolean mCancelled; //otherwise the myTask thread may never stop
For your problem :
if (!serviceStarted) {
serviceStarted = true;
myTask = new MyTask(this);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.registerOnSharedPreferenceChangeListener(myTask); //err, you must register
Thread t = new Thread(myTask); t.start();
}
Docs :
These preferences will automatically save to SharedPreferences as the user interacts with them. To retrieve an instance of SharedPreferences that the preference hierarchy in this activity will use, call getDefaultSharedPreferences(android.content.Context) with a context in the same package as this activity.
[emphasis mine]
Edit : your second snippet probably fails cause you get the wrong shared prefs - you must get the default ones - I thought it was failing because of :
SharedPreferences.onSharedPreferenceChangeListener not being called consistently
I have a login form with a checkbox to let the app remember the email in LoginActivity. If I press the Log in button the email should be stored in SharedPreferences using the class AppPreferences.
The app remembers the email if I return to home screen by pressing home button and by pressing back.
But if I force close the app shows the default value as defined in the Preferencemanager.getString("value", "default_value"); method.
I have tried a lot of things people suggested on SO, but unfortunately none of the solutions worked. I even tried to solve it by putting all the SharedPreferences code in a separate class (see this question).
Below I put as much code relevant to the question. So both the classes LoginActivity and AppPreferences. There is no error message given by LogCat.
At both the Samsung devices I9100 and P3110 with Android 4.2.2 Cyanogenmod 10.1 and several different emulators this problem occurs. (I read some Samsung S devices with HoneyComb could't save SharedPreferences properly?)
EDIT:
As I forgot to mention, the project is targeted to API 17 and the minSdkVersion = 11. I only save credentials on click of Log in button.
EDIT 2: This problem also occurs if phone reboots
the LoginActivity class:
public class LoginActivity extends Activity
{
private static final String PREF_REMEMBER_EMAIL = "LoginCredentialsRememberEmail";
private static final String PREF_EMAIL = "LoginCredentialsEmail";
private String mEmail;
private EditText mEmailView;
private CheckBox cbRememberEmail;
private AppPreferences appPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
appPreferences = new AppPreferences(LoginActivity.this);
loadUserCredentials();
}
#Override
protected void onResume() {
super.onResume();
loadUserCredentials();
}
#Override
protected void onStart() {
super.onStart();
loadUserCredentials();
}
private void loadUserCredentials() {
String rememberEmail = appPreferences.getPreferenceString(PREF_REMEMBER_EMAIL);
String email = appPreferences.getPreferenceString(PREF_EMAIL);
mEmailView = (EditText) findViewById(R.id.email);
mEmailView.setText((rememberEmail == "1") ? email : "");
cbRememberEmail = (CheckBox) findViewById(R.id.cbRememberEmail);
cbRememberEmail.setChecked(rememberEmail == "1" ? true : false);
mEmail = mPassword = "";
}
private void saveUserCredentials() {
try {
String rememberemail = (((CheckBox) findViewById(R.id.cbRememberEmail)).isChecked()) ? "1" : "0";
appPreferences.setPreferenceString(PREF_REMEMBER_EMAIL, rememberemail);
String email = (rememberemail == "1") ? mEmail : "";
appPreferences.setPreferenceString(PREF_EMAIL, email);
}
public void cbRememberEmailClick(View view) {
boolean checked = ((CheckBox) findViewById(R.id.cbRememberEmail)).isChecked();
if (checked) {
new AlertDialog.Builder(this).setTitle(R.string.remember_email_notification_title).setMessage(R.string.remember_email_notification_message).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((CheckBox) findViewById(R.id.cbRememberEmail)).setChecked(true);
}
}).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((CheckBox) findViewById(R.id.cbRememberEmail)).setChecked(false);
}
}).show();
}
}
// ...
}
The AppPreferences class:
public class AppPreferences {
Context context;
private SharedPreferences settings = null;
private static String LOGIN_CREDENTIALS = "com.example.login.credentials";
private static String DEFAULT_STRING = "";
public AppPreferences(Context context) {
this.context = context;
settings = PreferenceManager.getDefaultSharedPreferences(context);
}
private String getKey(String key) {
return LOGIN_CREDENTIALS + "." + key;
}
public String getPreferenceString(String key) {
return settings.getString(getKey(key), DEFAULT_STRING);
}
public void setPreferenceString(String key, String value) throws Exception {
SharedPreferences.Editor editor = settings.edit();
editor.putString(getKey(key), (String) value);
editor.commit();
}
// ...
}
Any help is really appreciated, I'm stuck at this for days and it's really frustrating now.
Thanks in advance.
Dediqated
You don't show the code that calls saveUserCredentials. You should call it in onPause:
#Override
protected void onPause() {
super.onPause();
saveUserCredentials();
}
If you call it in one of the later lifecycle methods (such as onDestroy), it won't be called if the app is force-closed while in the background. (You can defer this to onStop if you are targeting only Honeycomb and later.)
i fixed it by changing the field rememberEmail to a Boolean instead of a string containing a 1 or 0. I dont know why this didn't work but I'm happier about the fact that after 11 days of frustration this is no issue anymore.
Also did I delete all the preference files in folder /data/data/com.example/shared_prefs/
changed code in LoginActivity
// ....
private void loadUserCredentials() {
Boolean rememberEmail = appPreferences.getPreferenceBoolean(PREF_REMEMBER_EMAIL);
String email = appPreferences.getPreferenceString(PREF_EMAIL);
mEmailView = (EditText) findViewById(R.id.email);
mEmailView.setText(rememberEmail ? email : "");
cbRememberEmail = (CheckBox) findViewById(R.id.cbRememberEmail);
cbRememberEmail.setChecked(rememberEmail);
}
private void saveUserCredentials() {
try {
Boolean rememberEmail = ((CheckBox) findViewById(R.id.cbRememberEmail)).isChecked();
appPreferences.setPreferenceBoolean(PREF_REMEMBER_EMAIL, rememberEmail);
String email = (rememberEmail) ? mEmail : "";
appPreferences.setPreferenceString(PREF_EMAIL, email);
}
// ....
and in AppPreferences
// ....
private String getKey(String key) {
key = key.toLowerCase();
return LOGIN_CREDENTIALS + "." + key;
}
// newly added methods below
public String getPreferenceBoolean(String key) {
return settings.getBoolean(getKey(key), DEFAULT_BOOLEAN);
}
public void setPreferenceBoolean(String key, Boolean value) throws Exception {
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(getKey(key), (Boolean) value);
editor.commit();
}
// ....
I hope you won't make the same mistake as I did ;)
I'd recommend you, putting the save method into the onDestroy method
If you are calling saveUserCredentials(); when ever checkbox is checked,This should work perfectly.Also try to initialise preference obj on start of application
Hi i have a class (MyCustomForm.xml) which i use as a LoginForm for the user.
Now i want to save and load the value from the username(EditText) from the LoginForm using SharedPreferences but i do not know how to set the value of username saved by SharedPreferences into the EditText in LoginForm(MyCustomForm.xml).
I was thinking to save the value in OnPause in my Main.xml and load the value through OnCreate in the class MyCustomForm.xml
Generaly i would like to use SharedPreferences globaly.
How would this look like?
Can somebody please help me to get on the right track?
It was thinking something like this Main.xml:
public class AndroidLogin extends Activity implements OnClickListener {
#Override
protected void onPause() {
super.onPause();
Editor e = mPrefs.edit();
e.putString(USERNM, username);
e.commit();
}
}
Code MyCustomForm (LoginForm):
public class MyCustomForm extends Dialog {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.sencide.R.layout.inlogdialog);
EditText userTest = (EditText)findViewById(R.id.txtUserName);
userTest.setText(USERNM);
}
}
You can do something like this :
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(YouActivity.this);
String servername = settings.getString("sharedPreferencesKey", "defaultValue");
server.setText(servername); // EditText
And you store data like this :
SharedPreferences.Editor editor = settings.edit();
editor.putString("server", "serverName");
EDIT :
This piece of code should do the trick for you :
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
String servername = settings.getString("sharedPreferencesKey", "defaultValue");
You need to use the Prefs & Editor
SharedPreferences spOptions;
SharedPreferences.Editor spOptionEditor;
spOptions = getSharedPreferences("yourKey", 0);
spOptionEditor = spOptions.edit();
string username = spOptions.getString("USERNM", null)
null represents the default value if you don't have anything stored yet
You store the data like this:
spOptionEditor.putString("USERNM", txtUsername.getText().toString());
spOptionEditor.commit();
Generally I would recommend you to save the username on a valid login, and not in any lifecycle method.
Then change myForm to this:
public class MyCustomForm extends Dialog {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.sencide.R.layout.inlogdialog);
String s = getContext().getSharedPreferences("prefName", Mode.PRIVATE).getString(USERNM);
EditText userTest = (EditText)findViewById(R.id.txtUserName);
userTest.setText(s);
}
}
public void sharedPrefernces() {
sh_Pref = getSharedPreferences("Login Credentials", MODE_PRIVATE);
toEdit = sh_Pref.edit();
toEdit.putString("Username", username);
toEdit.putString("Password", password);
toEdit.commit();
}
Read more: http://mrbool.com/how-to-implement-shared-preferences-in-android/28370#ixzz34ymRp6mN
Just create a file called preferences... and store the value to it using different methods.
Use the methods people have suggested to put and get data from them...
public class Settings extends PreferenceActivity implements
OnSharedPreferenceChangeListener{
public static final String PREFS_PRIVATE = "PREFS_PRIVATE";
public static final String MASTERKEY = "!##$%^&*";
public static final String KEYA = "KEYA";
public static final String KEYB = "KEYB";
public static final String KEYC = "KEYC";
--- the create and get methods for getting and sharing data in the prefs... .....
public static void createPreference(Context context){
getPrefs(context).edit().putString(KEYA, "Default");
getPrefs(context).edit().putInt(KEYB, 0);
getPrefs(context).edit().putLong(KEYC, 0);
getPrefs(context).edit().putBoolean(KEYD, false);
getPrefs(context).edit().commit();
}
public static SharedPreferences getPrefs(Context context) {
return context.getSharedPreferences(PREFS_PRIVATE, 0);
}
public static String getUsername(Context context) {
getPrefs(context).getString(USERNAME, "default");
}
public static void setUsername(Context context, String value) {
getPrefs(context).edit().putString(USERNAME, value).commit();
}
}
..... so on and so forth..... Just implement it if you find any doubt or any thing that you need in more specific please let me know.
Whenever I try to add this line it crashes my app. Am I not putting it in the right spot?
preferences.registerOnSharedPreferenceChangeListener(myActivity.this);
Here is my class
class Simulation extends View {
// I declare my program variables here
public Simulation(Context context) {
super(context);
// get the preferences
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(context);
preferences
.registerOnSharedPreferenceChangeListener(myActivity.this);
String storedPreference = preferences.getString("nPref", "0");
}
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
Log.i(TAG, "preferences changed!");
}
}
Thanks!
Do like this
SharedPreferences.OnSharedPreferenceChangeListener prefListener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key) {
if (key.equals("date")) {
}
}
};
and
preferences.registerOnSharedPreferenceChangeListener(prefListener);
One note about the Answer, the prefListener needs to be a class field, not a local variable or it may get garbage collected.
SharedPreferences.onSharedPreferenceChangeListener not being called consistently