Flash MX
introduces the concept of a shared-object. Shared-objects are sometimes referred as
Flash cookies in the Flash/web development community. Shared-objects enable Flash movies to save data which persists across
multiple sessions. (In this context, a session
means an instance of entering and leaving a site.) There are many
possible uses of shared-objects. For example to keep track of a shopping
cart; to store user's preferences; or to check whether a user is a new
visitor.
Note: This discussion is limited to local shared-objects. Flash MX also support remote
shared-object; which allows
you to save to and retrieve data from a Flash COM (RMTP)
server.
A local shared-object is functionally similar to a browser cookie. The differences
are:
Browser cookies are handled by the browser; shared-objects are handled by the
Flash player.
Browser cookies are stored in a relatively recognizable location in the user hard
drive. Most user and web developers are familiar on how to delete browser cookies; and there are
many utilities that do that. While local shared-objects are also
stored in the user's hard drive; the folder location is not obvious;
so it's not as easy for user to delete. Whether this is good or bad
depends on your perspective. Most likely, web developers like it, while users hates it (although most users nowadays don't seem to mind cookies that much).
Local shared-object is a good alternative to browser cookies. A
local shared-object
is easier and
more straightforward to use and Flash programmer will find it to be a good, if not interesting, alternative to regular cookies. Yet, there are things that you simply need to do with browser cookie. This is
especially true unless your site is all Flash. To see how Flash
can use browser cookies, see this tutorial.
There is currently no mechanism to force a shared-object to "expire". Browser cookies
have an expiration mechanism built
in.
Browser cookies are stored
as text and are human readable. Shared-object are stored as binary
data (although variable names are still human readable);.
Some characteristics of a local shared-object:
A local shared-object can only be read by movies from the same domain as the
Flash movie that originates the shared object. This means that a Flash movie from mysite.com, cannot read a
local shared-object from yoursite.com, and vice verse.
Currently, using a local shared-object is the only way to instruct a Flash movie write
data to the user's hard drive directly from within the movie.
A local shared-object is stored on the user's machine; so they can be deleted by the
user either purposefully or inadvertently. If for instance, the user
reformats the hard drive where the local shared-object is stored, the
local shared-object
will be gone.
On Windows, local shared-objects are stored in Documents and Settings\userName\Application Data\Macromedia\Flash
Player\#SharedObjects.
According to the Macromedia docs, local shared-objects has a file extension of .SO,
but they seem to be saved with .SOL extension on my Windows XP.
User can disable local shared-object by disallowing a particular site to write to the
user's hard drive. This can be done in the Macromedia player Setting
window:
Only Flash Player 6 and newer support shared-objects. If you must support older versions, consider using
browser cookies.
You are not limited to one shared-object per Flash movie.
PROGRAMMING EXAMPLES
If these examples does not work, make sure that you have Flash Player 6 or
newer; and that you have not disallowed Flash Player to store local shared
objects from this site.
Example 1
This movie creates a local shared-object. Type something then press Write
to write the object to the local disk.
Example 2 This movie reads the shared-object written by the movie above.
Example 3
This is a counter. A local shared-object is
used to store the counter value. Press the browser's Reload button
to see
the value incremented.
Side note: If you're runing WIndows, you can check the Documents and Settings\userName\Application Data\Macromedia\Flash
Player\#SharedObjects and see if you can find the .SO* files from this
domain created by the movies above.
CREATING LOCAL SHARED-OBJECT
Create a local shared-object by using this static member function:
static function
SharedObject.getLocal(objectName:string [, objectPath:string]):SharedObject
objectName
This is the name of the shared-object. If a local shared-object with the
specified objectName does not already exists, a new one will be created.
There can only be one shared-object with the same name and path.
Example:
// Create a shared-object named "userData"
mySharedObject=SharedObject.getLocal("userData");
objectPath
This is an optional parameter. The default value is the full path of the swf
(including the swf filename). This parameter is useful if you want
to have several local shared-objects with a same name. You can differentiate the
objects by using the path. Note that this may only be
set to the actual path (or part of the path) of where the swf file is stored.
Eq: If you have the swf stored in "/pathA/",
you cannot pass "/pathB/"; but you can pass "/"
or "/pathA". More on this parameter can be read on
the Advanced Subject section later.
WRITING SHARED-OBJECT
A shared-object has a class member named data, which is an
object.
To write to a shared-object; add members to data and assign the
value. The syntax is like this:
mySharedObject.data.variableName=value
For example, to store a name and a score:
// Create a shared-object named "userData"
mySharedObject=SharedObject.getLocal("userData");
// Store the name
mySharedObject.data.name="Jim";
// Store the score
mySharedObject.data.score=200;
mySharedObject.flush();
You can add any valid object as the data value (numbers, strings,
objects), even a movie clip instance (but why would you?).
The shared-object will be written when the user closes the Flash
movie. (Closing the movie could mean leaving the page, closing
the browser, or reloading the page.)
You can also force the data to be written immediately by issuing a flush()
command:
function flush([minimumDiskSpace:Number):Object
So, the code above could be written like this:
// Create a shared-object named "userData"
mySharedObject=SharedObject.getLocal("userData");
// Store the name
mySharedObject.data.name="Jim";
// Store the score
mySharedObject.data.score=200;
mySharedObject.flush();
There are 3 possible return values from the flush() command: true,
false, or the string "pending". Here are
what they mean: true is returned if the data is written successfully.
"pending" is returned if the user has not allowed
sufficient disk space in the Flash Player setting. In this
case, the setting dialog box will be displayed asking the user whether
to allow more space or not. The dialog currently looks like this:
false is returned if the user has checked the Never box
in the Player Settings (shown below).
In this case, the shared-object will simply not be written, and there
will be no warning to the user. You can however, warn the user
manually; or force the Player Settings dialog to be shown (see
the Advanced Subjects section below on how to do this).
READING SHARED-OBJECT
It's also very simple to read from a shared-object; just assign the value of the data member to a variable.
variable=mySharedObject.data.variableName
For example, to read the name and score from the above example:
// Create/read a shared-object named "userData"
mySharedObject=SharedObject.getLocal("userData");
// Read user name
userName = mySharedObject.data.name;
// Read more data
userScore = mySharedObject.data.score;
You should always check if the data exists before reading them.
You can check whether this is the case by testing a variable against null.
If the shared-object does not exists, then a new one will
be created with empty data. Here's an example of checking
whether the object already exists on the user machine or not.
// Creates/read a shared-object named "userData"
mySharedObject=SharedObject.getLocal("userData");
// If name variable is not available, we assume that this is a new user
if (mySharedObject.data.name==null)
{
// Object doesn't exists, do something, display registration form, etc...
}
else
{
// Read user name
userName = mySharedObject.data.name;
// Read more data
score = mySharedObject.data.score;
}
DELETING SHARED-OBJECT
Unlike browser cookies, there's no way to tell a local shared-object to expire. You can however; clear it
manually. In Flash Player 7, you can use:
function clear()
For example:
mySharedObject.clear();
Otherwise, you can also traverse the data and
delete all the contents
for (var myVariable in mySharedObject.data)
{
delete mySharedObject.data[myVariable];
}
ADVANCED SUBJECTS
Effects
of specifying the object path when creating a shared object:
You create a local shared-object by using this static member function:
static function
SharedObject.getLocal(objectName:string [, objectPath:string]):SharedObject
The objectPath is an optional parameter. The default value is the full path of the swf
(including the swf filename). This parameter is useful if you want
to have several local shared-objects with a same name. For example... if I have a swf file is at
http://www.permadi.com/pathA/pathA1/a.swf
then these are valid objectPath values:
SharedObject.getLocal("userData", "/pathA/Patha1/a.swf");
(This last example might work on some servers, but path
names are case sensitive on most UNIX servers so you should always use the
proper letter cases.)
A swf can only access local shared-objects along its path. Some
examples:
If I have a swf at /pathA/pathA1/a.swf, which creates this shared-object:
Then this object is accessible by any swfs in my site.
If I have a swf at /pathA/pathA1/a.swf, which creates this shared-object:
mySharedObject=SharedObject.getLocal("userData");
Then this shared-object is accessible only by /pathA/pathA1/a.swf.
Checking
the size of a shared-object:
function getSize():Number
This function returns a Number, which is the amount of disk space
(in bytes) used by the shared-object.
Checking
whether a shared-object is written successfully:
function onStatus=function(infoObject:Object):void
This callback function returns an object.code with values of SharedObject.Flush.Failed
or SharedObject.Flush.Success. The callback is only
performed if a flush() command has failed
(see Writing Shared Object section above for information on how a
flush() command might fail). When a flush()
command failed, you can warn the user.
For example:
// Create a shared-object named "userData"
mySharedObject=SharedObject.getLocal("userData");
mySharedObject.onStatus=function(infoObject:Object)
{
if (infoObject.code==SharedObject.Flush.Failed)
{
// FAILED, do something
}
}
// Store the name
mySharedObject.data.name="Jim";
// Store the score
mySharedObject.data.score=200;
flushStatus=mySharedObject.flush();
if (slushStatus!=true)
{
// do something
}
Printing
all the variables on a shared-object:
Traverse
the data field like this:
function printSharedObject(mySharedObject)
{
for (var variableNames in mySharedObject.data)
{
trace("Variable name="+variableNames +
" value="+mySharedObject.data[variableNames]);
}
}
Prompting
user to allow saving of shared-objects or to ask for more space:
This is
useful if your swf failed to write a shared object and you want to warn
the user. You can detect such failures by using the flush() command
(see Writing Shared Object section above).
System.showSettings(1); // 1 refers to the index of the second tab (ie:
// the Local Storage tab like shown below)
Important:
the dimension of the swf must be equal or larger that the dimension of
the Flash Player Setting dialog (currently, it's about 215x135 pixels-like shown
above). If the movie dimension is smaller than that, the dialog will refuse
to show up. It is rather silly, but now you know why I have
these oversized example movies.
Here's an example. The Settings button will bring up the
Flash Player Settings dialog. The Write button calls flush()
on the shared object. You can try altering the settings to see
what happens. The settings dialog will be
shown also if flush() failed. The Clear Object
button clears the object (as described in Deleting Shared Object
section above).
You can download the FLA
here. The code is in the top-most layer of the first frame of the main
timeline.