I am facing an issue with saving an object boolean in SharedPreferences. The object (part of ArrayList "questions") contains a boolean "recentAnswer".
If I change the boolean value and want to use it in another activity, the value is still the old one.
Here is my saveData-method from Activity 1:
private void saveData(){
SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(questions);
editor.putString("task list", json);
editor.apply();
}
and here's where I use it in order to save the changed boolean value (Activity 1):
private void checkAnswer(Button answerButton){
if (answerButton.getText().equals(questions.get(currentQuestion).getAnswer1())){
questions.get(currentQuestion).recentAnswer = true;
}
else{
questions.get(currentQuestion).recentAnswer = false;
}
Toast.makeText(this, Boolean.toString(questions.get(currentQuestion).recentAnswer), Toast.LENGTH_SHORT).show();
saveData();
}
Firstly, I load the ArrayList in Activity 2:
private void loadData(){
SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("task list", null);
Type type = new TypeToken<ArrayList<Question>>(){}.getType();
questions = gson.fromJson(json, type);
if(questions == null){
questions = new ArrayList<>();
}
}
And then I want to get the "recentAnswer" values (Activity 2):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_statistics);
loadData();
for (Question element : questions){
int recentWrong;
if (!element.recentAnswer){
recentWrong++;
}
}
Toast.makeText(this, Integer.toString(recentWrong), Toast.LENGTH_SHORT).show();
}
No matter, how I change the values in Activity 1, in Activity 2 "recentWrong" is always = 0, even though I am accessing the questions.
Don't do this:
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(questions);
editor.putString("task list", json);
Do not do this ever. First off is you are not checking and do not know what the value questions may hold and you also should not save something like that in SharedPrefs.
If you have several questions, then save each question together with its response in SharedPrefs and if you need to save an answer that you want to check against later in code, use string values stored in the res->strings.xml.
If the question is too long, find a way to concat it or use the res->string-arrays.xml and keep the questions there, then reference them from there.
You need to go back a bit and take a look at how to design programs in Java, Kotlin or any language for that matter. This is what comes after you learn programming basics.
Related
I'm making an android game with levels. I made a Button[][] Array which every Button has setEnabled(false) exept the first one which has been set true due to allow players to start the game and "unlock" other levels. I stored a global Boolean Array with the button enabling state so that every time i enter the "LevelsActivity" i can read the Boolean array and update the buttons states. And all of this works fine.
My question is about how to save this Boolean array so that i can load it after the app closing.
I read about SharedPreferences and i find out some code but i can't implement to my purpose. Furthermore i read that array aren't supported by SharedPreferences and i should convert the array to string but i still can't do it. Thanks in advance
This is my Global class if it could help:
public class Globals extends Application {
private boolean[] array = new boolean[125];
public Globals() {
for (int i = 0; i < 125; i++) {
array[i] = false;
}
array[0] = true;
}
public boolean getData(int i){
return this.array[i];
}
public void setData(int i, boolean value){
this.array[i]=value;
}
}
You can't put a boolean array directly, but you can put a boolean for each level. Something like:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences();
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("level_one", true);
editor.putBoolean("level_two", false);
...
editor.commit();
and then when you get to the activity where you need to check these values you can get them with
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences();
Boolean level_one = prefs.getBoolean("level_one", false);
Boolean level_two = prefs.getBoolean("level_two", false);
...
I'd store it as a string of 0's and 1's in one SharedPrefs, and then read that String back and populate the boolean array based in that.
SharedPreferences preferences =
getApplicationContext().getSharedPreferences("PREFS", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// Write
boolean[] array = new boolean[125];
StringBuilder builder = new StringBuilder();
for (boolean i : array) {
builder.append(i ? '1' : '0');
}
editor.putString("BOOLEAN_ARRAY", builder.toString()).apply();
// Read
String arrayPrefs = preferences.getString("BOOLEAN_ARRAY",null);
if(!TextUtils.isEmpty(arrayPrefs)){
for(int i = 0; i < array.length;i++){
array[i] = arrayPrefs.charAt(i) == '1';
}
}
You can use gson library to serialize your data and then save it in sharedPref:
Gson gradle dependency
implementation 'com.google.code.gson:gson:2.8.6'
Serializing array
val arrayOfBooleans = arrayOf(false, true, false, true)
// or you could use hashMap which has more readable output after serialization
val mapOfBooleans = mapOf(1 to false, 5 to true)
val serializedJson1 = Gson().toJson(arrayOfBooleans) // [false,true,false,true]
val serializedJson2 = Gson().toJson(mapOfBooleans) // {"1":false,"5":true}
Saving in SharedPreferences
fun saveData(json: String) {
val prefManager = PreferenceManager.getDefaultSharedPreferences(context)
prefManager
.edit()
.putString(KEY_OF_DATA, json)
.apply()
}
companion object {
const val KEY_OF_DATA = "keyOfData"
}
I am new to Android App Development and I am supposed to make a TodoList App for a course. But the SharedPreference in my code is not working. I dont know if I'm supposed to use it in a specific way in a specific method like onCreate or onStop.
It is saving the first input the user is entering permanently, but in the same position:
(The "task0" is what I used to track the different variable names I used as argument for "putString" in addStuff method, to avoid replacing values)
It is saving the inputs after that in the same session, but if the user ends that session, all those values after "t" are gone. If the user restarts the app and inputs something else (like "g"), it is saving "g" in that same 3rd position.
I have basic Java knowledge and I tried to understand what is going on using it, but failed. Please let me know where is the mistake and how to use SharedPreferences properly.
public class TodoActivity extends AppCompatActivity {
public ArrayList<String> items;
public ArrayAdapter<String> itemsAdapter;
public ListView list;
public String s;
public EditText taskBox;
public static final String filename = "itemsList";
public TextView text;
public static int counter = 0;//counter starting at 0 no matter what, everytime the app starts
public String newtask= "task";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todo);
list = (ListView) findViewById(R.id.list1);text = (TextView) findViewById(R.id.text1);
taskBox = (EditText) findViewById(R.id.box);
s = taskBox.getText().toString();
items = new ArrayList<String>();
itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
list.setAdapter(itemsAdapter);
//add items to list
items.add("First Item");
items.add("Second Item");
//restore
SharedPreferences sp = this.getSharedPreferences("itemsList", 0);
//checking if it stores the previous values, this gives the last input but not the previous ones after restarting the app
String dummyname = "task";
text.setText(String.valueOf(counter));//since counter is again at
for(int c=0; c<=50; c++){
String num = String.valueOf(c);
dummyname = dummyname + num;
String x = sp.getString(dummyname, "not found");
if (x.equalsIgnoreCase("not found")){
counter=c-1;
break;
} else {
items.add(x);
text.setText(dummyname);
}
}
}
public void addItem(View v){
s = taskBox.getText().toString();
itemsAdapter.add(s);//adding the new task as string
String temp = String.valueOf(counter);
newtask = "task" + temp;
//trying to store the new tasks with different variable names to avoid being replaced
text.setText(newtask);
SharedPreferences sp = this.getSharedPreferences("itemsList", 0);
SharedPreferences.Editor e = sp.edit();
e.putString(newtask,s);
e.apply();
counter++;
}
}
If you have relatively small collection of key-values that you would like to save,
You should use Shared preference API
Read from the shared preference:
Pass the key and value you want to write,create a SharedPreferences.Editor by calling edit() on your SharedPreferences.
Pass key and values you want to save by using this method putInt() ,putString() ,Then call commit() to save the changes. For example:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("KeyName", newHighScore);
editor.commit();
Write from the shared preference:
To retrieve values from a shared preferences file, call methods such as getInt() and getString(),
providing the key for the value you want, and optionally a default value to return if the key isn't present. For example:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt("KeyName", defaultValue);
Two things :
1) To initialize SharedPreferences use :
sharedPreferences = getSharedPreferences("itemsList", Context.MODE_PRIVATE);
2) Where are you calling addItem() method??
The problem is about the Tag you use to save items. See this Line :
dummyname = dummyname + num;
You add item by this format :
task0
task1
task2
but you are getting values in this format
task0
task01
task012
Just change these two line of code :
//dummyname = dummyname + num;
//String x = sp.getString(dummyname, "not found");
String newDummy= dummyname + num;
String x = sp.getString(newDummy, "not found");
This question already has answers here:
Gson - convert from Json to a typed ArrayList<T>
(9 answers)
Closed 6 years ago.
In my activity, the user has an array of images he picks, and then I want to store them in preferences. Then the user leaves the activity, and comes back, I want those images still loaded into an ImageView. I'm trying to use Gson to accomplish this, but am having trouble and can't see what I'm doing wrong.
Hoping external insight may help me with this obvious answer I'm just not seeing.
Thank you.
Here is my code so far.
private void savePreferencesForImages(String key, ArrayList<Image> imageList)
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(imageList);
editor.putString(key,json);
editor.commit();
}
//Storing Local data.
private void loadPreferences()
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Gson gson = new Gson();
String gsonString = sharedPreferences.getString("userImages", "");
ArrayList<Image> images = gson.fromJson(gsonString, Image.class);//Ask StackOverflow tomorrow.
}
In the part of retrieving the data you will need a type that deserialize the String into a List of Images...
like:
private void loadPreferences()
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Gson gson = new Gson();
Type type = new TypeToken<List<Image>>() {}.getType();
String gsonString = sharedPreferences.getString("userImages", "");
List<Image> images = gson.fromJson(gsonString, type);
}
One thing you can do is save the images individually and then load them into an ArrayList upon retrieval.
private void savePreferencesForImages(ArrayList<Image> imageList)
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
int imgKey = 0;
for (Image img: imageList) {
String json = gson.toJson(imageList);
editor.putString("" + imgKey,json);
editor.commit();
imgKey++;
}
}
private ArrayList<Image> loadPreferences()
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Gson gson = new Gson();
Map<String, ?> allPrefs = sharedPreferences.getAll();
String gsonString = sharedPreferences.getString("userImages", "");
ArrayList<Image> images = new ArrayList<Image>();
if (!allPrefs.isEmpty()) {
for (Map.Entry<String, ?> entry : allPrefs.entrySet()) {
String json = entry.getValue().toString();
Image temp = gson.fromJson(json, Image.class);
images.add(temp);
}
}
return images;
}
This is potentially the most over-complicated way to go about this but it is the first thing I could think of. You could also just make your own ImageManager class or something and emulate the behavior of an ArrayList, with a getImage(key) method and so on. This would eliminate the complications that are brought about when trying to save an ArrayList.
I am having an array list which is already stored in shared preferences.I want to add another item in array list.
Whenever i am trying to add an item in array list it is removing all the previous data stored in arraylist
How can i add item without removing the previous data in shared preferences
ArrayList<String> cartArrayListID,cartArrayListName,cartArrayListPrice,cartArrayListImage;
String cartID,cartName,cartPrice,cartImage;
cartArrayListID=new ArrayList<>();
cartArrayListName=new ArrayList<>();
cartArrayListPrice=new ArrayList<>();
cartArrayListImage=new ArrayList<>();
cartArrayListID.add(cartID);
cartArrayListName.add(cartName);
cartArrayListPrice.add(cartPrice);
cartArrayListImage.add(cartImage);
SharedPreferences sprefCart=getSharedPreferences("CARTINFO", Context.MODE_PRIVATE);
SharedPreferences.Editor editorCart=sprefCart.edit();
Gson gson = new Gson();
String id_=gson.toJson(cartArrayListID);
String name_=gson.toJson(cartArrayListName);
String price_=gson.toJson(cartArrayListPrice);
String image_=gson.toJson(cartArrayListImage);
editorCart.putString("ID", id_);
editorCart.putString("NAME", name_);
editorCart.putString("PRICE", price_);
editorCart.putString("IMAGE", image_);
editorCart.apply();
Toast.makeText(ProductActivity.this, "Added to cart", Toast.LENGTH_SHORT).show();
as I see in your code, you create a whole new ArrayLists cartArrayListID, cartArrayListName , ..etc everytime, and then you put the new value into it, after that you save it in SharedPreferences which in turn will replace the old one saved in it with your new one, so you have to:
get the corresponding ArrayList from Shared preferences at first.(for ex. cartArrayListName)
save it in a new array called cartArrayListID.
put the new values in this new array.
save it back in SharedPreferences.
You cannot get an ArrayList from SharedPreferences.
You can get a Set using getStringSet. Notice that the jdoc states that
Note that you must not modify the set instance returned by this call.
so do something like:
Set<String> mySet = new HashSet(yourPrefDataCollection);
mySet.add("some string");
sp.edit().putStringSet("your set key", mySet).commit();
Use GSON to get ArrayList from the String.
Add some items.
Try this example to save ArrayList to String, so you can store to SharedPreferences.
If your ArrayList has some special type (not String), use this construction:
ArrayList<Foo> list = new Gson().fromJson(
gsonString, new TypeToken<List<Foo>>(){}.getType());
The best way to accomplish this is by storing your array as a String in JSON format. You have to create a simple POJO to store your array and the rest is simple. See example below;
public void saveArray(List<String> yourArray) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("YOUR_ARRAY_KEY", new Gson().toJson(new ArrayListHolder(yourArray)));
editor.apply();
}
public List<String> getArray() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String arrayJson = sharedPreferences.getString("YOUR_ARRAY_KEY", null);
if (arrayJson != null) {
return new Gson().fromJson(arrayJson, ArrayListHolder.class).getYourArray();
}
return null;
}
private class ArrayListHolder {
private List<String> yourArray;
public ArrayListHolder(List<String> yourArray) {
this.yourArray = yourArray;
}
public List<String> getYourArray() {
return yourArray;
}
public void setYourArray(List<String> yourArray) {
this.yourArray = yourArray;
}
}
I save a string set in shared preferences that loads to my watchlist. When the user clicks on a button, in the movie's page, it takes the movie's name, title and release date and store them in a JSON object. All of them are stored as String. The problem persists when I try to add a movie in the watchlist, each new movie I add, the last movie gets overwritten, which means I can only have one movie in my watchlist at all time.
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences sharedPreferences = getSharedPreferences("WatchlistData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
JSONObject obj = new JSONObject();
try {
obj.put("name", name);
obj.put("date", releaseDate);
obj.put("platform", platform);
} catch (JSONException e) {
e.printStackTrace();
}
Set<String> set = new HashSet<String>();
set.add(obj.toString());
editor.putStringSet("setOfStrings", set);
editor.commit(); //saved
}
});
Watchlist fragment OnCreateView
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_watchlist, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.watchlist);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mWatchlistAdapter = new WatchlistAdapter(getActivity(), loadFromStorage());
mWatchlistAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mWatchlistAdapter);
return view;
}
The loadFromStorage, loads my xml file in the recyclerview, this method is passed in my adapter constructor.
SharedPreferences mPrefs = getActivity().getSharedPreferences("WatchlistData", Context.MODE_PRIVATE);
ArrayList<watchlist> items = new ArrayList<watchlist>();
Set<String> set = mPrefs.getStringSet("setOfStrings", null); //retrieving set of strings
if (set == null){
Toast.makeText(getActivity(), "No data found", Toast.LENGTH_LONG).show();
} else {
//for every string in set
for (String s : set) {
try {
JSONObject jsonObject = new JSONObject(s); //for every JSONObject String
String name = jsonObject.getString("name");
String date = jsonObject.getString("date");
String platform = jsonObject.getString("platform");
watchlist newGame = new watchlist();
newGame.setGame(name);
newGame.setDate(date);
newGame.setPlatform(platform);
items.add(newGame);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return items;
}
By default SharedPreferences replaces the old data with the newer one. What you can do is, get the old data first then append with with the newer one,
//Extract the value stored in SharedPreferences
String value = prefs.getString(<Key>, <DefaultValue>);
//Append to the extracted value
String appendedValue = append(value, newValue);
//Write the result back to SharedPreferences
editor.putString(<Key>, appendedValue).commit();
SharedPreferenced are made for lite weight data but not for heavy storage. So, according to your requirement you should write the data to a JSON/XML file in the external storage and read it back later.
it looks like you are just overwriting the stringset in SharedPreferences every time you put something there, which is why you only ever see the last result:
Set<String> set = new HashSet<String>();
set.add(obj.toString());
editor.putStringSet("setOfStrings", set);
You are just created a new 'set' on each click and saving that to "setOfStrings".
I was considering a similar implementation myself for a project, but saw that it became an issue manipulating the StringSet from SharedPreferences. For reference, [documentation on Android developers site](http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet(java.lang.String, java.util.Set))
states,
"Note that you must not modify the set instance returned by this call. The consistency of the stored data is not guaranteed if you do, nor is your ability to modify the instance at all."
There are workarounds to this, but from what I understand it is better to avoid using SharedPreferences for data such as this which will be manipulated often, as it is just saved as an xml file prone to issues- you may want to consider implementing that information in a SQLite database.