10

我正在开发一个需要在页面上调用一些 Javascript 并从中获取数据的 Flash 游戏。从 Flash 调用 Javascript 有效。从 Javascript 调用 Flash 函数(通常)不会。

我正在使用Gaia 框架

怎么了:

  1. 使用 SWFObject 加载 swf
  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. 定期重试 FlashaddCallback()并不能解决错误
  8. 发生错误时,ExternalInterface.available = trueExternalInterface.objectID包含 Flash 嵌入对象的正确名称。
  9. 发生错误时,document.getElementById('myflashcontent')正确返回 Flash 嵌入对象。

编辑添加:

  • 此问题出现在 Firefox 3.6 中,但未出现在 Chrome 或 IE8 中。我没有尝试过旧的浏览器。
  • 我正在运行 Flash 播放器的调试版本。
  • 我的电话ExternalInterface.addCallback()被包裹在一个try...catch块中。发生 JS 错误时,不会触发catch块。这是一个无声的失败。
  • 在 webhost 上进行测试时会发生错误,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(); }
});
4

8 回答 8

2

通过 ExternalInterface 对 JS 的调用被包装在一个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);

};
于 2010-06-22T15:30:46.193 回答
1

这是我们缩小所有条件后的场景:

  • 仅在 FireFox/Windows 上
  • 仅当 wmode=transparent
  • 仅在使用 js alert() 函数时

在这种特定情况下,ExternalInterface.call() 不会立即触发。它仅在使用 Timer 类创建一个微小的延迟后才起作用。

如果我们设置了 wmode=window,或者删除了 alert() - 一切正常。尝试使用 console.log() 在 firebug 中显示调试文本。

另一个问题?您的 js 函数是否返回数组或对象与字符串。令人惊讶的是,返回原生 js 数组是由 Flash 中的数组解释的。尝试输出有关您的退货数据的信息,如下所示:

var myRetVal = flash.external.ExternalInterface.call("my_js_func");
debug_txt.text = flash.utils.describeType(myRetVal).toString();
于 2011-01-27T17:27:49.370 回答
1

这可能与您遇到的问题类似。

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

于 2011-06-14T22:24:21.870 回答
0

我尝试了你的代码,如果我在所有事情之前都发出警报,它就可以了,所以,我认为这与你必须等待的某种时间有关。

于 2010-06-29T21:06:14.267 回答
0

如果在拨打电话时在 Flash 中发生错误,您可以看到该类型的错误消息。像一个未捕获的异常。

您正在运行播放器的调试版本吗?这可能会为您提供有关正在发生的事情的更多信息。

另外,这在浏览器中是否一致?我已经看到旧版本的 IE 无法接受几个连续的 Flash <-> JS 调用。

Ĵ

于 2010-04-14T06:30:24.100 回答
0

你在 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;
}
于 2011-06-04T14:15:05.027 回答
0

我们遇到了同样的问题,而且只在 Firefox 中。

根据 THM 给出的建议,我们能够找到解决方案。

在我们的例子中,被插入的 swf 位于一个 div 中,该 div 使用 jQuery.slideDown() 进行动画处理。这显然会导致它在启动时有时会重新启动。在某些情况下,这会导致回调函数不可用。

仅在 slideDown 效果完成后调用 swfobject.embedSWF 进行修复。

于 2011-09-01T12:58:34.720 回答
0

我收到此错误是因为我在页面上有多次相同的 Flash 文件。即使他们每个人都有不同的 id/name,他们都使用相同的回调。

于 2012-05-14T02:08:30.303 回答