Пример внешнего API: связь между ActionScript и JavaScript в веб-обозревателеFlash Player 9 и более поздних версий, Adobe AIR 1.0 и более поздних версий Этот образец приложения демонстрирует применение подходящих методов обмена данными между ActionScript и JavaScript в веб-обозревателе в контексте приложения для мгновенного обмена сообщениями, которое позволяет человеку участвовать в чате с самим собой (отсюда и имя приложения: Introvert IM). Пересылка сообщений между формой HTML на веб-странице и интерфейсом SWF выполняется с помощью внешнего API. В этом примере показаны, например, следующие методы:
Получить файлы приложения для этого примера можно на странице www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы приложения Introvert IM находятся в папке Samples/IntrovertIM_HTML. Приложение состоит из следующих файлов.
Подготовка связи между ActionScript и обозревателемОдно из наиболее частых применений внешнего API состоит в том, чтобы позволять приложениям ActionScript связываться с обозревателем. С помощью внешнего API методы ActionScript могут вызывать код, написанный на языке JavaScript, и наоборот. Из-за сложности обозревателей и их метода внутренней визуализации страниц не существует метода, гарантирующего, что документ SWF зарегистрирует обратные вызовы перед тем, как будет запущен первый код JavaScript на HTML-странице. По этой причине перед вызовом функций в SWF-документе из JavaScript ваш SWF-документ должен всегда вызывать HTML-страницу, чтобы уведомить ее о том, что SWF-документ готов к приему подключений. Например, выполнив ряд действий с применением класса IMManager, Introvert IM определяет, готов ли обозреватель для связи, и подготовить SWF-файл для связи. Первый шаг состоит в определении времени, когда обозреватель готов для связи. Он выполняется в конструкторе IMManager следующим образом: public function IMManager(initialStatus:IMStatus)
{
_status = initialStatus;
// Check if the container is able to use the external API.
if (ExternalInterface.available)
{
try
{
// This calls the isContainerReady() method, which in turn calls
// the container to see if Flash Player has loaded and the container
// is ready to receive calls from the SWF.
var containerReady:Boolean = isContainerReady();
if (containerReady)
{
// If the container is ready, register the SWF's functions.
setupCallbacks();
}
else
{
// If the container is not ready, set up a Timer to call the
// container at 100ms intervals. Once the container responds that
// it's ready, the timer will be stopped.
var readyTimer:Timer = new Timer(100);
readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
readyTimer.start();
}
}
...
}
else
{
trace("External interface is not available for this container.");
}
}
Первым делом код проверяет, доступен ли внешний API в текущем контейнере с помощью свойства ExternalInterface.available. При этом он приступает к установке подключения. Поскольку исключения, связанные с безопасностью, и другие ошибки могут происходить при попытке связи с внешним приложением, код упакован в блок try (соответствующие блоки catch были пропущены при перечислении для краткости). Затем код вызывает метод isContainerReady(): private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
Метод isContainerReady() в свою очередь обращается к методу ExternalInterface.call(), чтобы вызвать функцию JavaScript isReady() следующим образом: <script language="JavaScript">
<!--
// ------- Private vars -------
var jsReady = false;
...
// ------- functions called by ActionScript -------
// called to check if the page has initialized and JavaScript is available
function isReady()
{
return jsReady;
}
...
// called by the onload event of the <body> tag
function pageInit()
{
// Record that JavaScript is ready to go.
jsReady = true;
}
...
//-->
</script>
Функция isReady() просто возвращает значение переменной jsReady. Этой переменной исходно присвоено значение false; после запуска события onload на веб-странице переменная принимает значение true. Другим словами, если ActionScript вызывает функцию isReady() перед загрузкой страницы, JavaScript возвращает false для ExternalInterface.call("isReady"), а метод ActionScript isContainerReady() возвращает соответственно значение false. После завершения загрузки страницы функция JavaScript isReady() возвращает значение true. Поэтому метод isContainerReady() в ActionScript также возвращает true. В конструкторе IMManager происходит одно из двух событий в зависимости от готовности контейнера. Если isContainerReady() возвращает true, код просто вызывает метод setupCallbacks(), который завершает процесс установки связи с JavaScript. С другой стороны, если isContainerReady() возвращает false, процесс по существу откладывается. Создается объект Timer, которому дается инструкция вызывать метод timerHandler() раз в 100 миллисекунд: private function timerHandler(event:TimerEvent):void
{
// Check if the container is now ready.
var isReady:Boolean = isContainerReady();
if (isReady)
{
// If the container has become ready, we don't need to check anymore,
// so stop the timer.
Timer(event.target).stop();
// Set up the ActionScript methods that will be available to be
// called by the container.
setupCallbacks();
}
}
Каждый раз, когда вызывается метод timerHandler(), он снова проверяет результат метода isContainerReady(). После инициализации контейнера этот метод возвращает значение true. Затем код останавливает Timer и вызывает метод setupCallbacks(), завершая процесс установки подключения к обозревателю. Предоставление методов ActionScript JavaScriptКак показано в предыдущем примере, после того, как код определяет, что обозреватель готов, вызывается метод setupCallbacks(). Этот метод готовит ActionScript для принятия вызовов со стороны JavaScript, как указано ниже: private function setupCallbacks():void
{
// Register the SWF client functions with the container
ExternalInterface.addCallback("newMessage", newMessage);
ExternalInterface.addCallback("getStatus", getStatus);
// Notify the container that the SWF is ready to be called.
ExternalInterface.call("setSWFIsReady");
}
Метод setCallBacks() завершает задачу подготовки связи с контейнером путем вызова метода ExternalInterface.addCallback() для регистрации двух методов, которые можно будет вызвать из JavaScript. В этом коде первый параметр (имя, под которым этот метод известен JavaScript ("newMessage" и "getStatus") идентичен имени метода в ActionScript. В данном случае использование других имен не давало преимущества, поэтому для простоты повторно применялось одно и то же имя. В итоге метод ExternalInterface.call() использовался для вызова функции JavaScriptsetSWFIsReady(), которая уведомляет контейнер о том, что функции ActionScript были зарегистрированы. Связь между ActionScript и обозревателемПриложение Introvert IM демонстрирует целый ряд примеров вызова функций JavaScript на странице контейнера. В простейшем случае (пример из метода setupCallbacks()) функция setSWFIsReady() в JavaScript вызывается без передачи каких-либо параметров или получения в ответ значения: ExternalInterface.call("setSWFIsReady");
В другом примере из метода isContainerReady() ActionScript вызывает функцию isReady() и получает в ответ логическое значение: var result:Boolean = ExternalInterface.call("isReady");
Передать параметры функциям JavaScript можно также с помощью внешнего API. Рассмотрим, к примеру, метод sendMessage() класса IMManager, который вызывается, когда пользователь отправляет новое сообщение своему «собеседнику»: public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
И снова здесь применяется метод ExternalInterface.call() для вызова назначенной функции JavaScript, уведомляя обозревателя о новом сообщении. Кроме того, само сообщение передается в качестве дополнительного параметра методу ExternalInterface.call() и соответственно передается в качестве параметра функции JavaScriptnewMessage(). Вызов кода ActionScript из JavaScriptСвязь предполагает двусторонний обмен, и приложение Introvert IM не является исключением. Не только клиент системы мгновенного обмена сообщениями в проигрывателе Flash Player вызывает JavaScript для отправки сообщений. HTML-форма также вызывает код JavaScript для отправки сообщений и запроса информации из SWF-файла. Например, когда SWF-файл уведомляет контейнер о том, что он закончил устанавливать контакт и готов к связи, обозреватель первым делом вызывает метод getStatus() класса IMManager, чтобы узнать исходное состояние доступности пользователя из клиента системы мгновенного обмена сообщениями SWF. Это выполняется на веб-странице функции updateStatus() следующим образом: <script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
Код проверяет значение переменной swfReady, которая следит за тем, уведомил ли SWF-файл обозреватель о том, что он зарегистрировал свои методы в классе ExternalInterface. Если SWF-файл готов к приему связи, следующая строка (var currentStatus = ...) фактически вызывает метод getStatus() в классе IMManager. В этой строке происходят три события.
Примечание. Если вы внимательно отслеживаете код, то, вероятно, заметили, что в исходном коде для функции updateStatus() строка кода, вызывающая функцию getSWF(), на самом деле записана следующим образом: var currentStatus = getSWF("${application}").getStatus(). Текст ${application} является местозаполнителем в шаблоне страницы HTML. Когда Adobe Flash Builder создает конкретную страницу HTML для приложения, этот местозаполнитель заменяется тем же текстом, который используется в качестве атрибута id тега object и атрибута name тега embed (в данном примере это текст IntrovertIMApp). Именно это значение и ожидается функцией getSWF().
Функция sendMessage() для JavaScript демонстрирует передачу параметра функции ActionScript. (sendMessage() — это функция, которая вызывается, когда пользователь нажимает кнопку «Отправить» на HTML-странице.) <script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
Метод newMessage() для ActionScript ожидает один параметр. Поэтому переменная message для JavaScript передается в ActionScript. Она служит в качестве параметра при вызове метода newMessage() в коде JavaScript. Определение типа обозревателяИз-за различий в методе доступа обозревателей к содержимому важно всегда применять JavaScript, чтобы определить выбранный пользователем обозреватель и вызвать ролик в соответствии с синтаксисом для конкретного обозревателя с помощью объекта окна или документа, как показано в функции getSWF() для JavaScript в этом примере: <script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Если в вашем сценарии не определен тип обозревателя пользователя, пользователь может столкнуться с неожиданным поведением при воспроизведении SWF-файлов в контейнере HTML. |
|