Uso de la clase ExternalInterface

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

La comunicación entre ActionScript y la aplicación contenedora puede adoptar una de las siguientes formas: ActionScript puede llamar al código (por ejemplo, una función de JavaScript) definido en el contenedor, o bien, el código del contenedor puede llamar una función de ActionScript que se haya designado como función que es posible llamar. En cualquiera de los casos, se puede enviar la información al código que se está llamando y se pueden devolver los resultados al código que realiza la llamada.

Para facilitar esta comunicación, la clase ExternalInterface incluye dos propiedades estáticas y dos métodos estáticos. Estas propiedades y métodos se utilizan para obtener información acerca de la conexión de la interfaz externa, para ejecutar código en el contenedor desde ActionScript y para hacer que las funciones ActionScript estén disponibles para ser llamadas desde el contenedor.

Obtención de información sobre el contenedor externo

La propiedad ExternalInterface.available indica si Flash Player se encuentra en esos momentos en un contenedor que ofrece una interfaz externa. Si la interfaz externa está disponible, esta propiedad es true ; en caso contrario, es false . Antes de utilizar cualquier otra funcionalidad de la clase ExternalInterface, es recomendable comprobar que el contenedor que se está utilizando en esos momentos permite la comunicación a través de la interfaz externa del modo siguiente:

if (ExternalInterface.available) 
{ 
    // Perform ExternalInterface method calls here. 
}
Nota: la propiedad ExternalInterface.available indica si el contenedor que se está utilizando en esos momentos es de un tipo compatible con la conectividad mediante ExternalInterface. No indicará si JavaScript está habilitado en el navegador.

La propiedad ExternalInterface.objectID permite determinar el identificador exclusivo de la instancia de Flash Player (específicamente, el atributo id de la etiqueta object en Internet Explorer o el atributo name de la etiqueta embed en los navegadores que usan la interfaz NPRuntime). Este identificador exclusivo representa al documento SWF actual en el navegador y se puede utilizar para hacer referencia al documento SWF (por ejemplo, al llamar a una función de JavaScript en una página HTML contenedora). Cuando el contenedor de Flash Player no es un navegador web, esta propiedad es null .

Llamada a código externo desde ActionScript

El método ExternalInterface.call() ejecuta código en la aplicación contenedora. Como mínimo requiere un parámetro, una cadena que contenga el nombre de la función que se va a llamar en la aplicación contenedora. Todos los parámetros adiciones que se pasen al método ExternalInterface.call() se pasarán a su vez al contenedor como parámetros de la llamada a la función.

// calls the external function "addNumbers" 
// passing two parameters, and assigning that function's result 
// to the variable "result" 
var param1:uint = 3; 
var param2:uint = 7; 
var result:uint = ExternalInterface.call("addNumbers", param1, param2);

Si el contenedor es una página HTML, este método invocará a la función de JavaScript con el nombre especificado, que debe estar definida en un elemento script en la página HTML contenedora. El valor devuelto por la función de JavaScript se devuelve a ActionScript.

<script language="JavaScript"> 
    // adds two numbers, and sends the result back to ActionScript 
    function addNumbers(num1, num2) 
    { 
        return (num1 + num2); 
    } 
</script>

Si el contenedor es algún otro contenedor ActiveX, este método hace que el control ActiveX de Flash Player distribuya su evento FlashCall . Flash Player serializa en una cadena XML el nombre de la función especificada y todos los parámetros. El contenedor puede acceder a esa información de la propiedad request del objeto de evento y utilizarla para determinar el modo en que se ejecutará su propio código. Para devolver un valor a ActionScript, el código del contenedor llama al método SetReturnValue() del objeto ActiveX y pasa el resultado (serializado en una cadena XML) como parámetro de ese método. Para obtener más información sobre el formato XML utilizado para esta comunicación, consulte Formato XML de la API externa .

Tanto si el contenedor es un navegador web como si otro contenedor ActiveX, en el caso de que se produzca un error en la llamada o el método del contenedor no especifique un valor devuelto, se devolverá null. El método ExternalInterface.call() emite una excepción SecurityError si el entorno contenedor pertenece a un entorno limitado de seguridad al que no tiene acceso el código que realiza la llamada. Se puede solucionar esta limitación asignando un valor adecuado a allowScriptAccess en el entorno contenedor. Por ejemplo, para cambiar el valor de allowScriptAccess en una página HTML, es necesario editar el atributo adecuado en las etiquetas object y embed .

Llamadas a código ActionScript desde el contenedor

Un contenedor solo puede llamar a código ActionScript que se encuentre en una función; no puede llamar a ningún otro código ActionScript. Para llamar una función de ActionScript desde la aplicación contenedora, debe realizar dos operaciones: registrar la función con la clase ExternalInterface y posteriormente llamarla desde el código del contenedor.

En primer lugar se debe registrar la función de ActionScript para indicar que debe ponerse a disposición del contenedor. Para ello se usa el método ExternalInterface.addCallback() del modo siguiente:

function callMe(name:String):String 
{ 
    return "busy signal"; 
} 
ExternalInterface.addCallback("myFunction", callMe);

El método addCallback() utiliza dos parámetros: El primero, un nombre de función con formato String, es el nombre por el que se conocerá a la función en el contenedor. El segundo parámetro es la función real de ActionScript que se ejecutará cuando el contenedor llame al nombre de función definido. Dado que estos dos nombres son distintos, se puede especificar un nombre de función que se utilizará en el contenedor incluso si la función real de ActionScript tiene un nombre distinto. Esto resulta especialmente útil si no se conoce el nombre de la función (por ejemplo, cuando se especifica una función anónima o cuando la función que ha de llamarse se determina en tiempo de ejecución).

Una vez que la función de ActionScript se registra en la clase ExternalInterface, el contenedor puede llamar a la función. La forma de realizar esto varía según el tipo de contenedor. Por ejemplo, en el código JavaScript en un navegador web, la función de ActionScript se llama utilizando el nombre de función registrado como si fuese un método del objeto del navegador de Flash Player (es decir, un método del objeto JavaScript que representa a la etiqueta object o embed). Dicho de otro modo, se pasan los parámetros y se devuelve el resultado como si se llamase a una función local.

<script language="JavaScript"> 
    // callResult gets the value "busy signal" 
    var callResult = flashObject.myFunction("my name"); 
</script> 
... 
<object id="flashObject"...> 
    ... 
    <embed name="flashObject".../> 
</object>

Por otra parte, al llamar a una función de ActionScript en un archivo SWF que se ejecuta en una aplicación de escritorio, el nombre de función registrado y los parámetros deben serializarse en una cadena con formato XML. A continuación, se efectúa la llamada llamando al método CallFunction() del control ActiveX con la cadena XML como parámetro. Para obtener más información sobre el formato XML utilizado para esta comunicación, consulte Formato XML de la API externa .

En cualquiera de los dos casos, el valor devuelto por la función de ActionScript se pasa al código del contenedor, ya sea directamente como un valor si la llamada se origina en el código JavaScript de un navegador o serializado como una cadena con formato XML si la llamada se origina en un contenedor ActiveX.

Formato XML de la API externa

En la comunicación entre ActionScript y la aplicación que aloja el control ActiveX de Shockwave Flash se utiliza un formato XML específico para codificar las llamadas a las funciones y los valores. El formato XML usado por la API externa tiene dos partes. Se utiliza un formato para representar las llamadas a funciones. El otro se utiliza para representar valores individuales; este formato se emplea para parámetros de funciones y para los valores devueltos por las funciones. El formato XML para llamadas a funciones se utiliza para llamadas desde y hacia ActionScript. En el caso de una llamada a una función desde ActionScript, Flash Player pasa los datos XML al contenedor; cuando se trata de una llamada desde el contenedor, Flash Player espera que la aplicación contenedora pase una cadena XML con este formato. El siguiente fragmento XML muestra un ejemplo de llamada a función con formato XML:

<invoke name="functionName" returntype="xml"> 
    <arguments> 
        ... (individual argument values) 
    </arguments> 
</invoke>

El nodo raíz es invoke , Cuenta con dos atributos: name indica el nombre de la función que se va a llamar y returntype siempre es xml . Si la llamada a la función incluye parámetros, el nodo invoke tendrá un nodo secundario arguments , cuyos nodos secundarios serán los valores de los parámetros a los que se ha dado el formato de valor individual que se explica a continuación.

Los valores individuales, incluidos los parámetros de las funciones y los valores devueltos por estas, utilizan un esquema de formato que, además de los valores reales, incluye información sobre los tipos de datos. En la siguiente tabla se indican las clases de ActionScript y el formato XML utilizado para codificar los valores de ese tipo de datos:

Clase/Valor de ActionScript

Clase/Valor de C#

Formato

Comentarios

null

null

<null/>

Boolean true

bool true

<true/>

Boolean false

bool false

<false/>

String

cadena

<string>valor de cadena</string>

Number, int, uint

single, double, int, uint

<number>27.5</number> 
<number>-12</number>

Array (los elementos pueden ser de varios tipos)

Un conjunto que admite elementos de varios tipos, como ArrayList u object[]

<array> 
    <property id="0"> 
        <number>27.5</number> 
    </property> 
    <property id="1"> 
        <string>Hello there!</string> 
    </property> 
    ... 
</array>

El nodo property define elementos individuales y el atributo id es el índice numérico de base cero.

Object

Un diccionario con claves de tipo cadena y valores de objeto, como un objeto HashTable con claves de tipo cadena

<object> 
    <property id="name"> 
        <string>John Doe</string> 
    </property> 
    <property id="age"> 
        <string>33</string> 
    </property> 
    ... 
</object>

El nodo property define propiedades individuales y el atributo id es el nombre de la propiedad (una cadena).

Otras clases incorporadas o personalizadas

<null/> or  
<object></object>

ActionScript codifica otros objetos como null o como un objeto vacío. En ambos casos, los valores de la propiedad se pierden.

Nota: a modo de ejemplo, esta tabla muestra las clases de C# equivalentes además de las clases de ActionScript; no obstante, la API externa se puede usar para comunicarse con cualquier lenguaje de programación o entorno de tiempo de ejecución compatible con los controles ActiveX y no se limita a las aplicaciones C#.

Cuando se crean aplicaciones propias utilizando la API externa con una aplicación contenedora ActiveX, suele resultar cómodo escribir un proxy encargado de la tarea de convertir las llamadas a funciones nativas en el formato XML serializado. Para ver un ejemplo de una clase proxy escrita en C#, consulte Dentro de la clase ExternalInterfaceProxy.