Функции, зарегистрированные с ExternalInterface.addCallback, недоступны в Javascript - PullRequest
10 голосов
/ 14 апреля 2010

Я работаю над Flash-игрой, которая должна вызвать Javascript на странице и получить от нее данные. Вызов Javascript из Flash работает. Вызов функций Flash из Javascript (часто) этого не делает.

Я использую Gaia Framework .

Что происходит:

  1. SWF загружен SWFObject
  2. В файле Flash есть кнопка. При нажатии он использует ExternalInterface.call() для вызова функции Javascript. Это работает.
  3. Функция Javascript вызывает функцию Flash, которая была открыта с помощью ExternalInterface.addCallback().
  4. Иногда , Javascript выдает следующую ошибку: TypeError: myFlash.testCallback is not a function.
  5. Когда происходит ошибка, она влияет на все функции , зарегистрированные с addCallback(). Gaia и некоторые из включенных в нее библиотек используют addCallback(), и при вызове этих функций из Javascript также возникает ошибка TypeError.
  6. Длительное ожидание перед нажатием кнопки во Flash не устраняет ошибку.
  7. Повторная попытка Flash addCallback() периодически не устраняет ошибку
  8. При возникновении ошибки ExternalInterface.available = true и ExternalInterface.objectID содержат правильное имя для объекта встраивания Flash.
  9. При возникновении ошибки document.getElementById('myflashcontent') правильно возвращает объект для вставки Flash.

Отредактировано, чтобы добавить:

  • Эта проблема появляется в Firefox 3.6, но не в Chrome или IE8. Я не пробовал старые браузеры.
  • Я использую отладочную версию проигрывателя Flash.
  • Мои звонки на ExternalInterface.addCallback() заключены в блок try...catch. При возникновении ошибки JS блок catch не запускается . Это тихая ошибка.
  • Ошибка возникает при тестировании на веб-хосте, когда SWF-файл загружается с того же сервера, что и страница, на которой он находится.
  • Я установил allowScriptAccess = always.
  • Настройка flash.system.Security.allowDomain("mydomain") не исправляет ошибку.

С моей страницы класса:

public class MyPage extends AbstractPage
{
    // declarations of stage instances and class variables

    // other functions

    override public function transitionIn():void 
    {
        send_button.addEventListener(MouseEvent.MOUSE_UP, callJS);
        exposeCallbacks();

        super.transitionIn();
    }

    private function exposeCallbacks():void
    {
        trace("exposeCallbacks()");
        if (ExternalInterface.available) {
            trace("ExternalInterface.objectID: " + ExternalInterface.objectID);
            try {
                ExternalInterface.addCallback("testCallback", simpleTestCallback);
                trace("called ExternalInterface.addCallback");
            }
            catch (error:SecurityError) {
                trace("A SecurityError occurred: " + error.message + "\n");
            }
            catch (error:Error) {
                trace("An Error occurred: " + error.message + "\n");
            }
        }
        else {
            trace("exposeCallbacks() - ExternalInterface not available");
        }
    }

    private function simpleTestCallback(str:String):void
    {
        trace("simpleTestCallback(str=\"" + str + "\")");
    }

    private function callJS(e:Event):void
    {
        if (ExternalInterface.available) {
            ExternalInterface.call("sendTest", "name", "url");
        }
        else {
            trace("callJS() - ExternalInterface not available");
        }
    }

}

Мой Javascript:

function sendTest(text, url) {
    var myFlash = document.getElementById("myflashcontent");

    var callbackStatus = "";
    callbackStatus += '\nmyFlash[testCallback]: ' + myFlash['testCallback'];
    //console.log(callbackStatus);

    var errors = false;
    try {
        myFlash.testCallback("test string");
    }
    catch (err) {
        alert("Error: " + err.toString());
        error = true;
    }

    if (!error) {
        alert("Success");
    }
}

var params = {
    quality: "high",
    scale: "noscale",
    wmode: "transparent",
    allowscriptaccess: "always",
    bgcolor: "#000000"
};
var flashVars = {
    siteXML: "xml/site.xml"
};
var attributes = {
    id: "myflashcontent",
    name: "myflashcontent"
};

// load the flash movie.
swfobject.embedSWF("http://myurl.com/main.swf?v2", "myflashcontent",
"728", "676", "10.0.0", serverRoot + "expressInstall.swf",
flashVars, params, attributes, function(returnObj) {
    console.log('Returned ' + returnObj.success);
    if (returnObj.success) { returnObj.ref.focus(); }
});

Ответы [ 8 ]

2 голосов
/ 22 июня 2010

Вызовы, сделанные в JS через ExternalInterface, заключены в блок try { }, что приводит к подавлению последующих ошибок JS.

Обходной путь для того же - вызвать закрытие функции в JavaScript и выполнить реальный код после истечения времени ожидания.

Пример:

function myFnCalledByEI (arg1, arg2) {

    setTimeout(myActualFunction () {
       // You can use arg1 and arg2 here as well!
       // Errors raised within this function will not be
       // suppressed.
    }, 0);

};
1 голос
/ 15 июня 2011

Это может быть похоже на проблему, с которой вы столкнулись.

http://www.google.com/support/forum/p/translator-toolkit-api/thread?tid=58cda1b34ae1e944&hl=en

1 голос
/ 27 января 2011

Вот наш сценарий, когда мы сузили все условия:

  • Только в FireFox / Windows
  • Только когда wmode = прозрачный
  • Только при использовании функции js alert ()

В этом конкретном сценарии ExternalInterface.call () не сработает сразу. Это сработало только после небольшой задержки с классом Timer.

Если мы сделали wmode = window или удалили оповещение () - все заработало. Попробуйте использовать console.log () для отображения текста отладки в firebug.

Другой гоча? Возвращает ли ваша функция js массив или объект против строки. Удивительно, что возвращенный нативный массив js был интерпретирован массивом во Flash. Попробуйте вывести информацию о ваших возвращаемых данных следующим образом:

var myRetVal = flash.external.ExternalInterface.call("my_js_func");
debug_txt.text = flash.utils.describeType(myRetVal).toString();
0 голосов
/ 14 мая 2012

Я получал эту ошибку, потому что у меня был один и тот же файл Flash на странице несколько раз. Хотя у каждого из них был свой идентификатор / имя, они все использовали один и тот же обратный вызов.

0 голосов
/ 01 сентября 2011

Мы столкнулись с той же проблемой, и только в Firefox.

Следуя совету THM, мы смогли найти решение.

В нашем случае вставляемый swf находился внутри div, анимированного в виде с помощью jQuery.slideDown (). Это, по-видимому, иногда приводит к перезагрузке при запуске. В некоторых случаях это приводило к недоступности функций обратного вызова.

Исправлено вызовом swfobject.embedSWF только после завершения эффекта slideDown.

0 голосов
/ 04 июня 2011

Вы пробовали это в JavaScript?

if (myFlash)    
{
  if (!myFlash.testCallback)
  {
    if (__flash__addCallback)
    { 
       __flash__addCallback( myFlash, "testCallback" );
    }
    else
    {
      console.log("Error: Flash External Interface injected JavaScript function not found. The external interface function won't work.");
    }
  }
}

myFlash.testCallback("test string");  

Я использовал это во многих случаях.

Снова в определенных местах мне пришлось переопределить функции __flash_addCallback и _ flash _removeCallback, чтобы минимизировать ошибки.

В настоящее время я не помню, что я сделал для __flash_addCallback, но это то, что я сделал для последнего:

if (__flash__removeCallback) 
{
   __flash__removeCallback = function (instance, name) {if(instance && instance[name]) instance[name] = null;
}
0 голосов
/ 30 июня 2010

Я попробовал твой код, и он работал нормально, если я поставил предупреждение перед всем, поэтому я думаю, что это что-то, связанное с тем, что тебе нужно ждать.

0 голосов
/ 14 апреля 2010

Вы можете увидеть этот тип сообщения об ошибке, если во Flash произошла ошибка. Что-то вроде необъяснимого исключения.

Вы используете отладочную версию плеера? Это может дать вам больше информации о том, что происходит.

Кроме того, это совместимо в разных браузерах? Я видел старые версии IE, у которых были проблемы с принятием нескольких последовательных вызовов Flash <-> JS.

J

...