用 ExternalInterface.addCallback 注册的函数在 Javascript 中不可用

Posted

技术标签:

【中文标题】用 ExternalInterface.addCallback 注册的函数在 Javascript 中不可用【英文标题】:Functions registered with ExternalInterface.addCallback not available in Javascript 【发布时间】:2011-02-07 17:04:52 【问题描述】:

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

我正在使用Gaia framework。

会发生什么:

    使用 SWFObject 加载 swf Flash 文件中有一个按钮。单击时,它使用ExternalInterface.call() 调用Javascript 函数。 这行得通。 Javascript 函数调用了一个以ExternalInterface.addCallback() 公开的 Flash 函数。 有时,Javascript 会产生以下错误:TypeError: myFlash.testCallback is not a function。 当错误发生时,它会影响在addCallback() 注册的所有函数。 Gaia 及其一些包含的库使用addCallback(),并且从 Javascript 调用这些函数也会产生 TypeError。 在 Flash 中按下按钮之前等待很长时间并不能解决错误。 定期让 Flash 重试 addCallback() 并不能解决错误 发生错误时,ExternalInterface.available = trueExternalInterface.objectID 包含 Flash 嵌入对象的正确名称。 发生错误时,document.getElementById('myflashcontent') 正确返回 Flash 嵌入对象。

编辑添加:

此问题出现在 Firefox 3.6 中,但未出现在 Chrome 或 IE8 中。我没有尝试过旧版浏览器。 我正在运行 Flash 播放器的调试版本。 我对@9​​87654331@ 的调用被封装在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(); 
);

【问题讨论】:

你有没有发现这个错误?我得到了同样的东西,只是我只在 IE 中进入,而不是 FF 或 Chrome。好奇怪 这个问题似乎只在调试模式下的 Firefox 和 Flash 上出现(不是在 Chrome 中)(只在 Linux 上?)。 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

按照 THM 的建议,我们找到了解决方案。

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

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

【参考方案4】:

你在 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;

【讨论】:

【参考方案5】:

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

仅在 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();

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

通过 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);

;

【讨论】:

我可以通过 ExternalInterface 调用 JS 很好。这是给我带来问题的另一个方向。 我想,到目前为止,我无法就此提供任何意见。如果我在您的问题仍未得到解答时遇到某些问题,那么我一定会发表我的想法。 :)【参考方案8】:

如果在拨打电话时 Flash 出现问题,您可以看到该类型的错误消息。类似于未捕获的异常。

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

另外,这在浏览器之间是否一致?我看到旧版本的 IE 无法接受多个连续的 Flash JS 调用。

J

【讨论】:

如果您查看我的代码,您会看到 addCallback() 调用被包装在 try..catch 块中。 catch 块永远不会触发。我在 Firefox 3.6 中遇到错误,所以这不是 IE6/7 问题。

以上是关于用 ExternalInterface.addCallback 注册的函数在 Javascript 中不可用的主要内容,如果未能解决你的问题,请参考以下文章

校用设备|校用设备课桌椅|校用设备

c++中的cin 和cout 有啥用怎么用 >> <<有啥用怎么用

resource啥时候用单数?啥时候用复数?

测试用例设计:测试用例格式

什么时候用卡方检验,什么时候用t检验,什么时候用u检验

pybot执行多条用例时,某一个用例执行失败,停止所有用例的执行