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
}
Related
Most of the examples I have seen deal with external memory or show how to create a new directory inside internal memory but not how to write to it, I tried implementing my own code into it but can't seem to find the created file even though the directory has been created, here is the code that I have been trying to use:
public void fileCreate(Context context, String fileDir) throws Exception{
File myNewDir = context.getDir(fileDir, Context.MODE_PRIVATE);
if (!myNewDir.exists()){
myNewDir.mkdirs();
File testContnet = new File(myNewDir + "/hello_file.txt");
String hello = "Hello world";
FileOutputStream fos = openFileOutput(testContnet.toString(), Context.MODE_PRIVATE);
fos.write(hello.getBytes());
fos.close();
}
}
Now, when I call this function I use:
try {
fileCreate(this, "testerDirectory");
}catch(Exception e) {
e.printStackTrace();
}
With no results. It is just for a small experiment I am doing so it is nothing too serious, but I still want to know about the proper way of creating a directory(in this case one called testerDirectory, and saving the file to it, I believe that my code is wrong but I do not have much experience with this to know exactly where to go. The Android documentation did show me how to create and save files although in this case I am trying to merge that example with that of creating a new directory and saving a file to it. Any help/pointers would be greatly appreciated.
I know also that the file is not being written accordingly upon inspecting the contents of the directory by using the adb shell.
You are only writing a file to the directory if the directory does not already exist.
Move your work with testContnet to be outside of the if block:
public void fileCreate(Context context, String fileDir) throws Exception{
File myNewDir = context.getDir(fileDir, Context.MODE_PRIVATE);
if (!myNewDir.exists()){
myNewDir.mkdirs();
}
File testContnet = new File(myNewDir, "hello_file.txt");
String hello = "Hello world";
FileOutputStream fos = new FileOutputstream(testContnet);
fos.write(hello.getBytes());
fos.flush();
fos.getFD().sync();
fos.close();
}
This way, you create the directory if it does not exist, but then create the file in either case. I also added fos.flush() and fos.getFD().sync(), to ensure all bytes get written to disk before you continue.
UPDATE: You were using openFileOutput(), which does not write to your desired directory. Moreover, it is unnecessary. Just create a FileOutputStream on your File.
In my app I want a small database (.sql), with data about energy (kCal) in food.
The problem is, I have a bit expertise with SQL, but I don't really get my database into my app. Do I have to make a new .java file? Or I've read somewhere else, in my assets? I think the database isn't on a server, just within the app. The project I already have, is an about about food, overweight and BMI. Now I want to add a database about the amount of kCal in food.
I do not really know what I have to say more here. Hopefully you understand what I'm trying to do. I've read ALL related questions here on Stackoverflow, but still didn't got an answer.
If you can help me, you would be my hero! :)
Thank you all in advance,
Jacob
Android's built-in on-device DBMS is not mysql, but SQLite. You can find an excellent tutorial on setting it up and integrating it into your app here.
Create the SQLite database file with whatever data you want in it on your PC. Then create an assets folder in your project root in Eclipse (same level as src/, bin/, libs/, res/, etc.). Put your SQLite file in there. Then write some code to copy that asset file into the correct location on the device. Following is the code I currently use for that. I wrote it a while back when I was a beginner so there is probably a better way, but this works.
try {
InputStream is = getActivity().getApplicationContext().getAssets().open("sourceDatabaseFile.db");
OutputStream os = new FileOutputStream(getActivity().getApplicationContext().getDatabasePath("destinationDatabaseFile.db"));
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.flush();
os.close();
is.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
Another way would be to create the database using some Android code, and then have a (giant) class containing all the SQL statements to insert the data into the database.
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.
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.
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");