Sharing Data Between Applications

This is a topic that comes up from time to time and is applicable to both Flash and Flex as the solution lies within the Flash Player.

Let’s say you have a customer’s profile you’d like to store on their local machine. Perhaps your web site has multiple HTML pages, some with Flash or Flex applications and you would like those applications to use the same customer profile information.

Providing this is not a lot of information, the SharedObject is the best way to go. SharedObject is a class for, well, sharing data. A small data file is stored on the local computer and requires the end-user’s consent (which is granted by default). The end-user also has control over how much space to allocate for ALL SharedObjects – not just for your applications. Bear these restrictions in mind when writing your applications – you may need to query the user for the information if it cannot be stored and retrieved.

Download Sample Flex Application


Using SharedObject is pretty easy. Here’s how to store a String and a Number:

var so:SharedObject = SharedObject.getLocal( "MyAppData" );
so.data.customerName = customerData.name;
so.data.serialNumber = customerData.serialNumber;
so.flush();

And that’s it. A local SharedObject is created with the name “MyAppData”. The SharedObject has a public member, data. Noticed that I didn’t set data directly, but set properties on data itself. That is very important – you cannot change the value of data, you must add properties to it – otherwise your information will not be saved.

Reading the information is just as easy:

var so:SharedObject = SharedObject.getLocal( "MyAppData" );
if( so.data.customerName ) customerData.name = so.data.customerName;
if( so.data.serialNumber ) customerData.serialNumber = so.data.serialNumber;

Notice that I tested each property to see if it exists before using it.

A common question is if it is possible to save ActionScript class instances. Consider this example: you have a Person class which has members like name and age. The class also has a member address which is typed to be the ActionScript class Address. What you’d like to do is this:

var currentPerson:Person;
...
so.data.person = currentPerson;

This generally works, but what is saved to the SharedObject is NOT an instance of the Person class. Rather, so.data.person is a plain ActionScript Object – all information with respect to the class has been removed.

When you want to read this information, you need to assign each part. For example:

currentPerson.name = so.data.person.name;
currentPerson.age = so.data.person.age;
currentPerson.address.street = so.data.person.address.street;
...

It is also not guaranteed that your class will be successfully (or completely) turned into nested ActionScript Objects.

A better way to serialize your class is by implementing a serialization technique. One way is to use flash.utils.IExternalizable; you could also use XML. You don’t really need to implement this interface as SharedObject doesn’t know anything about IExternalizable. It is just good practice to do so.

Implementing IExternalizable requires your classes to have two functions: writeExternal and readExternal. Basically you convert your class to a series of bytes which can be stored in the SharedObject and read back later. For example:

class Person implements IExternalizable
{
    public function writeExternal( output:IDataOutput ) : void
    {
      output.writeUTF(name);
      output.writeInt(age);
      address.writeExternal(output);
    }


    public function readExternal( input:IDataInput ) : void
    {
      name = input.readUTF();
      age = input.readInt();
      address.readExternal(input);
    }
}

The Address class would do the same. The IDataOutput and IDataInput interfaces are implemented by several classes. You can use ByteArray for use with SharedObject. Here’s how to save your Person class instance:

var bytes:ByteArray = new ByteArray();
currentPerson.writeExternal(bytes);
so.data.person = bytes;
so.flush();

Reading them back and creating your Person record is also simple:

if( so.data.person ) {
    currentPerson.readExternal( so.data.person as ByteArray );
}

If you’d rather use XML than ByteArray, simply write functions to create the XML (eg, toXML) and parse XML (eg, fromXML) in place of the writeExternal and readExternal functions, respectively.

For a simple class this might not be worth the effort. But if you have a complex class it would certainly be better to encapsulate the serialization within the class and store the serialized data in the SharedObject.