I am working on android project built partially in kotlin and partially in java. I am trying to pass information from a kotlin fragment class to a java class. I have come to see that there is a problem with the passing of information as I do not receive the needed value. After some debugging I have seen that the information is successfully stored, however when the information from shared preferences is accessed, only the default value is returned.
This is the code in the kotlin class. When a button is clicked it changes the value of a boolean variable to the opposite one, sets the text of a button to true/false and saves the value of the variable in shared preferences.
btnStyle.setOnClickListener() {
styleHasChanged = !styleHasChanged;
if(styleHasChanged == true){
btnStyle.setText("true")
}else{
btnStyle.setText("false")
}
val sharedPref : SharedPreferences?= activity?.getPreferences(MODE_PRIVATE);
sharedPref?.edit()?.putBoolean("bla", styleHasChanged)?.apply()
}
This is the java class. Shared preferences is called inside a function which chooses a filepath based on the received value.
public static String getHtmlContent(Context context, String htmlContent, Config config) {
SharedPreferences sharedPreferences = context.getSharedPreferences("bla",MODE_PRIVATE);
boolean hasStyleChanged = sharedPreferences.getBoolean("bla", false);
//moj
String cssPath;
if (!hasStyleChanged) {
cssPath = String.format(context.getString(R.string.css_tag), "file:///android_asset/css/Style.css");
} else {
cssPath = String.format(context.getString(R.string.css_tag), "file:///android_asset/css/Style2.css");
}
This is where the problem arises. Shared preferences in the java class always fetches the default value, no matter if the button is clicked or not.
The getPreferences method implicitly uses the class name of the Activity as the preference file name. By passing "bla" as the file name to getSharedPreferences you're trying to fetch the saved value from a different file.
If you would like to access the same preferences accross your application, then either use getSharedPreferences (for both writing and reading the preference) with the same file name, or use the getDefaultSharedPreferences static method of PreferenceManager to obtain the default SharedPreferences instance.
You should change your code to something like this:
val sharedPref : SharedPreferences? = activity?
.getSharedPreferences("someFileName", MODE_PRIVATE)
sharedPref?.edit()?.putBoolean("bla", styleHasChanged)?.apply()
And the Java part:
SharedPreferences sharedPreferences = context
.getSharedPreferences("someFileName", MODE_PRIVATE);
boolean hasStyleChanged = sharedPreferences.getBoolean("bla", false);
Your context.getSharedPreferences("PreferencesFileName",MODE_PRIVATE) should be the same even when using the activity?.getPreferences("PreferencesFileName",MODE_PRIVATE). In you code it's not like that.
Plus a simple suggestion, because I'm not sure if you're clear on that. The bla is the key for your boolean value not your Preferences file name. I mean it could be, but it's better to separate.
Related
I have a shared preference with no default value defined in the xml because I would like to set the default value programmatically when the main activity is created. The preference in question should either be the device language (if that language is available), otherwise the first available language, where the languages are defined in the appropriate xml as a string array.
I currently have, inside the main activity's onCreate method, the following
SharedPreferences preferences = getSharedPreferences(
getString(R.string.shared_prefs_key),
MODE_PRIVATE
);
String detailLanguage = preferences.getString(
getResources().getString(R.string.detail_display_language),
""
);
if (detailLanguage.isEmpty()) {
String deviceLanguage = Locale.getDefault().getLanguage();
String[] availableLanguages = getResources().getStringArray(R.array.pref_entry_values_detail_display_language);
boolean deviceLanguageSupported = false;
for (String availableLanguage : availableLanguages) {
if (deviceLanguage.equals(availableLanguage)) {
deviceLanguageSupported = true;
break;
}
}
preferences.edit()
.putString(
getResources()
.getString(R.string.detail_display_language),
deviceLanguageSupported ? deviceLanguage : availableLanguages[0]
).commit();
Debugging this code on the first run it enters the above if statement and sets the preference but the preference doesn't show as selected in the preference activity first time around (if I then select it myself, from then onward it appears selected as something).
Am I missing something? I am fairly new to Android. I tried the above based on some other similar SO questions.
PreferenceActivity and PreferenceFragment read preferences from a default preference file. To get access to those preferences you should use PreferenceManager.getDefaultSharedPreferences(context) method.
I am guessing that this is the reason you aren't seeing your changes: you write them to getString(R.string.shared_prefs_key) rather than to the default one.
Try changing your first line to this:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
I know there must be douzens of answers to this question out there, but either i cant't find them or I don't understand them.
The Question:
How do I get my app to exactly start as it was left?
F.e. dynamicly added checkBoxes shouldn't dissapear!
There is no "out of the box" way of doing it. You could save the current state of your Activity in some way (More on persistence)
Then you need to be able to rebuild the desired state of the persisted state in your Activity lifecycle
You could save and load with the shared preferences for example:
public void saveState(YourState state) {
SharedPreferences sharedPreferences = app.getSharedPreferences(R.string.preference_file_key, Context.MODE_PRIVATE)
sharedPreferences.edit()
.putString("CustomAtt", state.getCustomAtt())
}
public YourState loadState() {
SharedPreferences sharedPreferences = app.getSharedPreferences(R.string.preference_file_key, Context.MODE_PRIVATE)
String customAtt = sharedPreferences.getString("CustomAtt", "DefaultValue")
return new YoutState(customAtt)
}
And use it like this
#Override
protected void onCreate(Bundle savedInstanceState) {
YourState state = loadState();
// Rebuild your activity based on state
someView.setText(state.getCustomAtt())
}
You can store such values in SharedPreferences.
https://developer.android.com/training/basics/data-storage/shared-preferences.html
It is using key-value approach for saving. So you can save some values and read it from SharedPreferences whenever you want to.
This is the best approach for small data, that can be used on the app launch. So you can quit your app and the data is still present - so can be read on the next app launch.
Or save the condition of your program to a text file, so that the program can "translate" it back into conditions before it stops, or what I do not recommend, it saves every object created with ObjectOutputStream.
I have a variable and I want to change it only the first time that I start my app. For example:
I open the app: Variable is not initialized. Variable changes to 4.
I close the app
I open the app Variable is 4.
And so on.
How can I do this?
I guess you are new to Android. You can save the values using "SharedPreferences".
Check this link : https://developer.android.com/training/basics/data-storage/shared-preferences.html
Also check out this example :
https://www.tutorialspoint.com/android/android_shared_preferences.htm
You can use this code :
SharedPreferences sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
Editor editor = sharedpreferences.edit();
editor.putString("key", "value");
editor.commit();
Here, MyPREFERENCES is the file name. Replace the "value" with the variable name.
Again, if you want to retrieve the value, then use:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.getBoolean("key", true);
//There are other methods like getInt(),getDouoble().getString() depending on the type of value
You can also write to a local file and use SQLite for that purposes if you would like to persist big object's data.
In MainActivity.java I write
SharedPreferences pref = getApplicationContext().getSharedPreferences("My_Pref" , 0);
Then I create object of Editor to put data in it
Editor edit = pref.edit();
Then I put data
edit.putString("1","Hello");
edit.commit(); / edit.apply();
In Second.java, I get preferences:
SharedPreferences pref = getPreferences(0);
then I try to receive data like
pref.getString("1",null);
and set it to text of textview. But this does not work.
Also, how do I access Preferences and editor in other java classes properly? I cannot understand the concept.
You are writing to and reading from different preference files. Use the same file and it should work.
To get an instance of SharedPreferences you do this:
1) In activity MainActivity:
SharedPreferences pref =
getApplicationContext().getSharedPreferences("My_Pref" , 0);
2) In activitySecond:
SharedPreferences pref =
getPreferences(0);
The first form opens preference file "My_Pref", the second form opens a file named after your activity class, i.e.: "Second". So they are reading and writing in different files.
I always use this form to open a preferences file:
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(this);
Try this way
public void saveToSharedPrefrence(Context context, String word) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
Editor editor = sharedPreferences.edit();
if (sharedPreferences.contains("history")) {
preExistRemove(word, context);
} else {
editor.putString("history", word.trim());
editor.commit();
}
}
Check this for more details
Get the context of your activity
Context shrdContext= ActivityClass.getContextOfApplication();
Now pass the context to get your shared preferences in your another class
SharedPreferences myPrefs= PreferenceManager.getDefaultSharedPreferences(shrdContext);
You have 3 ways to access preferences for a Android application.
The first you used is
SharedPreferences pref = getApplicationContext().getSharedPreferences("My_Pref" , 0); is the first one. With this you can read and write to a custom-named shared preference file. In your case the name of your file would be My_Pref.
This one is useful if you want to have differents preferences differents domain as it allow you to create many shared preferences with differents names. (ex : preferences for timezone, preference for your user).
The second getPreferences(int) allow to access preferences for an Activity and is bind closely to the activity calling it. The file created is named using the Activity name. In your case Second.
The third method PreferenceManager.getDefaultSharedPreferences(Context) create a shared preference file like the first method, but this time the file is named using your application package name. This is the best methods to use shared preferences, if you intend to have only one shared preference file.
In your initial question you wrote a data in one file and tried to read in an other file, which result in an error. That's why like Rob Meeuwisse write you must use PreferenceManager.getDefaultSharedPreferences(Context)
I am using Android Shared Preference for saving some small Boolean data. Now if I use the same keyword string that passed as String Parameter to the getSharedPreferences() method to save my all boolean values like that sample code is they conflict?
I mean if I use A common String for all getSharedPreferences() method and inside them if I use different String in putBoolean() is they are saved properly? Actually whats the functionality of the String argument of getSharedPreferences()?
I used this to save values:
public void saveStatus(boolean b){
SharedPreferences preferences = getApplicationContext().getSharedPreferences("STATUS", android.content.Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("s1",b);
editor.commit();
}
they won't conflict if you use different key values like s1 s2 s3 different keyword for each boolean value other wise it will overwrite earlier value(This way will make keys unique):
why don't you pass two parameters to tackle issue like this:
public void saveStatus(String key,boolean b){
SharedPreferences preferences = getApplicationContext().getSharedPreferences("STATUS", android.content.Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(key,b);
editor.commit();
}
They will not conflict
Shared Preferences are stored as xml files.So the string argument(first one) you are passing in the getSharedPreferences() is the name of the xml file which will be created in persistent storage while the one you are using in the putBoolean() is the name of the property with its value specified as second argument which wil be added in that xml file.
For further details also see this:
Where are shared preferences stored?
About XML files