2

I'm currently working on an Android app that automatically changes the phones state based on a certain event, such as battery level. I have a Profile class which has 3 main parameters, names, Event and State (Event and State are 2 other custom classes)

In my ProfileEdit class, there are various components such as EditText and Spinner for users to configure a Profile. I need access to an ArrayList of type Profile in a ListActivity class which displays each profile, and my ProfileEdit class which gets the current ArrayList and adds the new profile, or updates one.

The idea I had to do this first was to use ObjectOutputStream to write my ArrayList to the phones sd card, then it can be retrieved by any class that needs it. However my attempts to do this so far just end up throwing an IOException. My code is as follows:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/sdcard/profile.prof"));
oos.writeObject(profiles);
oos.flush();
oos.close();

The profiles object is my ArrayList to be written to the file. I can't figure out why this is throwing the exception. I tried changing the object to a string by calling writeObject("Hello"); and that no longer threw the exception, so I can only assume its a problem with the ArrayList. I was under the impression that the ArrayList class implements serializable and my Profile class also implements serializable, although it does the same thing without.

Alternatively, if there's a better way I can give both my ProfileList (ListActivity) and ProfileEdit classes access to the same ArrayList then please let me know.

Edit: Here's the IO Exceptions stack trace: (Line 114 of the ProfileEdit class is the writeObject() line)

EZSettings(14788): IO Exception
EZSettings(14788): java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1535)
EZSettings(14788): java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
EZSettings(14788): java.util.ArrayList.writeObject(ArrayList.java:651)
EZSettings(14788): java.lang.reflect.Method.invokeNative(Native Method)
EZSettings(14788): java.lang.reflect.Method.invoke(Method.java:507)
EZSettings(14788): java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
EZSettings(14788): java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
EZSettings(14788): java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
EZSettings(14788): java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
EZSettings(14788): com.ezstatechanger.ProfileEdit.saveState(ProfileEdit.java:114)
EZSettings(14788): com.ezstatechanger.ProfileEdit.access$0(ProfileEdit.java:80)
EZSettings(14788): com.ezstatechanger.ProfileEdit$1.onClick(ProfileEdit.java:72)
EZSettings(14788): android.view.View.performClick(View.java:2538)
EZSettings(14788): android.view.View$PerformClick.run(View.java:9152)
EZSettings(14788): android.os.Handler.handleCallback(Handler.java:587)
EZSettings(14788): android.os.Handler.dispatchMessage(Handler.java:92)
EZSettings(14788): android.os.Looper.loop(Looper.java:123)
EZSettings(14788): android.app.ActivityThread.main(ActivityThread.java:3691)
EZSettings(14788): java.lang.reflect.Method.invokeNative(Native Method)
EZSettings(14788): java.lang.reflect.Method.invoke(Method.java:507)
EZSettings(14788): com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
EZSettings(14788): com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
EZSettings(14788): dalvik.system.NativeStart.main(Native Method)
BenMorel
  • 34,448
  • 50
  • 182
  • 322
William Stewart
  • 841
  • 1
  • 14
  • 27

2 Answers2

2

All your objects and all their fields need to be serializable - otherwise they can not be serialized. Another source of IO exception would be lack of permission to write on SD card. ( does somebody except your application needs this data? if not, it belongs into provate area.)

Serializing config data is convenient, but may be bad idea - if your object signature changes, data will be unreadable. Better solution would be to marshall objects into JSON and save this file ( Shameless self advertising on: https://github.com/ko5tik/jsonserializer )

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • My Profile class is Serializable, and ArrayList too, do the attributes within Profile class also need to be Serializable? I have the permission to write to external storage, without this it threw a FileNotFound exception rather than IO. With regards to marshall objects into JSON, I had a look at the code and it kind of made sense. To write my ArrayList would I used writer.beginArray(); then a for loop to write.value() all of the Profiles, then writer.endArray()? – William Stewart Dec 06 '11 at 13:57
  • All the fields need to be serializable to. Unless they are merked transient. Marshalling to JSON Array is even easier that that if you take my databinding: JSONMarshaller.marshallArray(writer, arrayOfStuffYouLikeToMarshall); See test cases in project – Konstantin Pribluda Dec 06 '11 at 14:08
  • I see, it looks like JSON is the way to go then, how do I go about initialising the JsonWriter? – William Stewart Dec 06 '11 at 14:27
  • You do not initialize it. This is static method. Just stuff it a supply it a writer and object / array. You will need GSON - there is stripped down version with just parser / emitter without databinding – Konstantin Pribluda Dec 06 '11 at 14:48
  • I found GSON stream package only and I added it to external libraries. When I do JsonWriter writer; then JSONMarshaller.writeArray(writer, profiles); it says that writer may not have been initialized. – William Stewart Dec 06 '11 at 14:53
  • You must instantiate it before using. – Konstantin Pribluda Dec 06 '11 at 14:57
  • How do I do that? Apologies if it seems a stupid question, I cant see where it is instantiated in your code. – William Stewart Dec 06 '11 at 15:06
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/5621/discussion-between-konstantin-pribluda-and-william-stewart) – Konstantin Pribluda Dec 06 '11 at 15:17
0

Although Konstantin Pribluda identified a better solution for what I needed to do, this question has been solved.

Turned out I stupidly overlooked the fact that my Event and State classes didn't implement Serializable. Any fields within a Serializable class must also be Serializable, otherwise the IO Exception is thrown.

William Stewart
  • 841
  • 1
  • 14
  • 27