Javascript throws error when trying to send var to AS3 ExternalInterface - javascript

I know there have been tons of questions about this topic already but none of them have solved my issue, perhaps I am just missing something.
Anyways, here is the deal. I have a happy little html5 game that plays some audio and sound affects etc and it works great in every browser that supports html5. However, those that don't require a flash fallback. No big deal right? Apparently not… I've made a small swf that should accept the mp3 url from JS and then get the mp3 and play it. I have to use this way as there are a lot of audio files and I would like to try and avoid making a swf file for each one.
Here is the AS - I'm using the ExternalInterface to receive the variable from js.
import flash.external.*;
ExternalInterface.addCallback("callFlash", playSound);
function playSound(file:String):void {
var s:Sound = new Sound();
s.load(new URLRequest(file));
s.play();
}
And then my JS to pass the variable:
var flash = $('#fbplayer')[0];
console.log(flash); //returns flash object so jquery is not the issue
flash.callFlash(fallSource);
So theoretically everything should work fine (if I understand ExternalInterface correctly). However, the following error is thrown:
TypeError: flash.callFlash is not a function
flash.callFlash(fallSource);
I can't seem to find where the issue was.
I'm open to any answers or even a completely different way of doing this.
As long as it works as this is holding up the delivery of the project :C
Thanks!

I know this is really old, but I've never had success finding my flash objects properly with jquery. It's better to go with a getElementById. Also, one other crazy thing I ran into with some modern browsers just a couple months ago is that I actually needed to tell flash to wait a frame after initializing any callbacks via ExternalInterface.

Related

how do you allow javascript communications with Flex/Flash/Actionscript

Well here's a problem.
I've got a website with large javascript backend. This backend talks to a server over a socket with a socket bridge using http://blog.deconcept.com/swfobject/
The socket "bridge" is a Flex/Flash .swf application/executable/plugin/thing for which the source is missing.
I've got to change it.
More facts:
file appExePluginThing.swf
appExePluginThing.swf Macromedia Flash data (compressed), version 9
I've used https://www.free-decompiler.com/flash/ to decompile the .swf file and I think I've sorted out what's the original code vs the libraries and things Flash/Flex built into it.
I've used FDT (the free version) to rebuild the decompiled code into MYappExePluginThing.swf so I can run it with the javascript code and see what happens.
I'm here because what happens isn't good. Basically, my javascript code (MYjavascript.js) gets to the point where it does
window.log("init()");
var so = new SWFObject("flash/MYappExePluginThing.swf"", socketObjectId, "0", "0", "9", "#FFFFFF");
window.log("init() created MYappExecPluginThing!!!");
so.addParam("allowScriptAccess", "always");
log("init() added Param!!");
so.write(elId);
log("init() wrote!");
IE9's console (yeah, you read that right) shows
init()
created MYappExecPluginThing!!!
init() added Param!!
init() wrote!
but none of the debugging i've got in MYappExePluginThing.as displays and nothing else happens.
I'm trying to figure out what I've screwed up/what's going on? Is MYappExePluginThing.as running? Is it waiting on something? Did it fail? Why aren't the log messages in MYappExePluginThing.as showing up?
The first most obvious thing is I'm using FDT which, I suspect, was not used to build the original. Is there some kind of magic "build javascript accessible swf thing" in FlashBuilder or some other IDE?
First noteworthy thing I find is:
file MYappExePluginThing.swf
MYappExePluginThing.swf Macromedia Flash data (compressed), version 14
I'm using Flex 4.6 which, for all I know, may have a completely different mechanism for allowing javascript communication than was used in appExePluginThing.swf
Does anyone know if that's true?
For example, when FDT runs this thing (I can compile but FDT does not create a .swf unless i run it) I get a warning in the following method:
private function init() : void
{
Log.log("console.log", "MYappExePluginThing init()");
//var initCallback:String = Application.application.parameters.initCallback?Application.application.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
var initCallback:String = FlexGlobals.topLevelApplication.parameters.initCallback?FlexGlobals.topLevelApplication.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
try
{
ExternalInterface.addCallback("method1Callback",method1);
ExternalInterface.addCallback("method2Callback",method2);
ExternalInterface.call(initCallback);
}
catch(err:Error)
{
Log.log("console.log", "MYappExePluginThing init() ERROR err="+err);
}
}
I got a warning that Application.application was deprecated and I should change:
var initCallback:String = Application.application.parameters.initCallback?Application.application.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
to:
var initCallback:String = FlexGlobals.topLevelApplication.parameters.initCallback?FlexGlobals.topLevelApplication.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
which I did but which had no effect on making the thing work.
(FYI Log.log() is something I added:
public class Log{
public static function log(dest:String, mssg:String):void{
if(ExternalInterface.available){
try{
ExternalInterface.call(dest, mssg);
}
catch(se:SecurityError){
}
catch(e:Error){
}
}
trace(mssg);
}
}
)
Additionally, in MYjavascript.js MYappExePluginThing_init looks like this:
this.MYappExePluginThing_init = function () {
log("MYjavascript.js - MYappExePluginThing_init:");
};
Its supposed to be executed when MYappExePluginThing finishes initializing itself.
Except its not. The message is NOT displaying on the console.
Unfortunately, I cannot find any references explaining how you allow javascript communication in Flex 4.6 so I can check if I've got this structured correctly.
Is it a built in kind of thing all Flex/Flash apps can do? Is my swf getting accessed? Is it having some kind of error? Is it unable to communicate back to my javascript?
Does anyone have any links to references?
If this was YOUR problem, what would you do next?
(Not a full solution but I ran out of room in the comment section.)
To answer your basic question, there's nothing special you should need to do to allow AS3-to-JS communication beyond what you've shown. However, you may have sandbox security issues on localhost; to avoid problems, set your SWFs as local-trusted (right-click Flash Player > Global Settings > Advanced > Trusted Location Settings). I'm guessing this not your problem, though, because you'd normally get a sandbox violation error.
More likely IMO is that something is broken due to decompilation and recompilation. SWFs aren't meant to do that, it's basically a hack made mostly possible due to SWF being an open format.
What I suggest is that you debug your running SWF. Using break-points and stepping through the code you should be able to narrow down where things are going wrong. You can also more easily see any errors your SWF is throwing.
Not really an answer, but an idea to get you started is to start logging everything on the Flash side to see where the breakage is.
Since you're using IE, I recommend getting the Debug flash player, installing it, then running Vizzy along side to show your traces.
Should give you a good idea of where the app is breaking down.
Vizzy
Debug Player

Why CreateJS code not working in firefox?

Have exported my flash cs6 game using createjs using "toolkit for createjs". All sounds exported to directory successfully.
Following code calls sounds
var manifest = [
{src:"sounds/cutter.wav", id:"cutter"}
];
var loader = new createjs.PreloadJS(false);
loader.installPlugin(createjs.SoundJS);
loader.onComplete = handleComplete;
loader.loadManifest(manifest);
function playSound(name, loop) {
createjs.SoundJS.play(name, createjs.SoundJS.INTERRUPT_EARLY, 0, 0, loop);
}
chorme and opera plays sound correctly but firefox.
Thanks in advance :)
I would recommend trying the latest code available at http://www.soundjs.com. You'll also find helpful tutorials and examples that work in firefox. It doesn't offer direct toolkit support, but it can help you understand what the exported code is doing and how to alter it.
My best guess without seeing the code in context is you are trying to call play without waiting for load to complete. This creates a race condition, where sometimes if the sound is cached it will work, and other times it will fail.
It's also possible that it has something to do with the wav encoding. With mp3s we've found you mostly need to stick to default encoding to ensure browsers can actually play the audio. You might also want to consider using mp3 and ogg files for the broadest audio support.
Hope that helps.

SoundManager2 SWF Load Issue

Trying to load Soundmanager2's SWF file from our CDN. I assume I'm running into cross domain flash issues. has anybody done this? it is even possible?
here's what I'm trying...
var allowxdomainscripting = true;
var xdomain = "*";
soundManager.url = 'http://cdn.mycompany.com/inc/soundmanager2.swf';
there's a very obscure reference to this in the documentation, but it's pretty vague...
http://www.schillmania.com/projects/soundmanager2/doc/generated/src/SoundManager2_AS3.html
any help is appreciated.
I ran into this as well at one point. SoundManager2 now comes with cross-domain versions of the swf files.
They are zipped up in swf/soundmanager2_flash_xdomain.zip
https://github.com/scottschiller/SoundManager2/tree/master/swf
Simply unzip and replace with the standard .swf files provided with SoundManager2 and your problem should go away.
THANK YOU VERY MUCH!
I stumbled upon this answer by total chance after wasting a couple of hours trying to get SM2 SWF embed to work.
I'm going to "revive" this to add a few keywords so Google indexes this answer... Maybe the next person trying to embed SoundManager2 SWF in a cross-domain environment gets it done a little quicker than I did :)
The error I was getting upon flash initialization was: Error calling method on NPObject
On the JS side, this was the code that broke everything:
// attempt to talk to Flash
flash._externalInterfaceTest(false); <- KABOOM!
NPObject errors might have many meanings, but more often than not (in our environment) it means: You're trying to call the ExternalInterface through JS on a flash movie hosted on a different domain.
After a while I popped open SoundManager2 ActionScript 3 code and saw this:
public var allow_xdomain_scripting:Boolean = false;
public var xdomain:String = "*";
[... other stuff ...]
if (allow_xdomain_scripting && xdomain) {
Security.allowDomain(xdomain);
version_as += ' - cross-domain enabled';
}
Of course that means that the movie that you might be using (no matter if it's debug or not) will not be accessible from a different domain (a CDN, or whatever).
The solution was –as stated in #amlutz160's answer– to use the files contained in swf/soundmanager2_flash_xdomain.zip, which are compiled with allow_xdomain_scripting = true.
Posting this is quite embarrassing, and the solution is obvious, but I lost quite a bit of time with this and AFAIK the contents of that mysterious zip file are not documented anywhere (I found a tangential mention on SM2 forums).
PS: I'm forwarding this answer to Scott Schiller so maybe he can update SoundManager2 docs a little bit :P
Regards!

call Actionscript method from JS without loading SWF

Well yeah, it sounds funny, but all I want is to read the value of Capabilities.version to get the right version of the Flash player? I have tried getting the version info from swfObject library, but it doesn't give the complete version info:
http://www.adobe.com/devnet/flashplayer/articles/swfobject.html
FP version info have 4 numbers: major, minor, release and build. I couldn't find an API which can give me all four on all browsers without loading SWF. Hence I am looking for help here.
SWFObject has a detection function built into it and for the most part it is cross-browser capable.
The function name is getFlashPlayerVersion
It returns an object with 3 attributes major, minor,release
[EDIT]
SWFObject also has a function called testPlayerVersion.
I shortened it up for you but I think it gets what you want.
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
alert( doc.getElementsByTagName("body")[0].appendChild(o).GetVariable("$version") )
doc.getElementsByTagName("body")[0].removeChild(o);
Remember this is not browser compliant.
Pretty sure you need to test for plugin or active x also.
You do not need to load flash to know what is the version of the player.
There for is JS.
http://www.featureblend.com/javascript-flash-detection-library.html

External Javascript Interface on Flash Player not working on CDN (Cloudfront)

I have a flash player with an external javascript interface: reloadData() I'm calling that function via Javascript when editing information on the page - basically to keep data on the page and in the player in synch.
The reloadData() function works fine when the player is hosted locally. When we move it to the CDN (Amazon Cloudfront), the player loads successfully, but the external javascript interface no longer works - console.log(player) reveals the following:
<object type=​"application/​x-shockwave-flash" data=​"[our_cloudfront_url].swf" width=​"920" height=​"404" id=​"player" style=​"visibility:​ visible;​ ">​
Uncaught TypeError: Object #<an HTMLObjectElement> has no method 'reloadData'
I know there are a lot of things that behave differently when working with items on a CDN, but I'm wondering if anyone has experienced a similar problem and figured out a fix.
Oh, yeah...we're using a CNAME to point to the cloudfront distribution (buildid.ourdomain.net => distributionid.cloudfront.net)
Well, we figured this one out. Two things are necessary:
On the page when embedding the swf: allowScriptAccess="always"
In the swf itself: System.security.allowDomain("ourdomain.com")
I guess this is sort of obvious, but I figured I'd post it here in case some other poor lost soul such as myself is having the same problem.

Categories