I'm developing an Android app that uses Google Places API.
In order to keep the Google API Key out of the application code, I fetch it from my own authenticated API server and its needed in many places around the app.
what is the best way of storing / caching it to memory ?
I understand that just using a singleton will be garbage collected.
is extending the Application class and adding methods to there a good method ?
anything else I might consider ?
Use SharedPreferences
To save to preferences:
PreferenceManager.getDefaultSharedPreferences(context).edit().putString("MYAPIKEY",
"myStringToSave").commit();
To get a stored preference:
PreferenceManager.getDefaultSharedPreferences(context).getString("MYAPIKEY",
"defaultStringIfNothingFound");
Where context is your Context.
Once you get it from server, save it. You can then access it as and when you want. Uninstalling an app will of course remove its contents. Else it is persistant.
A VM cannot garbage collect string references that classes can still reach, so I don't see why you cannot keep the string in a singleton and store it as a static reference. You can also store it in a shared preference like Doomsknight suggests, but this will not be cached in memory. Shared preferences are stored as XML files on a persistence store (against values available on a RAM). Values are retrieved back from them.
Perhaps you need a combination of the two. Store the value in a shared preference and then cache it in memory when your app starts. I'm unaware if the PreferenceManager by itself has a caching mechanism of some sort in memory.
Related
Actually, I have a doubt regarding SharedPreferences in android.
I have started learning Android a few days back and I am creating a SignUp Page for now, for that, I have searched the internet and got some ideas and now I am using multiple shared preferences in my code which I am thinking it would be a bad practice. So, I just wanna know, what happens to the Application if we create multiple shared preferences in the code.
This will just result in multiple SharedPrefenrences files (XML) in the data folder of your app. This is neither a problem nor a bad practice. If you have larger sets of structured data, consider using a database (e.g. SQLite/Room).
It is not bad practice at all. There is always a default shared preference.
we can get default shared pref filename using .getDefaultSharedPreferences() method.
you can get back up of any single shared pref file which is efficient.
With the concept of consuming more memory we shouldn't use SharedPreference to store large amounts of data, Alwayas use SQL DB in android for that. Multiple sharedpreference is good because , you can store data seperate for different sections within the app if it doesn't need to be shared. Shared preference is just a xml file with key value pair. So if you store only simple key value pairs, its okay to have multiple shared preferences. But be logical in your decision, dont just do that because you can
Is there a better architecture that we can follow other that making these fields static(bad for performance) or storing in Shared Preference.
Either use Shared prefs or a database. Both are optimized for quick and (more or less) safe access. It might be worth your while to read about Architecture Components, Room (or others such as ObjectBox, Realm, etc) and repository pattern.
Android Jetpack would be your best option. Check out the documentation on Data Binding, it would allow you to access fields like user_id without writing tons of boilerplate java/kotlin code, by injecting the data directly into you xml code. Here's the link: Android Jetpack Data Binding
There is nothing wrong in saving two/three Strings as static variables, In fact it is the fastest way to get repeatedly used variables. I prefer Application class to do so(static variables of Application class), but the issue is if your app happens to crash for some reason, application class is recreated and app starts from the previous activity, alas your static variables are long gone, be aware of this pitfall
Depends on how/when you are using these static elements.
A few application global variables like userSession object might make sense to store in the MyApplication file itself and made exposed throughout the app so you confirm it is valid when app returns from background each time for example.
SharedPreference is not a great place to store secure elements as it is on file storage in unencrypted xml format which rooted phones and others may have access to get to.
Database is a fine option, but it requires more code bloat and requires a database connection and query everytime you want to use the token if you don't plan to store it in RAM.
Another option is a singleton class that is meant to store your necessary application elements like FirebaseHelper for example that could populate into RAM on app startup and utilize your variables throughout the application life.
So really depends on your app needs. You can also use a SecureSharedPreference tool. There are a few open source options out there for this that you can just include in your project that encrypt the xml elements for you if you prefer to use the xml for storing these items.
If it was me, I would either you a secureSharedPref if it was simple things like userId, Token, or things like that that are fairly harmless. Of course it will encrypt them, but worst case if they got your token, they could make a few API calls if they knew what they were doing, unlikely. Now storing things like password, bank info, medical records, or anything else sensitive definitely should be in a Database. In fact, I would go one step further and layer it with SQLCipher.
So long story short is it depends on what you are storing and the risk assessment of it's content being accessed and each app will be different.
Absolutely nothing wrong with storing some static variables or singletons. Anyone building an enterprise level application will have a fair amount of statics in their application if it is architected in a good way.
I have a quiz app that shuffles everytime it is run. What is the most elegant way of saving a game state locally so that my user can resume the quiz using the same ordered list as before, as well as other primitives such as score, level, life points, etc.
I already have a bundle that saves this state when the game is paused. How can I retain the state when my activity is destroyed.
I know of shared preferences, but there must be something more elegant?
I think we need to understand firstly that there is several possibilities to save data in your app (with possibility to re-enter application and restore data):
1) Save on disc (it fast, but you can erase this data, for example, when reinstall application)
2) Save on remote disc (it slow, but it will keep your game progress throug removing and reinstalling app).
So first of all you need to choose one of this possibilities. I think in your case it will be enough to keep changes locally on disc (besides remote storage cost some additional $$)
In first possibility there are several variants to implement it:
- through shared preferences
- through saving in file (internal storage)
- through saving in file (external storage)
- through keeping data in database
I think last variant is not for you, since you want to just save state of game.
And 'external storage' variant is not for you, too, because game state is private data of your application.
So you need to choose between shared preferences and internal storrage.
In this dilemma, you can think about what you like more. For me shared preferences provides convenient and async way to save data, which is more preferable in game. But you need to think about how many data you want to keep.
If it's not big, choose Shared preferences. And if you do enance your way to save in SharedPreferences (write less code and make it more readable), you can import Gson or Jackson library. Then pick out special GameState class for your game and just convert it to json string and save. Same for restoring. Pick string from prefs and parse it to GameState. That's all.
Hope it helps. :)
I suggest you to use a database and a cursor for retrieving the huge data list. https://developer.android.com/training/basics/data-storage/databases.html
SQLite is very fast and not hard to implement.
Im saving datas from my db/user into a gson formated ArrayList in SharedPreferences. Now my question :
Is it safe to save these datas (or data in general) into Sharedpreferences. Are users able to read these gson Arraylists out ? Maybe from SD card ,in a folder or somewhere else.
Thank you !
They are stored as xml files in your app directory, with permissions that allow only your app to access them. But on rooted device they are easily accessible. If you are concerned with security then you may use encryption, those projects might be usefull to you:
https://github.com/rtoshiro/SecureSharedPreferences
https://github.com/sveinungkb/encrypted-userprefs
still those projects does not give you 100% guarantee, hacker may decompile your apk and find keys used to encrypt shared preferences. So if your data is of use only for short time then remember to remove it from your device once user has finished using it. You may for example keep data on server and download it only when needed, caching locally only for short time - when its needed.
SharedPreferences is just a file located in phone private memory. So user can't access it but root can. Root can everything and many users have root's nowadays. You shouldn't store fragile data there
Android SharedPreference security
You can read all shared preferences Data
The SharedPreferences class provides a general framework that allows
you to save and retrieve persistent key-value pairs of primitive data
types.
To see the information in the store you need to know the important thing from the data. This will make reading through the information super easy. But as simple as it's to keep a tiny bit of data as difficult it's to keep and browse large structured data since you need to define key for every data, in addition you can't really search inside the data except you've got a certain concept for naming the secrets.
Please read Android SharedPreference security
After reading the documention it seems that onSaveInstanceStaate works per instance (as the name suggests). I am just wondering what the preffered method of storing data is so that it is available for all instances of that activity?
As MaciejGorski mentioned in his comment, there are different levels of data storage available in Android:
Shared preferences
Internal storage
External storage
SQLite database
Network
From personal experience, the lower you go down this list, the more complicated your implementation will become. Thus, if you are simply trying to save simple data for your app to be shared among different instances of an activity (or of multiple activities), shared preferences are certainly the way to go. You can even create private shared preferences, which only your app can access.
In any case, check out this SO answer for how to implement them: How to use SharedPreferences in Android to store, fetch and edit values