1

I'm using the following code to save and retrieve objects to and from the Androids internal memory. I have tested it with a string object with success. When I try to save a Bitmap I get a IOException. (I found out that I have to call the compress method) So I notice that I can save some objects, what are the restrictions to saving objects?

When I save a object, does it only save the fields? Can I save objects that contains other objects? Please clear me up.

Code:

    public Object readObjectFromMemory(String filename) {
        Object defautObject = null;
        FileInputStream fis;
        try {
            fis = game.openFileInput(filename);
            ObjectInputStream is = new ObjectInputStream(fis);
            defautObject = is.readObject();
            is.close();
            this.gameEngineLog.d(classTAG, "Object successfully read: " + filename);
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "FileNotFoundException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (StreamCorruptedException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "StreamCorruptedException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (IOException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "IOException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (ClassNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "ClassNotFoundException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        }

        return defautObject;

    }

public void writeObjectToMemory(String filename, Object object) {
        FileOutputStream fos;
        try {
            fos = game.openFileOutput(filename, Context.MODE_PRIVATE);
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(object);
            os.close();
            this.gameEngineLog.d(classTAG, "Object successfully written: " + filename);
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename);

        } 
        catch (IOException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename);

        }

    }

Thanks in advance.

Luke Taylor
  • 9,481
  • 13
  • 41
  • 73

3 Answers3

1

The restriction is that all objects have to be serializable (implement the interface Serializable). If an object data member of an object is not serializable, it has to be marked as transient:

private transient SomeClass notSerializable;

EDIT about serializing non-serializable members

It depends on what you are trying to serialize that is not serializable. Since this is a question tagged with Android it could be a Context object for example.

Contexts are not serializable for a good reason, they are tied to a life cycle, either of the application or of an Activity. Its state is volatile and even if you could serialize and deserialize it later, its internal state wouldn't make sense, since a new Context has been established, a new thread or even a different process may be running by now.

In case of data members like Contexts you need to declare them as transient and re-assign the fresh and valid current Context to the deserialized object.

If you are trying to serialize different kinds of objects that on the one hand just represent data like a bunch of strings and / or numbers, but on the other hand are not serializable, you have two options:

  • If these are your classes, then just add the Serializable interface to them
  • Or you could customize the serialization process in your class that has non-serializable data members

Customization can be done by implementing the methods

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

These methods are invoked on serialization / deserialization of the class. The trick is to take the data / state of a non-serializable object and pack that data into a serializable object instead. You could for example use any Collection object like an ArrayList for sequentially storing the raw data.

Let's assume you want to serialize a Location object (for geo location coordinates) and let's also assume that object is not serializable. But you know that it consists of three values which can be serialized:

  • double longitude
  • double latitude
  • double altitude
  • (and others like provider, speed, time...)

You could store these three values in an ArrayList or you could create your own custom, serializable class which stores these values for serialization purposes. Put the ArrayList or your serializable intermediate object into the ObjectOutputStream of your custom writeObject method.

In readObject you need to reverse these steps and reconstruct your data member that is not serializable based on the raw data you serialized.

I also suggest reading Sun's documentation about serialization

tiguchi
  • 5,392
  • 1
  • 33
  • 39
0

Yes, you can save all types of data in an object, you just need to make sure that you are defining all the variables inside your object:

public class YourObject{
int yourInteger;
String yourString;
Bitmap yourBitmap;
float yourFloat;
...
}

You also need to make sure that you are setting the fields off those objects using a set method:

public class YourObject{
int yourInteger;
String yourString;
Bitmap yourBitmap;
float yourFloat;
...
//sets the value of yourInt
public void setYourInteger(int yourInt){
 this.yourInt = yourInt;

}

}

If you don't explicitly set the fields, you won't be able to save them.

BlackHatSamurai
  • 23,275
  • 22
  • 95
  • 156
  • So I can save a object that contains a bitmap object, yet I can't save a bitmap object by itself (with the code I've provided above)? – Luke Taylor Jul 10 '12 at 15:34
  • Can you provide the code for your object class, as well as the code you use to invoke the `writeObject` method? – BlackHatSamurai Jul 10 '12 at 16:22
0

From the Oracle's Javadoc:

An ObjectOutputStream writes both primitive data types and graphs of Java objects to an underlying OutputStream. The objects and other data can then be read (reconstituted) using an ObjectInputStream. Persistent storage of objects can be accomplished by using a file for the stream. If the stream is a network socket stream, the objects can be reconstituted on another host or in another process.

Only objects that support the java.io.Serializable or java.io.Externalizable interface can be serialized to an output streams. The class of each serializable object is encoded including the class name and signature of the class, the values of the object's non-static and non-transient fields and arrays, and including any other objects referenced by the object (except those that do not implement the java.io.Serializable interface themselves). Multiple references to the same object are encoded using a referece sharing mechanism, so that a graph of the object can be restored appropriately.

The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also.

Jonathan Naguin
  • 14,526
  • 6
  • 46
  • 75