Hello in my app I need to store single object with several fields. At this moment it is saved like this
#Override
public Object onRetainNonConfigurationInstance() {
return UILApplication.advert;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Advert retainedAdvert = (Advert) getLastNonConfigurationInstance();
if (retainedAdvert != null) {
UILApplication.advert = retainedAdvert;
}
}
Where UILApplication is singleton to keep advert. Sometimes ( often when call camera) advert object is erised to default. So i want to know about save and efficient way to kepp this object. Is it wise to store it in file/ serialise it or create database for a single record or there is something better?
Taken from my calculator:
#SuppressWarnings("unchecked")
private void loadState() {
ObjectInputStream ois;
try {
ois = new ObjectInputStream(openFileInput(FILE_STATE));
state = ((State) ois.readObject());
ois.close();
ois = new ObjectInputStream(openFileInput(FILE_HISTORY));
historyListAdapter.setItems((List<String>) ois.readObject());
ois.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
state = new State();
} catch (IOException e) {
e.printStackTrace();
state = new State();
} catch (ClassNotFoundException e) {
Toast t = Toast.makeText(this, "Error parsing saved state",
Toast.LENGTH_SHORT);
t.show();
state = new State();
}
setState(state);
}
private void saveState() {
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(openFileOutput(FILE_STATE,
Context.MODE_PRIVATE));
oos.writeObject(state);
oos.close();
oos = new ObjectOutputStream(openFileOutput(FILE_HISTORY,
Context.MODE_PRIVATE));
oos.writeObject(historyListAdapter.getItems());
oos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onPause() {
saveState();
super.onPause();
}
Call loadState() in onCreate().
Worked fine for me, I know its not advised to use java serialization in android, but I didn't encounter any errors or bugs whatsoever. No issues with performance either.
You should of course tweak error handling depending on your application.
Depends how big your object is. Try with shared preferences: http://developer.android.com/guide/topics/data/data-storage.html#pref
Combination of preferences, right places to populate/read from it, and some static init method could do things for you.
Hope it helps.
Related
I have created a ListView and it can add data dynamically but whenever I restart the App the previous stored list is lost.
How can I save that list ?
You can save them into client local via using android SharedPreferences
Or, you can write your own model.
You should pass your object here;
public boolean writeYourObjectOnLocal(File dir, YourObject yourObject) {
ObjectOutput output = null;
OutputStream buffer = null;
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(dir.toString() + File.separator + "myFile.dat");
buffer = new BufferedOutputStream(fileOutputStream);
output = new ObjectOutputStream(buffer);
output.writeObject(yourObject);
return true;
} catch (Throwable e) {
return false;
} finally {
try {
output.close();
} catch (Throwable e) {}
try {
buffer.close();
} catch (Throwable e) {}
try {
fileOutputStream.close();
} catch (Throwable e) {}
}
}
You can Read your object;
public YourObject readYourObjectFromLocal(File dir) {
ObjectInput input = null;
BufferedInputStream buffer = null;
FileInputStream fileInputStream = null;
try {
String fileName = dir.toString() + File.separator + "myFile.dat";
fileInputStream = new FileInputStream(fileName);
buffer = new BufferedInputStream(fileInputStream);
input = new ObjectInputStream(buffer);
return (YourObject)input;
} catch (Throwable e) {
return null;
} finally {
try {
input.close();
} catch (Throwable e) {
}
try {
fileInputStream.close();
} catch (Throwable e) {
}
try {
buffer.close();
} catch (Throwable e) {
}
}
}
I would recommend you to use caching library like Reservoir. Check instructions how to use it on this link.
https://github.com/anupcowkur/Reservoir
Be sure to allocate enough memory in your application class (size in bytes).
Example: Save data (Async):
// it can be any type of object (here is String)
List<String> strings = new ArrayList<String>();
strings.add("one");
strings.add("two");
strings.add("three");
Reservoir.putAsync("myListKey", strings, new ReservoirPutCallback() {
#Override
public void onSuccess() {
//success
}
#Override
public void onFailure(Exception e) {
//error
}
});
Example: Read saved data (Async):
Reservoir.getAsync("myListKey", new TypeToken<List<String>>() {}.getType(),
new ReservoirGetCallback<List<String>>() {
#Override
public void onSuccess(List<String> strings) {
//success - set your list adapter and show those items
}
#Override
public void onFailure(Exception e) {
//error
}
});
If you need to persist large volume of data you should use SQLite database and it is best for this purpose. But you can also use xml to store your data, xml is slow then SQLite database.
You can refer this standard Storage options.
I have a class that contains 2 functions:
public class FileHandler extends Activity {
public void writeToFile(){
String fileName = "lastDevice.txt";
try {
FileOutputStream fos = openFileOutput(fileName, MODE_PRIVATE); //Exception thrown here
fos.write("some device id".getBytes());
fos.close();
Toast.makeText(this, "File updated", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String readFromFile(){
try {
String fileName = "lastDevice.txt";
FileInputStream fis = openFileInput(fileName); //Exception thrown here
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String sLine = null;
String data ="";
while ((sLine = br.readLine())!=null) {
data+= sLine;
}
return data;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "FileNotFoundException";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "IOException";
} catch (NullPointerException e){
// TODO Auto-generated catch block
e.printStackTrace();
return "Null Pointer Exception";
}
}
these functions are called from my main activity as follows:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvDevices = (ListView)findViewById(R.id.ListViewDevices);
lastDeviceTxt = (TextView)findViewById(R.id.lastDeviceTxt);
//get last connected device
FileHandler fh = new FileHandler();
String last = fh.readFromFile();
lastDeviceTxt.setText(last);
}
but i keep getting a NullPointerException from both functions.
when running the functions from my MainActivity (I copied them to my main activity) they work fine.
What am I doing wrong? (please remember that I'm very new to android development).
You've defined FileHandler as an Activity. You can't instantiate an Activity yourself, which you are doing here:
FileHandler fh = new FileHandler();
Activities need to be instantiated by the Android framework (otherwise their context isn't set up correctly).
If you don't want these methods in your own Activity, then you can put them in another class. However, that class cannot inherit from Activity. You will then find that you need to pass your Activity's Context to these methods so that they can call methods like openFileInput()
I want my app to hold data from ArrayList in file in between sessions. Class I use implements Serializable. When I debug saving seems to go OK, with no exceptions thrown, and going through the loop the right amount of times. Loading loads just some of entries and then throws EOF Exception. The code is here:
public int saveChildren(Context context){
FileOutputStream fos;
ObjectOutputStream os;
try {
fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
os = new ObjectOutputStream(fos);
for(Child c : children){
os.writeObject(c);
}
os.close();
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 1;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 2;
}
return 0;
}
public void loadChildren(Context context){
FileInputStream fis;
try {
fis = context.openFileInput(filename);
ObjectInputStream is;
is = new ObjectInputStream(fis);
while(is.readObject() != null){
Child c = (Child) is.readObject();
boolean skip = false;
for(Child ch: children){
if(ch.getName().equals(c.getName())){
skip = true;
}
if(ch.getNr().equals(c.getNr())){
skip = true;
}
if(ch.getImei() != null){
if(ch.getImei().equals(c.getImei())){
skip = true;
}
}
}
if(!skip){
children.add(c);
}
}
is.close();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (StreamCorruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
What causes the errors?
You can directly write the children object into the ObjectOutputStream. ArrayList implements serializable. A second thing you might want to do is flush the stream before closing it with os.flush(). You will have:
os = new ObjectOutputStream(fos);
os.writeObject(children);
os.flush();
os.close();
and for reading:
is = new ObjectInputStream(fis);
ArrayList<Child> children = (ArrayList<Child>)is.readObject();
is.close();
You're using ObjectInputStream#readObject() returning null as an exit condition for your loop. #readObject() can return null - if you've serialized a null - it will however throw an exception if it fails to read an object because you've reached the end of the stream.
For a quick and easy fix: Consider serializing the length of the array as an integer before serializing the children & use a for-loop or similar construct to read the values - or serializing the ArrayList itself. It's also Serializable.
I am currently saving a message to a single file from multiple activity classes within my app. Each activity class has the same function WriteToFile.
public void WriteToFile(String info) {
FileOutputStream FoutS = null;
OutputStreamWriter outSW = null;
try {
FoutS = openFileOutput("file.txt", MODE_PRIVATE);
outSW = new OutputStreamWriter(FoutS);
outSW.write(info);
outSW.flush();
}
catch (Exception e) {
}
finally {
try {
outSW.close();
FoutS.close();
} catch (IOException e) {
}
}
}
I have been attempting to create a separate class which holds this function write (and read) to file but I haven't been able to without getting errors.
I think the function needs to have context passed through to the WriteToFile void like...
//Changes to this line
public void WriteToFile(String info, Context context) {
FileOutputStream FoutS = null;
OutputStreamWriter outSW = null;
try {
//Changes to this line
FoutS = context.openFileOutput("file.txt", MODE_PRIVATE);
outSW = new OutputStreamWriter(FoutS);
outSW.write(info);
outSW.flush();
}
catch (Exception e) {
}
finally {
try {
outSW.close();
FoutS.close();
} catch (IOException e) {
}
}
}
if that is correct am I passing the context correctly?
String msg = "This is a message";
WriteToFile(msg, this);
It's not working so I am doing something wrong.
You should use your context to call the method
context.openFileOutput("file.txt", context.MODE_PRIVATE);
what you wrote has no meaning, or far from what you mean.
This is my first attempt at serializing/deserializing objects on any platform and, to put it mildly, I'm confused.
After implementing Serializable to my game object I output it to a file thus:
public void saveGameState(){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(theGame);//theGame is an instance of the custom class
//TGame which stores game info.
byte[] buf = bos.toByteArray();
FileOutputStream fos = this.openFileOutput(filename,
Context.MODE_PRIVATE);
fos.write(buf);
fos.close();
} catch(IOException ioe) {
Log.e("serializeObject", "error", ioe);
}
File f =this.getDir(filename, 0);
Log.v("FILE",f.getName());
}
This seems to work, in that I get no exceptions raised. I can only know for sure when I deserialize it. Which is where things go pear shaped.
public God loadSavedGame(){
TGame g=null;
InputStream instream = null;
try {
instream = openFileInput(filename);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
try {
ObjectInputStream ois = new ObjectInputStream(instream);
try {
g= (TGame) ois.readObject();
return g;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
I got the basis of this code from here Android Java -- Deserializing a file on the Android platform and tried to modify it for my app. When running I get
05-31 23:30:45.493: ERROR/copybit(1279): copyBits failed (Invalid argument)
When the output should be loaded and the saved game start up from when it was saved.
Any help would be appreciated.
The error you've shown is not at all related to serialization: its actually a video display error. I'd suggest looking at the object BEFORE you serialize to make sure its not null, and I'd also suggest serializing to a file on the SD card to make sure you actually had data output (so use new FileOutputStream("/mnt/sdcard/serializationtest") as the output stream and new FileInputStream("/mnt/sdcard/serializationtest") as the input stream) while you are debugging; you can switch back to the context methods after it works, but make sure your sdcard is plugged in while you are doing this.
Finally, modify your logging to look like this:
try {
ObjectInputStream ois = new ObjectInputStream(instream);
try {
g= (TGame) ois.readObject();
return g;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
android.util.Log.e("DESERIALIZATION FAILED (CLASS NOT FOUND):"+e.getMessage(), e);
e.printStackTrace();
return null;
}
} catch (StreamCorruptedException e) {
android.util.Log.e("DESERIALIZATION FAILED (CORRUPT):"+e.getMessage(), e);
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (IOException e) {
android.util.Log.e("DESERIALIZATION FAILED (IO EXCEPTION):"+e.getMessage(), e);
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
and see what error gets returned. I expect the serialization is failing somehow.
To seralize or deserialize anything you can use SIMPLE api. It is very easy to use. Download the file and use it in your program
Have a look here
http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#deserialize
Thanks Deepak
I have created below class to do the save and retrieve object.
public class SerializeUtil {
public static <T extends Serializable> void saveObjectToFile(Context context, T object, String fileName){
try {
FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(object);
os.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static<T extends Serializable> T getObjectFromFile(Context context, String fileName){
T object = null;
try {
FileInputStream fis = context.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
object = (T) is.readObject();
is.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return object;
}
public static void removeSerializable(Context context, String filename) {
context.deleteFile(filename);
}
}