Android Store and Retrieve Data - java

How do I store and retrieve private application data for my app? I have an activity that runs depending on certain parameters entered by the user (file path, volume, etc.) and I want to be able to store what they input and then retrieve it every time they open the activity.
Should I user FileWrite or FileOutputStream/FileInputStream?
UPDATE:
Currently I have this as the code for saving the string.
final String audioPathFN = "Audio_Path";
final String audioPathC = String.valueOf(path);
FileOutputStream saveAudioPath;
try {
saveAudioPath = openFileOutput(audioPathFN, Context.MODE_PRIVATE);
saveAudioPath.write(audioPathC.getBytes());
saveAudioPath.close();
} catch (Exception e) {
e.printStackTrace();
}
Now how do I retrieve the string so I can use it in the app?

There are a few mechanisms to store private data :
SharedPreferences
using a simple file in you activity.getCacheDir() folder
a database
All those options are explained here : http://developer.android.com/training/basics/data-storage/index.html
Of course, all those solutions are local, you can also wanna use a web-service to communicate data with a server, but you would then be entering in a totally different landscape.

Related

Read a file from shared location with access restrictions (java)

I have a program that has to read a file from network location - something like this
String sFileSource = "//MyShared/location/fileName.txt" ;
File inputFile = new File(sFileSource);
try {
ffBuffer = new BufferedReader(new FileReader(inputFile));
}
catch (FileNotFoundException e) { // should never happen
}
Now, the problem is that that shared location is on the different network domain and accessible only using domain credentials
How can I embed entering the credentials into this java program ? The problem is that when ran from different PCs it fails due to login.
Reading a file like that is not a secure way to do it, because you will expose your user domain credentiels.
Reversing the java app could lead to that, so it's better to use an ftp server for that.
The way I have done it before:
Read remote file in java which needs username and password

Methods for saving user input like notes (Android Studio/Java programming)?

I am starting to code an app for taking notes, like Evernote or a basic preinstalled memo app, so that I can learn and practice coding.
Currently I save the user input in a .txt file, so that every note would have an own text file in the storage, with the note content.
What are other methods of saving user input in storage (you don't need to explain it, keyword would be appropriate) and what are the advantages or disadvantages of doing so? What can be cons of saving text files like I'm now doing?
Save the content to a file in your app's cache
If the content is plain text (and not too long), you can easily use SharedPreferences to save the content
You can use a database
Note that if the content is rich text, you can format that (for example, using HTML, JSON or XML and save files (like images) in a specified folder and write the location of the files to the formatted text) and then save to a database.
Useful links to get started:
Using databases:
https://developer.android.com/training/data-storage/sqlite
https://developer.android.com/training/data-storage/room
https://www.tutorialspoint.com/android/android_sqlite_database.htm
Rich Text Editors:
https://github.com/chinalwb/Android-Rich-text-Editor
https://github.com/wasabeef/richeditor-android
How to get cache directory?
File cacheDir = this.getCacheDir();
or
File cacheDir = this.getApplicationContext().getCacheDir();
Note that if the content is important, you can create a new folder in the storage (like "My App Name Files") and save the content to that folder.
If you are using EditText:
I name the EditText uinput. Here we go:
private void saveContent() {
String content = uinput.getText().toString();
String name = "Note 1"; // You can create a new EditText for getting name
// Using SharedPreferences (the simple way)
SharedPreferences sp = this.getApplicationContext().getSharedPreferences("notes", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString(name, content);
editor.apply();
}
private Map<String, ?> getAllNotes() {
SharedPreferences sp = this.getApplicationContext().getSharedPreferences("notes", Context.MODE_PRIVATE);
return sp.getAll();
}
private String getNoteContent(String noteName) {
SharedPreferences sp = this.getApplicationContext().getSharedPreferences("notes", Context.MODE_PRIVATE);
return sp.getString(noteName, "Default Value (If not exists)");
}
Don't save other things in SharedPreferences "notes".

Saving to file in android

I created a simple map creator for a game and I want to create a save button that will save all the information of the level in the game files forever (so when they quit the app the level will still be there), I tried saving all the information in a text file, but I fail to understand how it works and how to work with the FileOutputStream and how to load later on the text file. Is there an easier way to save a level or more suggested way? and can anyone explain me how to save a text file and load it simply? Thanks!
If you are not storing a lot of data, the best way would be to use SharedPreferences. Here, the data is stored as key value pair. It is easier to store and retrieve data using this.
e.g.
To store data
SharedPreferences preferences = getSharedPreferences("temp", getApplicationContext().MODE_PRIVATE);
Editor editor = preferences.edit();
editor.putString("name", name);
editor.commit();
To fetch data
SharedPreferences preferences=getSharedPreferences("temp", getApplicationContext().MODE_PRIVATE);
String name=preferences.getString("name",null);
Definitely the SQL Lite database is that what you want to use, if you save your data inside the DB, you will (later if you are enhancing your appp) have the possibility to easy sync saved information with a server so the gamestate can be synced with other devices without using the DB and just SharedPrefs this is much more complicated.
I would also advice you to use greendao which is an ORM for Android so you don't need to write plain SQL code
In case you really want to use Streams,
Inside your onClick method for your save button, you want to call this:
try
{
FileOutputStream fos = getApplicationContext().openFileOutput("file_name.txt", Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(obj);
os.close();
} catch(Exception e) {
//handle exceptions
}
which will save whatever you defined in obj to a file named "file_name.txt".
To read obj back from this textfile, you can call:
try
{
FileInputStream fis = getApplicationContext().openFileInput("file_name.txt");
ObjectInputStream is = new ObjectInputStream(fis);
my_obj = (MyObject) is.readObject();
is.close();
} catch(Exception e) {
//handle exceptions
}

Files not being written to device

I have been trying a hundred different methods to solve my problem, but for some reason they simple won't work.
I'm trying to make a quick and dirty way, for my application to be persistent. It basically got a lot of objects it needs to save when destroying, so I thought I would make it put the objects into an ArrayList, and then write the ArrayList to the file using an ObjectOutputStream.
public void onStop() {
super.onStop();
Log.d("Event", "Stopped");
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = openFileOutput("Flights", MODE_WORLD_WRITEABLE);
oos = new ObjectOutputStream(fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<Flight> alFlightList = new ArrayList<Flight>();
Iterator it = flightMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
alFlightList.add((Flight) pairs.getValue());
}
try {
oos.writeObject(alFlightList);
oos.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
Log.d("Info", "File created!");
}
}
I got a similar algorithm for reading it out again, but it complains about there not being any file to read from.
I know using files for persistence is not the best practice, but this is as previously mentioned, supposed to have been a quick and dirty solution. (But the time I have used on it now, might as well have been spent on making a database. ._.)
Thanks!
From the documentation on Saving Persistent State,
There are generally two kinds of persistent state than an activity
will deal with: shared document-like data (typically stored in a
SQLite database using a content provider) and internal state such as
user preferences.
For content provider data, we suggest that activities use a "edit in
place" user model. That is, any edits a user makes are effectively
made immediately without requiring an additional confirmation step.
Supporting this model is generally a simple matter of following two
rules:
When creating a new document, the backing database entry or file for
it is created immediately. For example, if the user chooses to write a
new e-mail, a new entry for that e-mail is created as soon as they
start entering data, so that if they go to any other activity after
that point this e-mail will now appear in the list of drafts. When an
activity's onPause() method is called, it should commit to the backing
content provider or file any changes the user has made. This ensures
that those changes will be seen by any other activity that is about to
run. You will probably want to commit your data even more aggressively
at key times during your activity's lifecycle: for example before
starting a new activity, before finishing your own activity, when the
user switches between input fields, etc.
So if you want to do it "correctly", I would save the data in onPause... and I'd probably save the state using an SQLite database of some sorts. You should also perform file I/O on a separate thread using an AsyncTask, as this sort of thing could potentially block the UI thread and crash your app.
If you want a quick and dirty way to do it (i.e. if you are not releasing this application on the Android market), then I am betting that the problem is that you are trying to perform the file I/O in onDestroy, which is not guaranteed to be called. This is another reason to perform the file reads/writes in onPause.
The last thing I would suggest is reading through the documentation on internal/external storage. It could be that you aren't writing to the correct directory because you don't have the file permissions to do so. You should perform the file I/O like so:
String FILENAME = "FLIGHTS";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(...);
fos.close();
Replace Flight in /sdcard/Flights or else it creates a file in null space. :)
I am not sure if it will work.
Why don't you use database? and call back all the setting from the database when the app is created or restarted?
You can also use onpause() or onstop() method to store all the data into the database.

Using a button to export sqlite db to an excel-readable file (perhaps csv)?

I adapted this tutorial (http://www.screaming-penguin.com/node/7749) to an Android app I've built to allow for a button press to export the current database to the user's sdcard. It works flawlessly.
But I'm afraid that users of my app would be unfamiliar with the db file, and I'm looking for a way to convert that to a more user-friendly format. I came across this thread (http://groups.google.com/group/android-beginners/browse_thread/thread/4e53ebca14daecfc), which recommends "querying data from the database and writing the data into a csv file."
I was hoping someone could point me in the right direction to begin figuring out how to do this. I'm finding it hard to track down more information about the specific method.
Or does it make more sense to just explain in a short "about" how to read and access .db files?
Thanks
EDIT: I also have a question about the sqlite export process, which I think I'll just ask here rather than create a new question. Is there a way to modify the code below so that each export would receive either a string representation of the date or just a single numeral appended to it? Right now if you export a second time, it automatically overwrites the old file. Thanks.
protected Boolean doInBackground(final String... args) {
File dbFile = new File(Environment.getDataDirectory() +
"/data/com.example.example/databases/data");
File exportDir = new File(Environment.getExternalStorageDirectory(), "exampledata");
if (exportDir.exists()) {
exportDir.mkdirs();
}
File file = new File(exportDir, dbFile.getName());
try {
file.createNewFile();
this.copyFile(dbFile, file);
return true;
} catch(IOException e) {
Log.e(MyApplication.APP_NAME, e.getMessage(), e);
return false;
}
}
I was hoping someone could point me in the right direction to begin figuring out how to do this.
To read in the data, use rawQuery().
To write the data, use Java I/O. There are also open source CSV libraries for Java that may work on Android.
Is there a way to modify the code below so that each export would receive either a string representation of the date or just a single numeral appended to it?
Use string concatenation to add whatever you want to the filename.
Also, please get rid of:
File dbFile = new File(Environment.getDataDirectory() +
"/data/com.example.example/databases/data");
and replace it with:
File dbFile=getDatabasePath("data");

Categories