This question already has an answer here:
Saving user settings from GUI
(1 answer)
Closed 8 years ago.
How can i save the value of a variable in my program and then reuse it at the next program run ? I don't want to do it with file write/read.
Use the Java Preferences API.
import java.util.prefs.*;
public class Example {
// Preference key
private static final String FRUIT = "fruit";
public void savePreference(String favoriteFruit) {
Preferences prefs = Preferences.userNodeForPackage(Example.class);
prefs.put(FRUIT, favoriteFruit);
}
public String readPreference() {
Preferences prefs = Preferences.userNodeForPackage(Example.class);
return prefs.get(FRUIT, "default");
}
}
The data is stored based on the fully-qualified name of your class, so your package name and class name are relevant. From the documentation for the Preferences class:
This class allows applications to store and retrieve user and system preference and configuration data. This data is stored persistently in an implementation-dependent backing store. Typical implementations include flat files, OS-specific registries, directory servers and SQL databases. The user of this class needn't be concerned with details of the backing store.
One can store settings using java.util.prefs.Preferences. For two target groups: normally user settings, and less often application/system settings. They can use the platform settings, like under Windows.
There exists however also the possibility to store the settings as XML, which is a cleaner way, as it does not touch the Windows registry, which might be protected. Then a customary location would be inside a directory like ".myapp" under the directory System.getProperty("user.home").
You can use an in-memory key-value store like Redis, or an in-memory database like H2. But this may be overkill depending on your needs.
Related
I started to learn Android few days back and so far I am done with implementing Login Activity, Main Activity which extends abstract Base Activity.
Nav Bar item when clicked opens xml from Fragments.
I have a question about the token that I receive after successful login. This token is being used with each request to get data after successful login. Should I save the token in sqlite database securely or I should make a public property in Main Activity? Main Activity will always remain in memory as this will open fragments.
I can suggest 3 options:
1) you can save the token to the file, something like this:
public static void saveToken(Context ctx, String fileName, Object token) {
if (token == null) {
ctx.deleteFile(fileName);
} else {
ObjectOutputStream out = null;
try {
FileOutputStream fout = ctx.openFileOutput(fileName, 0);
out = new ObjectOutputStream(fout);
out.writeObject(token);
fout.getFD().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Make sure object token implements java.io.Serializable interface.
Usage before API level 24:
saveToken(appContext, someFileName, someTokenObject);
Usage with API level 24 and higher:
saveToken(appContext.createDeviceProtectedStorageContext(), someFileName, someTokenObject);
2) Use SQLCipher library for encrypted database.
3) You can encrypt your token using keystore system https://developer.android.com/training/articles/keystore.html
Use SharedPreferences and make sure you are using Context.MODE_PRIVATE this way only your app can access the data. SharedPreferences is a persistent store
e.g.
SharedPreferences prefs = context.getPreferences(Context.MODE_PRIVATE);
prefs.edit().putString("token", token).apply();
token = prefs.getString("token");
Why not to use SQLite:
SQLite is a database and is targeted at tabular data, a single token does not fit this use case.
Why not store in the main activity:
The main activity will not be around for the lifetime of the application install, it can be cleaned up by the OS at any time. It is not a persistent data store.
Should I save the token in sqlite database securely or I should make a public property in Main Activity? Main Activity will always remain in memory as this will open fragments.
The Official Android documentation already answers your question in the section on called "Best practices for security and privacy". It gives the following statement:
If you have access to user data and can avoid storing or transmitting it, don't store or transmit the data
In other words, if you can avoid persisting then don't persist it.
You mentioned "public property" in your question which makes me wonder if the concept of visibility modifiers is not yet clear. The Java public and private modifiers are for controlling access to the members of your class. They have nothing to do with security as per this answer here.
If you do persist the token in memory, as a public field or otherwise, you may reduce your exposure slightly by storing the token in a char[] rather than a String. That also is detailed in this canonical answer.
Finally, if you do have to store the token, the sqlite database is not the correct place to do it. Instead, you should use the provided KeyStore which will make for more difficult extraction of the token in the case that the device is compromised. The link to the documentation above is complete with code examples. If this proves too difficult to use, there are some wrappers around it including Scytale.
1) Store the token value within the base application singleton (where your application must be an instance of BaseApplication)
public class BaseApplication extends Application {
// token
private String token = null;
public String getToken() {return this.token;}
public void setToken(String token) {this.token = token;}
}
With the implementation above you will be able to set and get the token value from any activity/fragment. However the value is not persistent and it will be lost once the application ends.
Remark: If you are using the token for REST api access then you can store the token in the background service instance using a similar solution as above.
2) Use SharedPreferences - this is recommended way in case you want to store the token's value between application's runs.
Please see the answer from #Ryan.
You can use SharedPreferences to store token.it is available over application.
You can store it in Shared Preference as this one is token.
Now coming to the part of Security You can obviously use encryption for the shared preference.
There are already lots of open items available you can use below library for example
https://github.com/ophio/secure-preferences
Regarding keys that are in your java file to encrypt, You need to be sure you are applying proguard before you upload it to playstore.
In that manner now your token is fully secure with shared preferences.
In order to save it in sqlite than by decoding or root access your db file can also be accessed same as preferences. Regarding clear data from setting I think it will delete your sqlite data as well. Not sure about this though.
I hope it will help you out.
Better to use Sqlite or Realm. And store in Application memory and not in external memory. As for data residing in application memory we don't need to worry much about security. Saving in MainActivity is not a good solution, as once application closes, this will get cleared.
Storing in Shared Preference is also an option. But if user clears the cache from setting's this value will also get cleared. Realm Android Reference Link
I have a maps app on android that tracks your route via location data and stores the LatLng points in an SQL database and draws a line on the map with Polyline.
I would like to go further with that and allow the user to be able to save the route and load past routes. Is there a way that I can store/delete the entire table data into a file so that a fresh route can be created, then be able to load that file into the database again if the user chooses?
1: use objects to store your datas, and keep them as a Collection for example (Set, Map, ...)
2: use serialization, it is direct
What does Serializable mean?
You could try making a Route class, containing all information you want to store in your database, like so:
public class Coordinate {
double longitude;
double latitude;
public Coordinate(double x, double y){
this.longitude = x;
this.latitude = y;
}
}
public class Route {
private List<Coordinate> coordinates;
public Route() {
coordinates = new ArrayList<>();
}
}
Using Google Gson, you can convert routes to a Json file. You can store these files in the local storage, and use them when the user wants to use a past route.
A fantastic Guide to get you started:
http://developer.android.com/training/location/receive-location-updates.html
A tutorial, probably exactly what you are looking for:
http://javapapers.com/android/draw-path-on-google-maps-android-api/
Further Reading:
I would look at Google's Android Location API:
https://developers.google.com/android/reference/com/google/android/gms/location/package-summary
It also has a listener inbuilt, so that when the users location changes it will update you automatically.
You could then keep a history, like you suggest in your Database and when required. Then when required using the API to rebuild or monitor the users current path.
Location Listener: https://developers.google.com/android/reference/com/google/android/gms/location/LocationListener
Your Data, like you also suggest should translate to/from the API stored 'Location' format of:
http://developer.android.com/reference/android/location/Location.html
Well lets think clever here.
A route contains many possible locations.So a good idea is to create two sql tables.One table will be for the locations and one for routes
So you will make a search and you will find all locations that exist in a route.It depends on what kind of implementation you will make for your database.
I want to make a game level logic. The game itself similar with logo quiz game. It has locked and unlocked level. I need to display the locked and unlocked level based on the score which saved in shared preferences. so, how can I access the score variable in XML file?
declare these two variable in your activity
android.content.SharedPreferences someData;
public static String filename = "mySharedString";
initialize the Shared Preferences like this:
someData = getSharedPreferences(filename, 0);
you can add elements to the Shared Preferences like this:
android.content.SharedPreferences.Editor editor = someData.edit();
editor.putString("sharedString", stringData);
editor.commit();
you can retrieve data like this:
String dataReturned = someData.getString("sharedString","Couldn't load data");
The Couldn't load data will be set to the dataReturned variable if the sharedString is not existed in the Shared Preferences
also check this question How to use SharedPreferences in Android to store, fetch and edit values
I'd like to save user preferences from a sketch running either on a PC or an Android phone, using the same code in as standard "Java-way" as possible.
Ideal candidate for my purposes seems to be the java.util.prefs.Preferences class. So, I wrote a little test script to see if it's working in processing:
String prId = "counter";
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
int counter = prefs.getInt(prId, 0);
println(counter);
prefs.putInt(prId, 1+counter);
This program outputs an increasing number each time it is executed - on a PC. On Android, the default value (0) is always shown.
Are there any additional steps required to get this working on Android? Permissions to be requested?
Are there any alternatives for saving name - value pairs on both platforms?
Obs.: "WRITE_EXTERNAL_STORAGE" permission is already enabled
This is a known Android bug unfortunately: https://code.google.com/p/android/issues/detail?id=22232
Basically the app does not have write permissions for the generated path, which should be a system-specific location where the user has write permissions instead.
Simplest (cross platform) workaround could be to use java.util.Properties, where you have control over the storage location.
Another workaround (if you are tied to the Preferences API for some reason) might be to provide your own implementation of AbstractPreferences (perhaps backed by Android SharedPreferences?), see this SO post: Is there a way to use java.util.Preferences under Windows without it using the Registry as the backend?
P.S.: Another workaround option might be to explicitly export / import the data using Preferences.exportSubtree(OutputStream os) and
Preferences.importPreferences(InputStream is)
In Android, the preferred way to store preferences is to make use of SharedPreferences. The equivalent code would be like this:
String prId = "counter";
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
int counter = prefs.getInt(prId,0); // Get int, default is 0
SharedPreferences.Editor prefsEditor = prefs.edit();
prefsEditor.putInt(prId, counter++); // Put counter back
prefsEditor.commit(); //Don't forget to commit the changes
I don't know exactly why java.util.prefs.Preferences would fail in Android. I suspect the reason is data would be deleted after the current Activity or the application is destroyed.
Because directory structure is different on each platform, it's hard to get preferences by just using one single same method. For example, data is stored in /.java/.userPrefs/**yourpacakgename**/prefs.xml on Android while it's in Registry on Windows and in ~/Library/Preferences/**yourpacakgename**/prefs.xml on Mac OS X. Also, you can't use Preferences.userRoot() in Android because an application cannot get root access.
I am trying to create a free form BIRT report. The report is not consisted to rows which have the same columnNames in each row.
Instead, it is a free form report, which will be of the following form.
"Name: {FirstName} {LastName} Addess : {Address}
Phone# {Phone#}
....
....
"
I am using a scripted datasource, which essentially returns the Map containing the name value pairs of {FirstName, LastName, Address, Phone, and other fields}..
But I am not sure how to set the variables and how do I get the FirstName, LastName etc.
Should I try to use dynamic text.
I don't know of any way in which BIRT can handle non row related data.
Here's my open script of the dataset.
open:
util = new Packages.test.ReportsUtil();
reportsVO = util.getReportVO("ABC");
in fetch:
if(currentrow < totalrows) {
dataSetRow["FirstName"] = reportsVO.getPropValue("identity.FirstName");
dataSetRow["LastName"] = reportsVO.getPropValue("identity.LastName");
currentrow++;
} else {
return (false);
}
But I am not sure of how do I get access to the FirstName and LastName in the main layout page.
Thank you
The goal of a scripted data source is to allow you to leverage the logic inherent in your data model and benefit from any business rules that manipulate that data. In the end it still wants the data to be formed into a rather traditional row-based set.
You mention dynamic text and I think this would be a great use for the Java-based event handlers. You can use the logic in the Java object you had bound to the scripted data source to instead tie to an event in the life cycle of the report and get your non-relational data that way.
You can even call your Java object directly from a JavaScript event handler (much easier to plug into via the IDE) using the JS "Packages" construct.
There are many examples to help you get this done at the BIRT Exchange.
I did something similar (BIRT 3.7) but I used row["colName"] instead of dataSetRow["colName"] and that seems to work. I have my data in a list, and then each list item is a grid. I set the data binding in the list to the data set. The grid is able to see the value as row["colName"].