My application records user movement with Geofence boundaries, if the user exits the Geofence, alerts are appropriately escalated. These alert are counted and displayed in a summary at the end of the activity. However I would like to create a stats page where it displays the last week or month of activities as well as the number of alerts so that I can display these in a chart. Is there anyway to do this effectively without using a database?
I had thought of writing data to a log file and reading it but curious as to if there is a better option.
You can use SharedPreferences but it will require a lot of controls, probably more then creating a database. If you insist not to use a database, put an integer to your shared preferences saving the count of your data, also that integer will become your id. Then you can store your data with a loop depending on your data.
Here is to write your data to shared preferences
SharedPreferences mSharedPrefs = getSharedPreferences("MyStoredData",
MODE_PRIVATE);
private SharedPreferences.Editor mPrefsEditor = mSharedPrefs.edit();
int count = mSharedPrefs.getInt("storedDataCount", 0);
for(int i = 0 ; i < yourCurrentDataCount ; i++) {
mPrefsEditor.putInt("data" + count, yourData.get(i));
count++;
}
mPrefsEditor.putInt("storedDataCount", count);
And to get your data,
int count = mSharedPrefs.getInt("storedDataCount", 0);
for(int i = 0 ; i < count ; i++) {
yourData.add(mSharedPrefs.getString("data" + i, "defaultData"));
count++;
}
Edit:
I should have added some explaining. The idea is to save the count of your data to generate an id, and save the tag according to it. This code will work like this, lets say you have 5 strings. Since you don't have a MyStoredData xml, it will get created. Then since you don't have the "storedDataCount" tag, you will get 0 as a count. Your loop will iterate 5 times and in each iteration, you will add a tag to your xml like "<.data0>your first data<./data0><.data1>your second data <./data1>... After your loop is done, you will modify your storedDataCount and it will become <.storedDataCount>5<./ storedDataCount>. And the next time you use your app, your count will start from 5 so your tag will start from <.data5>. For reading, you will iterate through tags by checking "data0", "data1" and so on.
You can use java serialization if you dont want to use database.
You can also use XML/JSON for storing data.
I support already mentioned favoritism towards using a DB for this task. Nevertheless, if I were to do it via FS, I would use a transactional async library like Square's tape is.
In your case I would keep the data during a session in JSON object (structure) and persist it (in onPause()) and restore it (in onRestore()) with tape's GSON Object Converter.
Should be easy out of the box, I believe.
Tape website: http://square.github.io/tape/
Alternatively to manually persisting a file or using a 3rd party library like tape, you could always (de)serialize your JSON to SharedPreferences.
Related
Ultimately I am trying to store an Int Array in Shared Preferences but I know Kotlin doesn't support that. So I am converting my Int Array to a String Array using the method here:
How can I store an integer array in SharedPreferences?
My issue is that I am struggling to put in a default value for the getStringSet method:
private fun loadIntScoreArray() {
val prefs = getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE)
//TODO: Load the String array
var default = emptyList<String>()
avgScoreArrayString = prefs.getStringSet(AVG_SCORE_ARRAY, default)
}
However default is not an acceptable object in the prefs.getStringSet(AVG_SCORE_ARRAY, default) line. The error is confusing because it seems contradictory:
Required: MutableList
Found: (Mutable)Set!
Required: (Mutable)Set!
Found: MutableList
There is few things you need to know. Since API 11 you can only store plain objects or sets to shared preferences. You can convert your list to set, but it can be lossy conversion in your list contain duplicates.
If you want to use sets you should call it like this:
//to get
prefs.getStringSet(AVG_SCORE_ARRAY, emptySet<String>()))
//to set
prefs.edit().putStringSet(key, AVG_SCORE_ARRAY)
The other way is to join array to a single string using join operation. Here is a doc for you https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/join-to.html
To be honest both of these ways are not the perfect solutions. If it is production application and I recommend using persistance library like Room, Realm etc.
Hope it helps.
Edit.
If you are hundred percent sure you are going to have 5 ints stored (and it is not gonna change in a near or distant future), using database could be overkill. I recommend using joining to single string and storing it as single string or just store 5 independent int values. There is no point in complicating simple things.
I have 10 values (int and boolean) which I want to save, so I can load them whenever I need them (I need the different values at the same time which makes it easy). Is it overkill if I make one JSONString/(JSONObject) out of 10 values and save that string in SharedPreferences? Is it better practice to just store every single value like this:
editor.putInt("Volume", VolumeBar.getProgress());
editor.putInt("Difficulty", DifficultyBar.getProgress());
[...]
and to get it from SharedPreferences like this:
Volume = mPrefs.getInt("Volume", maxVolume);
Difficulty = mPrefs.getInt("Difficulty", 0);
I think it's better to create model with ten variables and convert it
to JsonString because you just put one strng value in SharedPref but it's issue that if you want to update one of it's values you have to retrieve the whole object and modify and set it back in sharedPref
I'm making an Android application and want to create a "Favorites" list for some objects in the app. I wanna make the list accessible and editable in all my activities and I can't really figure out the best way to do this.
Shared preferences? Writing a small txt file to the device? What's the fastest way to do this?
Thanks in advance!
dependencies {
compile 'com.google.code.gson:gson:2.3.1'
}
Then when you want to save, convert your array into String:
ArrayList<Type> yourData = new ArrayList<Type>();
String dataStr = new Gson().toJson(yourData);
//put this dataStr in your shared preferences as String
To retrieve and convert back to an object is also simple:
String str = "";
//you need to retrieve this string from shared preferences.
Type type = new TypeToken<ArrayList<Type>>() { }.getType();
ArrayList<Type> restoreData = new Gson().fromJson(str, type);
If you want to create a Favorites list, use a SQLite Database.
There's really only four ways to store data.
Shared Preferences
Databases
Local files
Remote Server - Slowest since it depends on network connection, so let's skip this.
Between the remaining 3, SharedPreferences is a great option when used to store a single value. However, it's not a good option for storing a Favorites list, mainly because you can only store a single String.
You can still store it by combining all items in your list into one string, then splitting it each time. However, as your Favorites list gets larger, this single long String will too. Splitting and combining all the time isn't efficient.
SharedPreferences is still a decent option if you only have to store the Favorite's list, but since you want to edit it too, it becomes a less attractive solution.
Local Files and Databases are the better options, however local files require you to read in the file each time you want to use it. This process of reading and writing to a file isn't as efficient as using a Database, especially if you want to edit. For example, let's say you want to remove an item from the middle of your Favorite's list. This would require you to read in the file, edit it, then write the change into the file again. Not too pleasant when compared with the ease of the final solution.
Databases are the best option for this, mainly because it's designed to manage data. You can create a single Favorite's table and add each item as it's own individual row. Fetching the entire table becomes quick and easy. Fetching a single item becomes quick and easy. Adding a new item or removing a new item is also quick and easy.
I save chosen items into shared preference, but as the user during runtime get to remove any of these items (from any position), and as I use the saved size (in the code below) to loop through the items, and here's the problem
Say I have 5 items ( item_1 - item_2 - item_3 - item_4 - item_5 )
if the user removed item_2 I update chosen_items_size to be 4 and I remove item_2 from the shared preference.
but when I load the items later I use the (size = which is 4 now), which as in the code below will miss item_5, how to fix this, any suggestions or better approach to achieve what I need?
mSharedPreference = getSharedPreferences("chosen_items", MODE_PRIVATE);
int size = mSharedPreference.getInt("chosen_items_size", 0);
for(int i = 1; i <= size; i++) {
mSharedPreference.getString("item_" + i, null);
}
Knowing that I want to enable drag and drop items, which using the above approach will make it pretty hard (if possible in the first place) to accomplish, any better approach to save & retrieve data / items?
Thank you
If you have a small amount of strings you can store them in one delimited string in SharedPreferences like so. You could also associate some metadata with each item and delimit that too.
You could utilize a built in SQL lite database.
Is this data that must persist between sessions? if not store it locally with a class and static variables/arrays.
I created an app in which users can add various markers on google maps using overlays. I want the app to save the overlay when the user creates it so that when they re-open the app later the markers will still be present.
Currently anytime the app is re-opened the created markers are gone. I have searched the internet and have not gotten a clear understanding of how to save my markers/overlays offline for later use.
As mentioned, you need to use some persistent storage. Perhaps, database would be an excess in your particular case (if you simply need to save a bunch of longitude-latitude pairs), and Shared Preferences would fit your needs. If you rarely need to read/store this data, then putting JSONArray as a String to Shared Preferences would be the simplest (in terms of reading and extracting data) solution:
SharedPreferences.Editor editor = getSharedPreferences("name", 0).edit();
JSONArray jsonArr = new JSONArray();
JSONObject json;
for (int i = 0; i < user_markers.size(); i++) { // here I assume that user_markers is a list where you store markers added by user
json = new JSONObject();
json.put("lat", user_markers.get(i).getLat());
json.put("long", user_markers.get(i).getLong());
jsonArr.put(json);
}
editor.putString("markers", jsonArr.toString());
editor.commit();
If you need to read/store this data a bit more often, then you may assign ids/indexes to separate SharedPreferences's values, but this may require more complicated extraction method. For example:
SharedPreferences.Editor editor = getSharedPreferences("name", 0).edit();
int id;
for (int i = 0; i < user_markers.size(); i++) { // here I assume that user_markers is a list where you store markers added by user
id = user_markers.get(i).getId(); // some Id here
// or simply id = i;
editor.putString("markers_lat_" + id, user_markers.get(i).getLat());
editor.putString("markers_long_" + id, user_markers.get(i).getLong());
}
editor.commit();
After all, you should consider using database if you plan to store big amount of data or data of complicated structure.
It just an idea, but you can save your markers in database and when you reopen your map just query database and put it on the map again...
You should use some persistent storage. SQLite would probably be the best option here. Overlays have their lat and lng. Just get them and whatever data you need along with them and put all these in the SQLite database. Then on Activity start get the points from database and show them on the map.
Use a SQLite database to save the user data. They are simple and for a large amount of data they are better than SharedPreferences.
More Info
Example