Page 1 of 1

Serialization in Android

#1 painkiller102  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 16
  • View blog
  • Posts: 281
  • Joined: 27-February 08

Posted 25 September 2011 - 12:58 PM

Welcome to Basic Android Serialization!

Serialization is a very important topic for many different reasons. Serializing a class file provides a fast and efficeint way to store information produced by your application! In this tutorial i will be discussing the basics and essentuals of serializing class files using the Android api!


What is serialization?

Serialization is essentually taking a screenshot of a class file and its contents. For example, lets say you have the following class:


public class AddressBook
{
	private String name="Billy bob";
	private String number="000-000-0000";
	private String address="some street, in some city";
}



Sense it is an address book, you will want to save this information somewhere on the phone. Your options are to output a text file with all of the information (which can get complicated with a more advanced address book, or you can choose to serialize the class file (which is very simple). If you choose to serialize it, once you 'read' the serialized file back in, you will have the exact same class and variables listed above!


The Basics of Serialization

Serialization is a very simple process that can be used in most cases. First you need to start off with a class file. I will be using the address book example listed above, except i am going to expand it a bit to make it more practical:


public class AddressBook
{
	private String name="";
	private String number="";
	private String address="";

	public void setName(String name)
	{
		this.name = name;
	}
	
	public void setNumber(String number)
	{
		this.number = number;
	}

	public void setAddress(String address)
	{
		this.address = address;
	}
}



Ok, now that you have a class the next step is to make it serializable! Making a class serializable is super simple, all you have to do is implement serializable! In the above example, you would change:


public class AddressBook



to


public class AddressBook implements Serializable



Then add a unique serialVersionUID to the class like so:


private static final long serialVersionUID = 4654897646;



The final result will look like this:


public class AddressBook implements Serializable //Added implements Serializable
{
	private String name="";
	private String number="";
	private String address=""; 
	private static final long serialVersionUID = 4654897646; //Added serialVersionUID variable (can be either an int or a long, whichever you prefer!)

	public void setName(String name)
	{
		this.name = name;
	}
	
	public void setNumber(String number)
	{
		this.number = number;
	}

	public void setAddress(String address)
	{
		this.address = address;
	}
}



And that is all you have to do to the class file! You may be wondering what the serailVersionUID value is for, and that is a good question. When we serialize a file, we add that unique ID to it so that we know we are loading in the right version of the class file agian. If you serialize a file, and then change the class code, the two files will no longer be capatable (more of this process will be explained later). With a serialVersionUID value, we are able to determine if the serialized class file matches the current version of the class file, which will avoid error and complications later on! So for now just view it as a safety net, and we shall move on!


Exporting a Serialized class file

Now its time to save our serialized class file! When writing to a text file, you would do something like this:


BufferedWriter out = new BufferedWriter(new FileWriter("file.txt"));
out.write("whatever");
out.flush();
out.close();



Exporting a serialized file is very similar to the above code, the only difference is that you will be using an 'ObjectOutputStream' instead of a 'BufferedWriter'. Now its time to write your first Serialzied class writer! First start off by initializing the class file that you want to serialize. I will be using the same address book code that i wrote above!


public class AddressBookActivity extends Activity 
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        AddressBook addressBook = new AddressBook();
        addressBook.setName("John Snuffy");
        addressBook.setAddress("Some adress like snuffy lane");
        addressBook.setNumber("564-676-8339"); // get it... john snuffy!
    }
}



The next step is to create our ObjectOutputStream, and write the class file (as an object) to the destination file (dont worry if this sounds a bit confusing, it will become crystal clear below!)


public class AddressBookActivity extends Activity 
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        AddressBook addressBook = new AddressBook();
        addressBook.setName("John Snuffy");
        addressBook.setAddress("Some adress like snuffy lane");
        addressBook.setNumber("564-676-8339"); // get it... john snuffy!
        
        try
        {
        	ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("save.bin"))); //Select where you wish to save the file...
        	oos.writeObject(addressBook); // write the class as an 'object'
        	oos.flush(); // flush the stream to insure all of the information was written to 'save.bin'
        	oos.close();// close the stream
        }
        catch(Exception ex)
        {
		Log.v("Address Book",ex.getMessage());
        	ex.printStackTrace();
        }
    }
}



Thats it! You have just successfully wrote a serialized class file to 'save.bin'! The next step is reading in serialized files (which is just as simple as writing them!


Importing a Serialized class file

Now that you have saved a serialized class file, you are now wanting to load one in! This process is almost identical to writing with an ObjectOutputStream, except this time we will be reading using an ObjectInputStream. Below is an example of how to load in a serialized class file:


public Object loadClassFile(File f)
{
    try
    {
    	ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
    	Object o = ois.readObject();
    	return o;
    }
    catch(Exception ex)
    {
	Log.v("Address Book",ex.getMessage());
    	ex.printStackTrace();
    }
    return null;
}



Now as you can see above, we have created a method that returns a read-in object. This object is the serialized class file, and we will need to now cast that object back into the proper form (whatever class you used to serialize it, is the same class you now need to cast the object as).


public class AddressBookActivity extends Activity 
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        AddressBook addressBook = (AddressBook)loadClassFile(new File("save.bin"));
    }
}



That is all there is to serialization! You must keep in mind the rules for serialization as list below:


Rules of Serialization

  • Always use variables that can actually be serialized
  • Never change the class files source after you serialize a class file from it
  • Do not use super large int[] arrays (bug described below)


Looking at the rules, one of the most important things is to not change the class file code after the class file has been serialized (as it will NOT load back in) For Example, lets say i serialized the AddressBook.class as listed above, and then i went and updated the AddressBook.class as so:


public class AddressBook implements Serializable
{
    private String name="";
    private String number="";
    private String address="";
    private static final long serialVersionUID = 4654897646;

    public void setName(String name)
    {
    	this.name = name;
    }
    
    public void setNumber(String number)
    {
    	this.number = number;
    }

    public void setAddress(String address)
    {
    	this.address = address;
    }
    
    public String getName()
    {
    	return name;
    }
    	
    public String getNumber()
    {
    	return number;
    }
    	
    public String getAddress()
    {
    	return address;
    }
}



Now as you can see, i added 3 more methods to return all of the information; however sense i have changed the source code of 'AddressBook.class' the old serialized file is not outdated. If you try to load in an outdated Serialized class file, you will get an exception


Reading Serialized files from you RAW folder

The next thing i want to show you is how to load in Serialized class files from your Resources. Lets say you have pre-made settings that you have saved in serialized classes. Once you have done that, you now need to add those files into your android project. Navigate to your project folder, lets say C:/Address Book/ in my case. Now go into res/ and you should see stuff like values, layouts, and drawble folders. Create a new Folder called 'raw'. Next move your save.bin (or whatever you called it) into the raw folder that you just created in 'C:/Project/res/'.


The next step is to load the file using android source code! Go back to your project, and load the resouce into an 'InputStream' like so:


public class AddressBookActivity extends Activity 
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        try
        {
        	InputStream is = getResources().openRawResource(R.raw.save);
        }
        catch(Exception ex)
        {
		Log.v("Address Book",ex.getMessage());
        	ex.printStackTrace();
        }
    }
}



Now we have to use that inputstream and put it into an 'ObjectInputStream'. Then all the rest is the same as above, you will cast the object into the class that it was serialized off of and you will be all set! Here is an example of that:


public class AddressBookActivity extends Activity 
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        try
        {
        	InputStream is = getResources().openRawResource(R.raw.save);
        	ObjectInputStream ois = new ObjectInputStream(is);
        	
        	AddressBook addressBook = (AddressBook)ois.readObject();
        	
        	Log.v("Address Book",addressBook.name + " | " + addressBook.address + " | " + addressBook.number);
        }
        catch(Exception ex)
        {
		Log.v("Address Book",ex.getMessage());
        	ex.printStackTrace();
        }
    }

    public class AddressBook implements Serializable
    {
    	private String name="";
    	private String number="";
    	private String address="";
        private static final long serialVersionUID = 4654897646;

    	public void setName(String name)
    	{
    		this.name = name;
    	}
    	
    	public void setNumber(String number)
    	{
    		this.number = number;
    	}

    	public void setAddress(String address)
    	{
    		this.address = address;
    	}
    	
    	public String getName()
    	{
    		return name;
    	}
    	
    	public String getNumber()
    	{
    		return number;
    	}
    	
    	public String getAddress()
    	{
    		return address;
    	}
    }
}



The Transient Keyword

So far you have learned what serialization is, and how to use it; however there is one more thing you can add to your serialized file which is transient variables. Serializtion requires steps both by the programmer and by the language. When we 'Serialize' a file, what actually happens is all of the variables are changed back down to the basic persistent form. So in other words, the variables of your class file will be converted into another basic level format. In some cases you may not want this to occure, and there is a way to prevent this conversion from happening! That is where transient comes into play. Lets use the AddressBook.class one last time:


public class AddressBook implements Serializable
{
    private transient String name="";    //Made name a transient variable
    private transient String number="";  //Made number a transient variable
    private transient String address=""; //Made address a transient variable
    private static final long serialVersionUID = 4654897646;
}



As you can see, i added the word 'transient' before each variable identifier. Now those variables will not be converted to persistent form.


Serialization Warnings

For the most part, i have never come across many issues with serializing class files. The main rule of thumb is to make sure that all the variables within the class are actually serializable (look at the android documents and they will tell you wether or not something is serializable). one main thing i have found with android serialization is a bug with large integer arrays. If you have an integer array that contains information above 1MB or so (I am not sure of the exact number) your application may not be able to load that class file back in (you will get an IO error of some kind). I discovered this bug recently and found that the best solution is to store big amounts of information in byte arrays instead of int arrays! If you have an integer array that only has like less than 100 or some elements then dont worry about it, it seems to be only for biger integer arrays (for example i stored RGB values from an image in it one time and it would not load back in). Other than that, serialization is always a good practice to use for all of your saveing needs!


Conclusion

Thats it for Serialization! It is a pretty simple process that can really help you out along the road on many programs and apps that you may create! Using serialized class files will help you maintain better organization over your programs and they make very efficeint save files for games and other applications! I hope you enjoyed this tutorial and that everything comes across crystal clear! Thanks for reading!


Is This A Good Question/Topic? 3
  • +

Replies To: Serialization in Android

#2 slehmann101  Icon User is offline

  • D.I.C Head

Reputation: 21
  • View blog
  • Posts: 146
  • Joined: 30-November 11

Posted 05 March 2012 - 05:14 PM

In these lines
ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream(new File("save.bin")));

i get the following error
The constructor ObjectOutputStream(FileOutputStream) is undefined
(In the third box of Exporting a Serialized class file)
Was This Post Helpful? 0
  • +
  • -

#3 Eowyn27  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 149
  • Joined: 17-October 11

Posted 19 September 2014 - 11:18 AM

Where should I store the file that I want to read in to deserialize the file?

Should it be stored in an SD card... what folder? What is the best practice?

Thanks.
Was This Post Helpful? 0
  • +
  • -

#4 futureideasnsol  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 28-August 14

Posted 24 September 2014 - 04:00 AM

I tried this android serialization & It worked for me.. Thanks for sharing
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1