HOWTO: SharedObjects for Local Storage AS3

Using SharedObjects in Flash is very simple. Flash has SharedObjects that have been in the player since Flash6 when the introduction of Flash Communication Server which is now Flash Media Server which is releasing version 3 soon (also remote SharedObjects in Red5 is an open source RTMP media server that is based on Flash Media Server). So we can thank this release for SharedObjects, Camera objects, Audio, lots of the NetConnections, protocol enhancements and many other things. However to keep the tips simple we will just touch on the local usage and post a series of posts on these objects.

SharedObjects locally and remote have changed the way offline is thought about and are the backbone of many offline systems and prototypes. They have been influential in moving storage locally to remote in a lightweight AMF0 or AMF3 format.

SharedObject is in the flash.net namespace in AS3.

Here we show how to use the local version of a SharedObject to store data in the most simple form.

import flash.net.SharedObject;
var so:SharedObject = SharedObject.getLocal("userData");
so.data.username= "user1377";
so.data.pwdhash= "[hash] or pwd";
so.flush(); // writes changes to disk

You can see this is extremely simple to store data.Here we show how to use the local version of a SharedObject to retrieve data in the most simple form.

import flash.net.SharedObject;
var so:SharedObject = SharedObject.getLocal("userData");
var username:String = so.data.username;
var pwdhash:String = so.data.pwdhash;

That is it! In the most basic form SharedObjects are more simple than cookies and also are quite nice living outside the bounds of the cookies folder. If a user deletes all cookies it will not delete the SharedObjects. To delete SharedObjects you need to roght click on the Flash player, go to Settings and delete the objects there.You can store any type of data Flash supports from objects to numbers to strings in the SharedObject data.

import flash.net.SharedObject;
var so:SharedObject = SharedObject.getLocal("userData");
so.data.username= "user1377";
so.data.uid= new Number(1337);
var obj:Object = new Object();
obj.prop = "value";
so.data.userobj= obj;
so.flush(); // writes changes to disk

For large applications SharedObjects local are great because users can have their SharedObject space set to a high amount of space or unlmited for large offline type apps or more complex apps stored in a state object. It gets interesting when you pass this to the server in AMF or extremely compact AMF3 format to a remote stored object, via remoting, Shared Object events or any way you want to.We will be posting more on remote shared objects and some of the other tools such as Camera and Streams for AS3 over the coming weeks and deeper into the Sync Events for remote and local SOs.Sephiroth has a great Python tool to peer into the SOs on disk.

The first version of SharedObject Reader was written in python 2.2.
This new version is written in C# (C Sharp) as it’s now part of FlashDevelop editor.

Red5 also does this as well as many AMF kits.

Sync Events for SharedObject (as they change they launch a sync event)

Event object type: flash.events.SyncEvent
SyncEvent.type property = flash.events.SyncEvent.SYNC

Read more at adobe docs:

flash.net.SharedObject

Sample from AS3 docs showing usage

package {
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.NetStatusEvent;
    import flash.net.SharedObject;
    import flash.net.SharedObjectFlushStatus;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;

    public class SharedObjectExample extends Sprite {

        private var mySo:SharedObject;

        public function SharedObjectExample() {
            buildUI();
            saveBtn.addEventListener(MouseEvent.CLICK, saveValue);
            clearBtn.addEventListener(MouseEvent.CLICK, clearValue);

            mySo = SharedObject.getLocal("application-name");
            output.appendText("SharedObject loaded...\n");
            output.appendText("loaded value: " + mySo.data.savedValue + "\n\n");
        }

         private function saveValue(event:MouseEvent):void {
            output.appendText("saving value...\n");
            mySo.data.savedValue = input.text;

            var flushStatus:String = null;
            try {
                flushStatus = mySo.flush(10000);
            } catch (error:Error) {
                output.appendText("Error...Could not write SharedObject to disk\n");
            }
            if (flushStatus != null) {
                switch (flushStatus) {
                    case SharedObjectFlushStatus.PENDING:
                        output.appendText("Requesting permission to save object...\n");
                        mySo.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
                        break;
                    case SharedObjectFlushStatus.FLUSHED:
                        output.appendText("Value flushed to disk.\n");
                        break;
                }
            }
            output.appendText("\n");
        }

        private function clearValue(event:MouseEvent):void {
            output.appendText("Cleared saved value...Reload SWF and the value should be \"undefined\".\n\n");
            delete mySo.data.savedValue;
        }

        private function onFlushStatus(event:NetStatusEvent):void {
            output.appendText("User closed permission dialog...\n");
            switch (event.info.code) {
                case "SharedObject.Flush.Success":
                    output.appendText("User granted permission -- value saved.\n");
                    break;
                case "SharedObject.Flush.Failed":
                    output.appendText("User denied permission -- value not saved.\n");
                    break;
            }
            output.appendText("\n");

            mySo.removeEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
        }

        // UI elements
        private var inputLbl:TextField;
        private var input:TextField;
        private var output:TextField;
        private var saveBtn:Sprite;
        private var clearBtn:Sprite;

        private function buildUI():void {
            // input label
            inputLbl = new TextField();
            addChild(inputLbl);
            inputLbl.x = 10;
            inputLbl.y = 10;
            inputLbl.text = "Value to save:";

            // input TextField
            input = new TextField();
            addChild(input);
            input.x = 80;
            input.y = 10;
            input.width = 100;
            input.height = 20;
            input.border = true;
            input.background = true;
            input.type = TextFieldType.INPUT;

            // output TextField
            output = new TextField();
            addChild(output);
            output.x = 10;
            output.y = 35;
            output.width = 250;
            output.height = 250;
            output.multiline = true;
            output.wordWrap = true;
            output.border = true;
            output.background = true;

            // Save button
            saveBtn = new Sprite();
            addChild(saveBtn);
            saveBtn.x = 190;
            saveBtn.y = 10;
            saveBtn.useHandCursor = true;
            saveBtn.graphics.lineStyle(1);
            saveBtn.graphics.beginFill(0xcccccc);
            saveBtn.graphics.drawRoundRect(0, 0, 30, 20, 5, 5);
            var saveLbl:TextField = new TextField();
            saveBtn.addChild(saveLbl);
            saveLbl.text = "Save";
            saveLbl.selectable = false;

            // Clear button
            clearBtn = new Sprite();
            addChild(clearBtn);
            clearBtn.x = 230;
            clearBtn.y = 10;
            clearBtn.useHandCursor = true;
            clearBtn.graphics.lineStyle(1);
            clearBtn.graphics.beginFill(0xcccccc);
            clearBtn.graphics.drawRoundRect(0, 0, 30, 20, 5, 5);
            var clearLbl:TextField = new TextField();
            clearBtn.addChild(clearLbl);
            clearLbl.text = "Clear";
            clearLbl.selectable = false;
        }
    }
}
  • Tony

    Wow, I officially love you. This was SO easy to understand and helped me a lot. One question though, if I display the information displayed in a shared object, how can I get it to constantly update?
    example:

    —-
    Frame 1:
    textfield.text=save1.data.pass;
    Frame 2:
    gotoAndPlay(1);
    ——
    it just stays the same, even if the information changes.

    Anyways, thanks again. :)

  • http://drawk.com drawk

    Hey Tony,

    Make sure when you are changing the data to .flush() it. That is all I can think of without seeing the code where you set save1.data.pass. Also, maybe saving to a temporary variable can help you debug if it is actually being set or if the text field is acting strangely.

  • Agustin

    Thanks a lot!!! just what I needed, a simple, quick explanation, without the introduction about the history of cookies in the last score of years…
    Got it working right away.
    Thanks

  • Colton

    Hi! Thanks so much for this!
    How would I access these sharedObjects I define in the parent swf from a swf that is loaded in (child)???

    Ex:// On the main timeline of my parent swf movie I define so.data.color = “blue”;… Then a swf loads into my timeline and accesses that color sharedObject…???…

    Please help whenever you can. I am desperate. :-)
    Thanks!

  • Colton

    Any help? Anyone???

  • http://blog.tobyskinner.co.uk Toby Skinner

    colton, would you not just open a new instance of the SharedObject inside your child swf?

    parent
    var so:SharedObject = SharedObject.getLocal(“so”);
    so.data.x = y;
    so.flush();

    child
    var so:SharedObject = SharedObject.getLocal(“so”);
    trace(so.data.x);

    not tested.

  • http://www.litpres.com larry

    In a nutshell I’m adding duplicates of the same child when the user clicks on “addBtn”. How would I use SOs to save the children that have been added?

    Cheers

    My code:

    var container_mc:MovieClip;
    var juryMC:MovieClip;

    container_mc = new MovieClip();
    addChild(container_mc);

    addBtn.addEventListener(MouseEvent.CLICK, onAdd);
    function onAdd(evt:MouseEvent):void {
    juryMC = new jury();
    juryMC.x = Math.random() * stage.stageWidth;
    juryMC.y = Math.random() * stage.stageHeight;
    container_mc.addChild(juryMC);
    }