Archive for the ‘AIR’ Category

SharedObject a.k.a. Flash Cookies

Thursday, August 28th, 2008

Per the ActionScript API:

The SharedObject class is used to read and store limited amounts of data on a user’s computer or on a server. Shared objects offer real-time data sharing between multiple client SWF files and objects that are persistent on the local computer or remote server. Local shared objects are similar to browser cookies and remote shared objects are similar to real-time data transfer devices. To use remote shared objects, you need Adobe Flash Media Server.

I find this to be very useful and so I have put together a simple class that will allow you to save, retrieve, and clear values from your SharedObject.

package {
    import flash.events.NetStatusEvent;
    import flash.net.SharedObject;
    import flash.net.SharedObjectFlushStatus;

    public class LocalSharedObject {

        // private properties
        private var _sharedObject:SharedObject;

        /*********************************************
         *
         *         PUBLIC METHODS
         *
         * *******************************************/     

        public function LocalSharedObject(name:String,
                                          localPath:String = null,
                                          secure:Boolean = false) {

            _sharedObject = SharedObject.getLocal(name, localPath, secure);

        }

        public function setValue( name:String, value:Boolean ):void {
            _sharedObject.data[name] = value;

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

        public function getValue( name:String ):Boolean {
            return _sharedObject.data[name];
        }

        public function clearValue( name:String ):void {
            trace("Cleared saved value for "+name+");
            trace("Reload SWF and the value should be \"undefined\".\n\n");
            delete _sharedObject.data[name];
        }

        public function clearAllValues():void {
            trace("Cleared all saved value);
            trace("Reload SWF and the value should be \"undefined\".\n\n");
            _sharedObject.clear();
        }

        /*********************************************
         *
         *         PRIVATE METHODS
         *
         * *******************************************/

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

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

    }
}

Now you’re pretty much done.  From another actionscript class, flex component, or whatever, just add something like the following:

import LocalSharedObject;

private var _myApplicationName:String = "My Application Name";
private var _myLocalPath:String = "/";
private var _lso:LocalSharedObject = new LocalSharedObject(_myApplicationName, _myLocalPath);

private function myFunction():void {
    trace(_lso.getValue( "newLSOname" ));  // returns false if value has not been set
    _lso.setValue( "newLSOname", true );  // sets value to true
    trace(_lso.getValue( "newLSOname" ));  // returns true
}

Note: Setting myLocalPath equal to “/” (slash) makes the shared object available to all SWF files in the domain, but increases the likelihood of name conflicts with other shared objects in the domain.

I’ll post a working example to play with soon.

Passing data from the browser to an AIR app

Thursday, August 28th, 2008

Passing data from the browser to an AIR app is actually pretty easy.  In order to do this you must setup a LocalConnection in the swf that plays in your browser and in the AIR app.

browser swf:

var sendingLC:LocalConnection = new LocalConnection();
sendingLC.addEventListener( StatusEvent.STATUS, onStatus );
sendingLC.send( "_localConnection", "receivingMethod", "param" );

private function onStatus( event:StatusEvent ):void {
    switch (event.level) {
        case "status":
            trace( "LocalConnection.send() succeeded" );
            break;
        case "error":
            trace( "LocalConnection.send() failed" );
            break;
    }
}

AIR app:

var receivingLC:LocalConnection = new LocalConnection();
receivingLC.client = this;
try {
    receivingLC.allowDomain('*');
    receivingLC.connect("_localConnection");
} catch (error:ArgumentError) {
    trace("Can't connect...the connection name is already being used by another SWF");
}

public function receivingMethod( param:String ):void {
    trace(param);
}

Since the browser swf resides on a server somewhere and the AIR app lives on your desktop, the connection name “_localConnection” is proceeded with underscore (_), in both the connect() and send() calls to avoid specifying the domain name in the send() method.  The allowDomain(*) method will allow communication between to the AIR from any domain.  If you only want to allow communication from a specific domain you just pass the domains from which you want to allow LocalConnection calls instead of the astrix.