Objetos compartidos

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

Un objeto compartido, a menudo referido como “cookie de Flash”, es un archivo de datos que se puede crear en el equipo a partir de los sitios que se visitan. Los objetos compartidos se utilizan sobre todo para mejorar la navegación en web ya que, por ejemplo, permiten personalizar el aspecto de un sitio web que se visita con frecuencia.

Acerca de los objetos compartidos

Los objetos compartidos funcionan como las cookies del navegador. Puede utilizar la clase SharedObject para almacenar datos en el disco duro local del usuario y llamar a los datos durante la misma sesión o en una posterior. Las aplicaciones pueden acceder únicamente a sus propios datos SharedObject y solo si se están ejecutando en el mismo dominio. Los datos no se envían al servidor y no se puede acceder a ellos mediante otras aplicaciones que se ejecuten en otros dominios, pero sí pueden acceder a ellos las aplicaciones del mismo dominio.

Objetos compartidos comparados con cookies

Las cookies y los objetos compartidos son muy similares. La mayor parte de los programadores web están familiarizados con el modo de funcionamiento de las cookies, por lo que puede resultar útil compararlas con los objetos SharedObject locales.

Las cookies que se adhieren al estándar RFC 2109 suelen disponer de las siguientes propiedades:

  • Pueden caducar y a menudo lo hacen al final de una sesión y de forma predeterminada.

  • Pueden desactivarse mediante el cliente en función de los criterios específicos de un sitio.

  • Existe un límite de 300 cookies en total y 20 cookies como máximo por sitio.

  • Se suelen limitar a un tamaño de 4 KB cada una.

  • En ocasiones se consideran una amenaza para la seguridad y, como resultado, se deshabilitan en el cliente.

  • Se almacenan en una ubicación especificada por el navegador cliente.

  • Se transmiten del cliente al servidor mediante HTTP.

    Por el contrario, los objetos compartidos cuentan con las propiedades siguientes:

  • No caducan de forma predeterminada.

  • De forma predeterminada, se limitan a un tamaño de 100 KB cada uno.

  • Pueden almacenar tipos de datos sencillos (por ejemplo, String, Array y Date).

  • Se almacenan en una ubicación que especifica la aplicación (en el directorio de inicio del usuario).

  • Nunca se transmiten entre el cliente y el servidor.

Acerca de la clase SharedObject

Si utiliza la clase SharedObject , podrá crear y eliminar objetos compartidos, además de detectar el tamaño actual de un objeto SharedObject que esté utilizando.

Creación de un objeto compartido

Para crear un objeto SharedObject , utilice el método SharedObject.getLocal() , que tiene la siguiente sintaxis:

SharedObject.getLocal("objectName" [, pathname]): SharedObject

El siguiente ejemplo crea un objeto compartido denominado mySO:

public var mySO:SharedObject; 
mySO = SharedObject.getLocal("preferences");

Con ello se crea un archivo en equipo del cliente llamado preferences.sol.

El término local hace referencia a la ubicación del objeto compartido. En este caso, Adobe® Flash® Player almacena el archivo SharedObject localmente en el directorio de inicio del cliente.

Cuando se crea un objeto compartido, Flash Player crea un nuevo directorio para la aplicación y el dominio dentro de su entorno limitado. También crea un archivo *.sol que almacena los datos de SharedObject. La ubicación predeterminada de este archivo es un subdirectorio del directorio de inicio del usuario. La siguiente tabla muestra las ubicaciones predeterminadas de este directorio:

Sistema operativo

Ubicación

Windows 95/98/ME/2000/XP

c:/Documents and Settings/username/Application Data/Macromedia/Flash Player/#SharedObjects

Windows Vista/Windows 7

c:/Users/username/AppData/Roaming/Macromedia/Flash Player/#SharedObjects

Macintosh OS X

/Users/username/Library/Preferences/Macromedia/Flash Player/#SharedObjects/web_domain/path_to_application/application_name/object_name.sol

Linux/Unix

/home/username/.macromedia/Flash_Player/#SharedObjects/web_domain/path_to_application/application_name/object_name.sol

Bajo el directorio #SharedObjects existe un directorio nombrado al azar. Debajo hay un directorio que coincide con el nombre de host y, a continuación, la ruta a la aplicación y finalmente el archivo *.sol.

Por ejemplo, si solicita una aplicación denominada MyApp.swf en el host local, y en un subdirectorio llamado /sos, Flash Player almacena el archivo *.sol en la siguiente ubicación en Windows XP:

c:/Documents and Settings/fred/Application Data/Macromedia/Flash Player/#SharedObjects/KROKWXRK/#localhost/sos/MyApp.swf/data.sol
Nota: si no proporcionan ningún nombre en el método SharedObject.getLocal() , Flash Player asigna un nombre al archivo undefined.sol.

De forma predeterminada, Flash puede guardar objetos SharedObject persistentes localmente de hasta 100 KB por dominio. Este valor puede configurarlo el usuario. Si la aplicación intenta guardar datos en un objeto compartido que podrían hacerlo superior a 100 KB, Flash Player muestra el cuadro de diálogo Almacenamiento local, que permite al usuario permitir o rechazar más almacenamiento local para el dominio que está solicitando acceso.

Cómo especificar una ruta

Puede utilizar el parámetro opcional pathname para especificar una ubicación para el archivo SharedObject . Este archivo debe ser un subdirectorio del directorio SharedObject de ese dominio. Por ejemplo, si se solicita una aplicación en el host local y se especifica lo siguiente:

mySO = SharedObject.getLocal("myObjectFile","/");

Flash Player escribe el archivo SharedObject en el directorio /#localhost (o /localhost si la aplicación está fuera de línea). Esto resulta útil si se desea que varias aplicaciones en el cliente puedan acceder al mismo objeto compartido. En este caso, el cliente podría ejecutar dos aplicaciones de Flex, que especifican una ruta al objeto compartido que es la raíz del dominio; el cliente podría acceder al mismo objeto compartido desde ambas aplicaciones. Para compartir datos entre varias aplicaciones sin persistencia, puede utilizar el objeto LocalConnection.

Si especifica un directorio que no existe, Flash Player no crea ningún archivo SharedObject.

Cómo añadir datos a un objeto compartido

Puede añadir datos al archivo *.sol de objeto compartido SharedObject mediante la propiedad data del objeto SharedObject. Para añadir nuevos datos al objeto compartido, utilice la siguiente sintaxis:

sharedObject_name.data.variable = value;

En el siguiente ejemplo se añaden las propiedades userName , itemNumbers y adminPrivileges y sus valores a SharedObject:

public var currentUserName:String = "Reiner"; 
public var itemsArray:Array = new Array(101,346,483); 
public var currentUserIsAdmin:Boolean = true; 
mySO.data.userName = currentUserName; 
mySO.data.itemNumbers = itemsArray; 
mySO.data.adminPrivileges = currentUserIsAdmin;

Tras asignar valores a la propiedad data , debe indicar a Flash Player que escriba estos valores en el archivo de SharedObject. Para que Flash Player escriba los valores en el archivo de SharedObject, utilice el método flush() de SharedObject , del siguiente modo:

mySO.flush();

Si no se llama al método SharedObject.flush() , Flash Player escribe los valores en el archivo cuando se cierra la aplicación. No obstante, esto no proporciona al usuario ninguna oportunidad de aumentar el espacio disponible que Flash Player tiene para almacenar los datos si estos sobrepasan la configuración predeterminada. Por lo tanto, se recomienda llamar a SharedObject.flush() .

Cuando se utiliza el método flush() para escribir objetos compartidos en el disco duro de un usuario, es necesario comprobar si el usuario ha desactivado de forma explícita el almacenamiento local a través del Administrador de configuración de Flash Player ( www.macromedia.com/support/documentation/es/flashplayer/help/settings_manager07.html ), tal y como se muestra en el siguiente ejemplo:

var so:SharedObject = SharedObject.getLocal("test"); 
trace("Current SharedObject size is " + so.size + " bytes."); 
so.flush();

Almacenamiento de objetos en objetos compartidos

Es posible almacenar objetos sencillos, como Arrays o Strings, en una propiedad data de SharedObject.

El siguiente ejemplo muestra una clase de ActionScript que define métodos que controlan la interacción con el objeto compartido. Estos métodos permiten al usuario añadir y eliminar objetos del objeto compartido. Esta clase almacena una ArrayCollection que contiene objetos simples.

package { 
    import mx.collections.ArrayCollection; 
    import flash.net.SharedObject; 
 
    public class LSOHandler { 
 
        private var mySO:SharedObject; 
        private var ac:ArrayCollection; 
        private var lsoType:String; 
 
        // The parameter is "feeds" or "sites". 
        public function LSOHandler(s:String) { 
            init(s); 
        } 
 
        private function init(s:String):void { 
            ac = new ArrayCollection(); 
            lsoType = s; 
            mySO = SharedObject.getLocal(lsoType); 
            if (getObjects()) { 
                ac = getObjects(); 
            } 
        } 
 
        public function getObjects():ArrayCollection { 
            return mySO.data[lsoType]; 
        } 
 
        public function addObject(o:Object):void { 
            ac.addItem(o); 
            updateSharedObjects(); 
        } 
 
        private function updateSharedObjects():void { 
            mySO.data[lsoType] = ac; 
            mySO.flush(); 
        } 
    } 
 
}

La siguiente aplicación Flex crea una instancia de la clase de ActionScript para cada uno de los tipos de objetos compartidos que necesita. A continuación llama al método de esa clase cuando el usuario añade o elimina direcciones URL de sitios o blogs.

<?xml version="1.0"?> 
<!-- lsos/BlogAggregator.mxml --> 
<mx:Application 
    xmlns:local="*" 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    creationComplete="initApp()" 
    backgroundColor="#ffffff" 
> 
    <mx:Script> 
        <![CDATA[ 
        import mx.collections.ArrayCollection; 
        import mx.utils.ObjectUtil; 
        import flash.net.SharedObject; 
 
        [Bindable] 
        public var welcomeMessage:String; 
        
        [Bindable] 
        public var localFeeds:ArrayCollection = new ArrayCollection(); 
 
        [Bindable] 
        public var localSites:ArrayCollection = new ArrayCollection(); 
 
        public var lsofeeds:LSOHandler; 
        public var lsosites:LSOHandler; 
 
        private function initApp():void { 
            lsofeeds = new LSOHandler("feeds"); 
            lsosites = new LSOHandler("sites"); 
            
            if (lsofeeds.getObjects()) { 
                localFeeds = lsofeeds.getObjects(); 
            } 
            if (lsosites.getObjects()) { 
                localSites = lsosites.getObjects(); 
            } 
        } 
        
        // Adds a new feed to the feeds DataGrid. 
        private function addFeed():void { 
            // Construct an object you want to store in the 
            // LSO. This object can contain any number of fields. 
            var o:Object = {name:ti1.text, url:ti2.text, date:new Date()}; 
            lsofeeds.addObject(o); 
    
            // Because the DataGrid's dataProvider property is 
            // bound to the ArrayCollection, Flex updates the 
            // DataGrid when you call this method. 
            localFeeds = lsofeeds.getObjects(); 
            
            // Clear the text fields. 
            ti1.text = '';        
            ti2.text = ''; 
        } 
        
        // Removes feeds from the feeds DataGrid. 
        private function removeFeed():void { 
            // Use a method of ArrayCollection to remove a feed. 
            // Because the DataGrid's dataProvider property is 
            // bound to the ArrayCollection, Flex updates the 
            // DataGrid when you call this method. You do not need 
            // to update it manually. 
            if (myFeedsGrid.selectedIndex > -1) { 
            
localFeeds.removeItemAt(myFeedsGrid.selectedIndex); 
             } 
        } 
        
        private function addSite():void { 
            var o:Object = {name:ti3.text, date:new Date()}; 
            lsosites.addObject(o); 
            localSites = lsosites.getObjects(); 
            ti3.text = '';                
        } 
        
        private function removeSite():void { 
            if (mySitesGrid.selectedIndex > -1) { 
            
localSites.removeItemAt(mySitesGrid.selectedIndex); 
            }       
        } 
 
        ]]> 
    </mx:Script> 
        
    <mx:Label text="Blog aggregator" fontSize="28"/> 
    
    <mx:Panel title="Blogs"> 
        <mx:Form id="blogForm"> 
            <mx:HBox> 
                <mx:FormItem label="Name:"> 
                    <mx:TextInput id="ti1" width="100"/> 
                </mx:FormItem> 
                <mx:FormItem label="Location:"> 
                    <mx:TextInput id="ti2" width="300"/> 
                </mx:FormItem> 
                <mx:Button id="b1" label="Add Feed" click="addFeed()"/> 
            </mx:HBox> 
 
            <mx:FormItem label="Existing Feeds:"> 
                <mx:DataGrid 
                    id="myFeedsGrid" 
                    dataProvider="{localFeeds}" 
                    width="400" 
                /> 
            </mx:FormItem> 
            <mx:Button id="b2" label="Remove Feed" click="removeFeed()"/> 
        </mx:Form> 
    </mx:Panel> 
    
    <mx:Panel title="Sites"> 
        <mx:Form id="siteForm"> 
            <mx:HBox> 
                <mx:FormItem label="Site:"> 
                    <mx:TextInput id="ti3" width="400"/> 
                </mx:FormItem> 
                <mx:Button id="b3" label="Add Site" click="addSite()"/> 
            </mx:HBox> 
 
            <mx:FormItem label="Existing Sites:"> 
                <mx:DataGrid 
                    id="mySitesGrid" 
                    dataProvider="{localSites}" 
                    width="400" 
                /> 
            </mx:FormItem> 
            <mx:Button id="b4" label="Remove Site" click="removeSite()"/> 
        </mx:Form> 
    </mx:Panel> 
    
</mx:Application>

Almacenamiento de objetos con tipo en objetos compartidos

Se pueden almacenar instancias de ActionScript con tipo en objetos compartidos. Esto se lleva a cabo llamando al método flash.net.registerClassAlias() para registrar la clase. Si se crea una instancia de la clase y se almacena en el miembro de datos del objeto compartido y posteriormente se lee el objeto, se obtendrá una instancia con tipo. De forma predeterminada, la propiedad objectEncoding de SharedObject admite la codificación AMF3 y desempaqueta la instancia almacenada desde el objeto SharedObject; la instancia almacenada conserva el mismo tipo que se especificó cuando se llamó al método registerClassAlias() .

(Solo iOS) Impedir copia de seguridad en la nube de objetos compartidos locales

Puede definir la propiedad SharedObject.preventbackup para controlar si se realizará una copia de seguridad de los objetos compartidos locales en el servicio de copia de seguridad en la nube de iOS. Apple lo exige así para contenido que puede volver a generarse o descargarse y es necesario para el funcionamiento correcto de la aplicación cuando se usa sin conexión.

Creación de varios objetos compartidos

Es posible crear varios objetos compartidos para la misma aplicación Flex. Para ello, cada uno de ellos se asigna a un nombre de instancia distinto, tal y como se muestra en el siguiente ejemplo:

public var mySO:SharedObject = SharedObject.getLocal("preferences"); 
public var mySO2:SharedObject = SharedObject.getLocal("history");

Con esto se crean los archivos preferences.sol y history.sol en el directorio local de la aplicación Flex.

Creación de un objeto SharedObject seguro

Cuando se crea una instancia de SharedObject local o remota mediante getLocal() o getRemote() , hay un parámetro opcional denominado secure que determina si el acceso a este objeto compartido queda restringido a los archivos SWF enviados a través de una conexión HTTPS. Si el valor de este parámetro es true y el archivo SWF se envía a través de HTTPS, Flash Player crea un nuevo objeto compartido seguro u obtiene una referencia a un objeto compartido seguro existente. Solo pueden leer o escribir en este objeto compartido seguro los archivos SWF enviados a través de HTTPS que llamen a SharedObject.getLocal() con el parámetro secure establecido en true . Si el valor de este parámetro es false y el archivo SWF se envía a través de HTTPS, Flash Player crea un nuevo objeto compartido u obtiene una referencia a un objeto compartido existente.

Los archivos SWF enviados mediante conexiones no HTTPS pueden leer o escribir en este objeto compartido. Si un archivo SWF se ha enviado a través de una conexión no HTTPS y se intenta establecer este parámetro en true , no se podrá crear un nuevo objeto compartido (o acceder a un objeto compartido seguro creado anteriormente), se emitirá un error y el objeto compartido se establecerá en null . Si se intenta ejecutar el siguiente fragmento de código desde una conexión no HTTPS, el método SharedObject.getLocal() emitirá un error:

try 
{ 
    var so:SharedObject = SharedObject.getLocal("contactManager", null, true); 
} 
catch (error:Error) 
{ 
    trace("Unable to create SharedObject."); 
}

Independientemente del valor de este parámetro, los objetos compartidos creados aumentan el espacio en disco total permitido en el dominio.

Visualización del contenido de un objeto compartido

Los valores se almacenan en los objetos compartidos dentro de la propiedad data. Puede repetir indefinidamente todos los valores de una instancia de objeto compartido utilizando un bucle for..in , tal y como se muestra en el siguiente ejemplo:

var so:SharedObject = SharedObject.getLocal("test"); 
so.data.hello = "world"; 
so.data.foo = "bar"; 
so.data.timezone = new Date().timezoneOffset; 
for (var i:String in so.data) 
{ 
    trace(i + ":\t" + so.data[i]); 
}

Eliminación de objetos compartidos

Para eliminar un elemento SharedObject en el cliente, utilice el método SharedObject.clear() . Con esta operación no se eliminan los directorios en la ruta predeterminada para los objetos compartidos de la aplicación.

En el siguiente ejemplo se elimina el archivo SharedObject del cliente:

public function destroySharedObject():void { 
    mySO.clear(); 
}

Ejemplo de SharedObject

El siguiente ejemplo muestra cómo se almacenan objetos sencillos, como un objeto Date, en un objeto SharedObject sin tener que serializarlos ni deserializarlos manualmente.

El ejemplo siguiente comienza dándole la bienvenida como visitante. Al hacer clic en Log Out (Cerrar sesión), la aplicación almacena la fecha actual en un objeto compartido. La próxima vez que inicie esta aplicación o actualice la página, la aplicación le dará la bienvenida con un recordatorio de la hora en que cerró la sesión.

Para ver la aplicación en funcionamiento, haga clic en Log Out y después actualice la página. La aplicación muestra la fecha y la hora en la que hizo clic en el botón Log Out en su visita anterior. En cualquier momento, puede eliminar la información almacenada haciendo clic en el botón Delete LSO.

<?xml version="1.0"?> 
<!-- lsos/WelcomeMessage.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()"> 
  <mx:Script><![CDATA[ 
  public var mySO:SharedObject; 
  [Bindable] 
  public var welcomeMessage:String; 
 
  public function initApp():void { 
     mySO = SharedObject.getLocal("mydata"); 
     if (mySO.data.visitDate==null) { 
        welcomeMessage = "Hello first-timer!" 
     } else { 
        welcomeMessage = "Welcome back. You last visited on " + 
           getVisitDate(); 
     } 
  } 
 
  private function getVisitDate():Date { 
     return mySO.data.visitDate; 
  } 
 
  private function storeDate():void { 
     mySO.data.visitDate = new Date(); 
     mySO.flush(); 
  } 
  
  private function deleteLSO():void { 
     // Deletes the SharedObject from the client machine. 
     // Next time they log in, they will be a 'first-timer'. 
     mySO.clear(); 
  } 
  
  ]]></mx:Script> 
  <mx:Label id="label1" text="{welcomeMessage}"/> 
  <mx:Button label="Log Out" click="storeDate()"/> 
  <mx:Button label="Delete LSO" click="deleteLSO()"/> 
</mx:Application>