Handle VerifyError: Error #1014 when loading swfs using AS3 - actionscript-3

We are making a system that has a main swf for the application, and loads separate tools from separate swfs -- there will be versioning issues in the future since the separate swfs are coming from a cms (especially now since we're still developing, but also in the future when other developers might create an incompatible tool). I'm trying hard to prevent them as much as possible but I'd really like to be able to display a message to the user of the system when an incompatible swf is loaded.
This would mean that we need to catch that VerifyError or at least determine the loading failed for some reason - I've got no idea how to handle that at the moment. I suspect it might be possible using 10.1 and the uncaughtError system, but we are currently targeting flash player 10. Does anyone have a good idea? (we are already handling IOErrorEvent.IO_ERROR)
UPDATE: I've built a solution that scans the bytecode before importing, looks like that will work. I'll post the solution later.

The best way to do this is by using one of the libraries bhups suggested. I used senocular's for the next example.
Also, because the senocular's library provides only basic operations for the parsed SWF you may need the SWF Format Spec (adobe.com/devnet/swf/pdf/swf_file_format_spec_v10.pdf) to get the info you want out of the loaded SWF.
The next example lists all the class names from a loaded SWF:
package swf
{
import flash.events.Event;
import flash.net.URLRequest;
import flash.net.URLStream;
import flash.utils.ByteArray;
import flash.utils.Endian;
import swf.SWFReader;
public class GetSWFInfo
{
private var swfInfo:SWFReader;
public function GetSWFInfo()
{
var urlRequest:URLRequest = new URLRequest("theswf.swf");
var loader:URLStream = new URLStream();
loader.load(urlRequest);
loader.addEventListener(Event.COMPLETE, onComplete);
}
public function onComplete(e:Event):void {
var recivedByteArray :ByteArray = new ByteArray();
URLStream(e.currentTarget).readBytes(recivedByteArray);
//create a new instance of SWFReader
swfInfo = new SWFReader();
//readTag it's a callback function that will be called when a tag is read during the SWF parse process.
//read more on tags in the SWF specification document
swfInfo.tagCallback = readTag;
//start parsing
swfInfo.parse(recivedByteArray);
}
public function readTag(tag:uint, bytes:ByteArray):void {
//76 it's the tag type for SymbolClass tag
//read more in the SWF specification document
if (76 == tag) {
var classesArray:Array = new Array();
var symbolsNumber:uint = 0;
var currentId:uint = 0;
bytes.endian = Endian.LITTLE_ENDIAN;
//read the symbols Number
//again read more in the SWF specification document
symbolsNumber = bytes.readShort();
bytes.position = 4;
while (true) {
var i:uint = bytes.position;
//every string name ends with a null byte
//again read more in the SWF specification document
while(bytes[i] != 0) i++;
var readAmount:uint = i - bytes.position;
classesArray.push(bytes.readUTFBytes(readAmount));
//the last ID is always the base class Id, and it's 0
currentId=bytes.readUnsignedShort();
bytes.position++;
if (currentId==0) {
break;
}
}
//this two should be equal
trace(classesArray.length + 1);//the number of elements in the classesArray
trace(symbolsNumber);//the number of classes retrived from the SWF
//list the names
var name:String;
for each (name in classesArray) {
trace(name);
}
//now you have an array with all the class names that you can use to compare
}
}
}
}

I did misunderstand what you are trying to do.
Well, actually, I guess there is no handler for verify error and to detect it, you have to fight with byte-codes.
By the way, I have and idea which is not the very answer for your question but may helps you.
a 3rd party swf is depending on a class that should be in my swf -- if that class is missing I get the VerifyError.
From this point, I can advice that if you link the 'missing class' into your swf and load the 3rd party swf into ApplicationDomain.currentDomain or new ApplicationDomain(ApplicationDomain.currentDomain), you can avoid the 'Verify Error'.
(This is because the flash player will find the diffinition of the missing class in the parent swf.)
Here is my sample code which loads a swf with verify error(http://teionclub.com/test/xml/main.swf).
Avoiding VerifyError - wonderfl build flash online

I think there is a way to workaround this issue.
load the swf using a URLLoader or
URLStream into a ByteArray.
Use any open source library for parsing SWF binary like this or
this.
check if it verifies that the whole byte array represents valid
SWF file.
If above test succeeds then load this ByteArray into loader using
loadBytes method.
Else show user that this is not working.
Disclaimer: A binary file can be a valid SWF still might not be render-able, but with this you can discard all the invalid SWFs or any other formats whose extension are changed to swf.

I've worked with that kind of application in the past but I think it would be better to fix the SWF loaded rather than handling VerifyError. VeriyError indicates that the SWF loaded is corrupted or malformed.
And it's natural that the SWF itself is malformed rather than that the SWF is corrupted during the transfer. I guess you are trying to load png or other format named ".swf" or the SWF is generated by some software other than Flex compiler or Flash such as swfmill(In the latter case, there would be a bug in that software).

To finally answer my own question, this is the utility class I've been using to detect possible errors. I load the SWF as a bytearray and scan the contents before loading it as an actual MovieClip.
As you can see my code heavily depends on the com.segfaultlabs.swfutils package
Important: I've stopped using this method of preventing errors, opting for the more manual approach of checking the files by actually trying to load them and see if they work. This is because the utility is not complete, and my current knowledge of the ABC format is not good enough to make sure I can develop a check that will always be correct.
Posting my code here as starting point for others who want to take a stab at it :-)
package nl.ijsfontein.utils
{
import com.segfaultlabs.swfutils.ABC.ABCCPool;
import com.segfaultlabs.swfutils.ABC.ABCClass;
import com.segfaultlabs.swfutils.ABC.ABCInstance;
import com.segfaultlabs.swfutils.ABC.ABCMethodInfo;
import com.segfaultlabs.swfutils.ABC.ABCMultiname;
import com.segfaultlabs.swfutils.ABC.ABCParser;
import com.segfaultlabs.swfutils.ABC.ABCTraitConstSlot;
import com.segfaultlabs.swfutils.ABC.ABCTraitsInfo;
import com.segfaultlabs.swfutils.ABC.ABCinfo;
import com.segfaultlabs.swfutils.SWFDataInput;
import com.segfaultlabs.swfutils.SWFFile;
import flash.system.ApplicationDomain;
import flash.utils.ByteArray;
/**
* utility to see which classes a swf uses, but doesn't contain itself
* - this can be used to detect possible VerifyErrors before they happen.
*/
public class SwfDependencyUtil
{
public function SwfDependencyUtil()
{
}
// return null if ok, or name of needed class if external depencendy
private static function resolveSuper(abc:ABCinfo, superClass:String):String
{
//if (superClass.indexOf("flash.") == 0 || superClass.indexOf("*") == 0 || superClass.indexOf("Object") == 0)
if (superClass.indexOf("*") == 0)
{
trace(' super: ' + superClass + " (ignore)");
}
else
{
var superClassClass:ABCClass = null;
for each ( var c:ABCClass in abc.classes )
{
if (c.name == superClass)
{
superClassClass = c;
}
}
if (superClassClass)
{
trace(' super: ' + superClass + " (resolved internally)");
return resolveSuper(abc, superClassClass.iref.base);
}
else
{
trace(' super: ' + superClass + " (NOTFOUND)");
return superClass;
}
}
return null;
}
/*
* checks: classes, superclasses, static variables, member variables
* TODO: function arguments
* won't check: method bodies
*
* TODO: refactor to multiple methods
*/
public static function getDependencies(swfBytes:ByteArray):Array /* of String */
{
var result:Array = [];
swfBytes.position = 0;
var swfr:SWFFile = new SWFFile(swfBytes);
var arr:Array;
if ( swfr.compressed )
{
swfr.dataInput = swfr.uncompress();
swfr.readHeader();
};
arr = swfr.parseTags();
if ( arr[82] != null )
{
var abc:ABCinfo = new ABCinfo();
var cpool:ABCCPool = new ABCCPool();
var abcparse:ABCParser = new ABCParser();
abcparse.readMethodBytes = true;
abcparse.readExceptions = false;
for ( var j:int = 0; j < arr[82].length; j += 1 )
{
swfr.dataInstance.position = arr[82][j].position;
try
{
abcparse.parse( swfr.dataInput as SWFDataInput, abc, cpool, new FakeLogger() );
for each ( var c:ABCClass in abc.classes )
{
trace('class:', c.name);
var superClass:String = c.iref.base;
var dependency:String = resolveSuper(abc, superClass);
if (dependency)
{
result.push(dependency);
}
for each (var mn:ABCMultiname in c.iref.interfaces)
{
var interfaceName:String = mn.nsset[0] != "" ? mn.nsset[0] + "::" + mn.name : mn.name;
var interfaceDependency:String = resolveSuper(abc, interfaceName);
if (interfaceDependency)
{
result.push(interfaceDependency);
}
}
for each (var ti:ABCTraitsInfo in c.traits)
{
if (ti is ABCTraitConstSlot)
{
var constName:String
if (QName(ABCTraitConstSlot(ti).type).uri)
{
constName = QName(ABCTraitConstSlot(ti).type).uri + "::" + QName(ABCTraitConstSlot(ti).type).localName
}
else
{
constName = QName(ABCTraitConstSlot(ti).type).localName
}
var constDependency:String = resolveSuper(abc, constName);
if (constDependency)
{
result.push(constDependency);
}
}
else if (ti is ABCMethodInfo)
{
trace('method', ABCMethodInfo(ti).name);
} else
{
trace(ti);
}
// trace(ti.type.localName);
}
// const (static?) members: c.traits
}
for each ( var i:ABCInstance in abc.instances )
{
// trace(i);
for each (var instanceTi:ABCTraitsInfo in i.traits)
{
if (instanceTi is ABCTraitConstSlot)
{
trace('instance:', createClassNameFromQname(ABCTraitConstSlot(instanceTi).type));
var csdep:String = resolveSuper(abc, createClassNameFromQname(ABCTraitConstSlot(instanceTi).type));
if (csdep)
{
result.push(csdep);
}
}
else if (instanceTi is ABCMethodInfo)
{
}
else
{
trace('unexpected trait type');
}
}
}
abc.dispose();
}
catch ( e:Error )
{
trace( " Error ",e.getStackTrace() );
};
};
cpool.dispose();
}
else
{
trace("No DoABC block... ;(");
}
return result;
}
private static function createClassNameFromQname(qn:QName):String
{
var result:String
if (qn.uri)
{
result = qn.uri + "::" + qn.localName
}
else
{
result = qn.localName
}
return result;
}
public static function getUnsatisfiedDependencies(swfBytes:ByteArray):Array /* of String */
{
var result:Array = [];
var dependencies:Array = SwfDependencyUtil.getDependencies(swfBytes)
for each (var dependency:String in dependencies)
{
if (ApplicationDomain.currentDomain.hasDefinition(dependency))
{
trace('ok: ', dependency);
}
else
{
trace('ERROR: unsatisfied dependency: ', dependency);
result.push(dependency);
}
}
return result;
}
}
}

Related

AS3: Reusing URLLoader, URLRequest, and URLVariables instances

My Flash project uses URLLoader.load a lot to load content from a web server and post to a php page. Should I reuse my URLLoader, URLRequest, and URLVariables instances, or should I create new ones each time? If I should create new ones each time, do the old ones need to be disposed of somehow?
You should most certainly never ever ever reuse any instances related to external operations and you should thoroughly dispose of them the very moment you don't need them. The overhead of Garbage Collector (GC) working on these objects is literally nothing next to the nightmare mess you might get into once your external operations collide via sharing the same operational instances.
URLVariables and URLRequest do not need any special treatment, just set null to any variables referencing them and ensure that method, where they were assigned to local variables, do not produce any function closures. Well, set URLRequest.data to null to break this reference.
URLLoader, on the other hand, needs to be pushed around a bit:
If URLLoader.data is a ByteArray, then you should ByteArray.clear() it (unless you need it).
Set the URLLoader.data to null.
Initially subscribe all error handlers with weak references (fifth argument of addEventListener set to true) and don't unsubscribe them. Weak keys won't affect the GCs judgement while keeping the subscriptions might save you from occasional Unhandled Error Event case.
Certainly do unsubscribe all non-error handlers.
In all the handlers, first check if Event.target is a valid URLLoader instance to avoid handling an event from a dead/disposed URLLoader.
Call URLLoader.close() just in case. Yes, after all of above is done.
Below is the class I use to load things in a simple way. It is built on the same principles I listed above. It allows loading text/binary data and also provides some proof against unstable network: you can set the repeatCount argument to higher values to provide fail-safe loading if you know that requests tend to fail sometimes.
Usage:
// Load binary data over unstable network.
DataFiles.load("data.dat", onData, true, 10);
// Load XML file as text over a stable network or from the local storage.
DataFiles.load("setup.xml", onSetup);
function onData(source:ByteArray):void
{
if (!source)
{
// Loading failed. Error case.
}
else
{
// File is loaded normally.
}
}
function onSetup(source:String):void
{
try
{
var aSetup:XML = new XML(source);
// Process loaded XML normally.
}
catch (fail:Error)
{
// The source is either null or an invalid XML string.
// Loading is failed, basically. Error case.
}
}
Implementation:
package simplify
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
public class DataFiles
{
static private var list:Vector.<DataFiles> = new Vector.<DataFiles>;
static public function load(url:String, handler:Function, binary:Boolean = false, repeatCount:int = 1):void
{
var aLoader:DataFiles = new DataFiles;
aLoader.url = url;
aLoader.binary = binary;
aLoader.handler = handler;
aLoader.repeatCount = repeatCount;
list.push(aLoader);
aLoader.start();
}
private var url:String;
private var binary:Boolean;
private var handler:Function;
private var loader:URLLoader;
private var repeatCount:int;
private function start():void
{
loader = new URLLoader;
if (binary) loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
loader.load(new URLRequest(url));
}
private function destroyLoader():void
{
if (!loader) return;
loader.removeEventListener(Event.COMPLETE, onComplete);
var aDead:Loader = loader;
loader = null;
aDead.data = null;
aDead.close();
}
private function onComplete(e:Event):void
{
if (e.target != loader) return;
var aResult:* = loader.data;
var aHandler:Function = handler;
destroy();
destroyLoader();
aHandler(aResult);
}
private function onError(e:IOErrorEvent):void
{
if (e.target != loader) return;
destroyLoader();
repeatCount--;
if (repeatCount >= 0)
{
start();
}
else
{
var aHandler:Function = handler;
destroy();
aHandler(null);
}
}
private function destroy():void
{
var anIndex:int = list.indexOf(this);
if (anIndex > -1) list.splice(anIndex, 1);
handler = null;
url = null;
}
}
}

How to exclude Library item from compiling if it is not present AS3

I have a MovieClip in Library , which I am loading dynamically through addChild method.
The problem I am facing is :--
I have a Main Class which runs with several other classes and several FLA's.
Main Class calls a sub class function which in return calls the code in a frame of a FLA which loads this object from Library.
This object is not present in all FLA's, thats where I am getting stuck, getting Compile time error.
Tried checking through this but failed :(
var classExist:Boolean = isClassExists("CTRL_ALARM");
function isClassExists(className:String, domain:ApplicationDomain = null):Boolean
{
var res:Boolean;
if(domain)
{
res = domain.hasDefinition(className);
}
else
{
// res = getDefinitionByName(className);
//or the same
res = ApplicationDomain.currentDomain.hasDefinition(className);
}
trace(res);
return res;
}
Is there any way I can duplicate objects on Stage in as3, or how can I restrict an object from being compiled if it is not present in Library?
Try the following. If all of your SWFs are in the same sandbox, it might just work:
import flash.utils.getDefinitionByName;
var AlarmClass:Class = getDefinitionByName("CTRL_ALARM");
var anAlarm:DisplayObject = new AlarmClass;
Then, to make it work even with sandbox restrictions, you may seek for the definition you want through the loaded SWFs:
// This should contain Loader objects with your loaded SWFs.
var aList:Array;
for each (aLoader:Loader in aList)
{
// Get reference to loaded app domain.
var aDomain:ApplicationDomain = aLoader.contentLoaderInfo.applicationDomain;
// Check if such a class is in that SWF.
if (aDomain.hasDefinition("CTRL_ALARM"))
{
var AlarmClass:Class = aDomain.getDefinition("CTRL_ALARM");
var anAlarm:DisplayObject = new AlarmClass;
break;
}
}

AS3 - Multiple Images Turn On/Off Not Working with Second MovieClip

Ok this has been driving me insane. My AS3 knowledge isn't the best in the world, but I'm trying to work out where I'm going wrong with all of this.
Basically, What I'm trying to do is at certain times, make visible/invisble two different MovieClips.
The weird thing is, one is responding. And the other isn't. They are both identical aside from jpeg contents and names. Is there a setting I'm missing? Both have matched MovieClip names and Instance names... but when I use the code below, HOP1 turns off/on, but HOP2 refuses to! Am i just missing some stupidly obvious preference?
I will mention, I'll have to modify the code to work with two different MovieClips, but right now I just want both files to turn off!
package {
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.utils.Timer;
import com.boo.CustomDate;
import com.boo.ScreensaverSimple;
public class Generic extends MovieClip {
// This is where you can set the Hour of Power time start and end time (in 24 hour format e.g. 1330 for 1:30pm)
// If there is no hour of power, simply set both numbers to 0
private var HourOfPowerStartTime:Number = 0;
private var HourOfPowerEndTime:Number = 0;
private var ss:ScreensaverSimple;
public var time_check_timer:Timer;
private var delay_add_timer:Timer;
public function Generic() {
Mouse.hide();
ss = new ScreensaverSimple;
ss.setScreensaver(screens);
HOP2.visible = false;
time_check_timer = new Timer(1000);
time_check_timer.addEventListener(TimerEvent.TIMER, checkTime);
delay_add_timer = new Timer(1,1);
delay_add_timer.addEventListener(TimerEvent.TIMER, addAllChildren);
delay_add_timer.start();
}
public function addAllChildren(evt:TimerEvent=null):void {
delay_add_timer.removeEventListener(TimerEvent.TIMER, addAllChildren);
delay_add_timer.stop();
delay_add_timer = null;
time_check_timer.start();
checkTime();
}
public function checkTime(evt:TimerEvent=null):void {
checkHOP2();
}
private function checkHOP1():void {
if(HourOfPowerStartTime == 0 && HourOfPowerEndTime == 0)
{
if(HOP2.visible == true)
{
HOP2.visible = false;
}
return;
}
var CurrentTime:Number = CustomDate.return24HourNumber();
if(CurrentTime >= HourOfPowerStartTime && CurrentTime <= HourOfPowerEndTime)
{
if(HOP2.visible == false)
{
HOP2.visible = true;
}
}
else
{
if(HOP2.visible == true)
{
HOP2.visible = false;
}
}
}
}
}
if(HOP2.visible == true)
{
HOP2.visible = false;
}
Fist thing the if condition is complete redundant here. If you think about it, those lines work exactly the same as this one alone:
HOP2.visible = false;
Also (HOP2.visible == true) would be exactly the same as (HOP2.visible) and also you can assign value of condition check directly to variable. Generally you can reduce your function to:
private function checkHOP1():void {
HOP2.visible = (HourOfPowerStartTime || HourOfPowerEndTime);
if (!HOP2.visible) return;
var CurrentTime:Number = CustomDate.return24HourNumber();
HOP2.visible = (CurrentTime >= HourOfPowerStartTime && CurrentTime <= HourOfPowerEndTime);
}
Then I see you call to checkHOP2() :
public function checkTime(evt:TimerEvent=null):void {
checkHOP2();
}
but I don't see the checkHOP2() function defined in code you gave.
Similarly I don't see form where you call your checkHOP1() function you have posted. And also I don't get why change HOP2 instance inside function named checkHOP1() . Is it suppose to be some kind of obfuscation?

How to detect Adobe Flash crash reason?

Edit02: The reason why the flash crash because the wrong distance cause the programm to divide something by 0 - well I found the error on my own, but my question still is, is there something like a crashreport that you can add / edit?
Edit: I found the bug in the script its located here
if(baseVerticies[vertX]-boneObj.x < 0){
distance = distance*-1;
}
at one point it generates the wrong distance, but this is not what the program causes to crash, I know how to solve the bug but it would still be interesting how to add functions to detect flash crash reasons
OLD:
Hey I am currently testing the CS6 Flash demo but one function always kills flash and I dont get any error messages, so my question is ... how can I hunt the bug down?
The only things I know: it crashes when I call a certain function (the one which I posted below) - it doesnt crash on the first call ... more like on the third or second
is there any way to add debugEvents or something als that would be usefull to track the error?
thx in advance =)
public function rotateBone(boneObj : Bone, point : Point){
//rotates the boneGrafik
boneObj.rotation = (point.x+boneObj.old_rotation)/2;
if(axis == "horizontal"){
var firstV : int = selected_bone*(squares+1)*2;
var lastV : int = selected_bone*(squares+1)*2 + squares*2;
var radius : Number = Math.sqrt((verticies[lastV]-verticies[firstV])*(verticies[lastV]-verticies[firstV])+
(verticies[lastV+1]-verticies[firstV+1])*(verticies[lastV+1]-verticies[firstV+1]));
//will be exectued for every single vertex
for(var s = 0; s<=squares; s++){
var vertX : int = selected_bone * (squares+1) * 2 + s*2;
var distance : Number = Math.sqrt((verticies[vertX]-boneObj.x)*(verticies[vertX]-boneObj.x)+
(verticies[vertX+1]-boneObj.y)*(verticies[vertX+1]-boneObj.y));
//calculates Vector
var rads:Number = boneObj.rotation / 180 * Math.PI;
var p:Point = new Point();
p.x=Math.cos(rads);
p.y=Math.sin(rads);
//baseMesh is used in order to check if the vertex pos is positiv / negative
if(baseVerticies[vertX]-boneObj.x < 0){
distance = distance*-1;
}
verticies[vertX] = boneObj.x + p.x * radius * (distance/radius);
verticies[vertX+1] = boneObj.y + p.y * radius * (distance/radius);
}
}else if (axis == "vertical"){
for(var r = 0; r<=rows; r++){
vertX = r * (squares+1) * 2 + selected_bone * 2;
}
}
updateMesh();
}
I'm not sure what you mean it crashes without exception. Are you testing in the browser? If so, then you could download and install the appropriate Flash debugger player from the list here: http://www.adobe.com/support/flashplayer/downloads.html
This should give you an error window whenever FlashPlayer crashes, which will contain debugging information. It will also write crashes and debugging data to a log file. There's more info on that here: http://helpx.adobe.com/flash-player/kb/configure-debugger-version-flash-player.html
Finally, if you want to catch and handle otherwise unhandled exceptions, you can do that in FP10.1 and later. Here are the Adobe docs about it: http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/events/UncaughtErrorEvent.html, and here is the sample code from that page:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.ErrorEvent;
import flash.events.UncaughtErrorEvent;
import flash.net.URLRequest;
public class LoaderUncaughtErrorEventExample extends Sprite
{
private var ldr:Loader;
public function LoaderUncaughtErrorEventExample()
{
ldr = new Loader();
ldr.load(new URLRequest("child.swf"));
ldr.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorHandler);
}
private function uncaughtErrorHandler(event:UncaughtErrorEvent):void
{
if (event.error is Error)
{
var error:Error = event.error as Error;
// do something with the error
}
else if (event.error is ErrorEvent)
{
var errorEvent:ErrorEvent = event.error as ErrorEvent;
// do something with the error
}
else
{
// a non-Error, non-ErrorEvent type was thrown and uncaught
}
}
}
}

Flash Builder 4 + Flash Professional + FlashVars != WORKING

I have a Flash Builder 4 project that's hooked up to a Flash Professional CS5 FLA.
I do NOT use MXML, and all code is handled directly in Flash Builder. (Flash itself is used simply for the library, and its easier for our artists to use)
Everything's been going along without a hitch, everything runs off of dynamically generated XML from the site the SWF is embedded to. But up until now I've had the XML path hardcoded in the actionscript. I wish simply to not make it so.
I have followed minimum 45 tutorials on getting FlashVars into FB4/As3, and quite simply nothing seems to be working.
Old school < embed > method, using < object > method, and even using swfObject method, simply I cannot seem to access these flashvar properties.
here's the html that i currently have now:
<script>
var flashvars = {
xml: "/mapsystem/xml"
}; // yes that is definitely the correct path, its the same value as when it was hardcoded
$(function() {
swfobject.embedSWF("/flash/map.swf", "map", "960", "885", "10.0.0", "expressInstall.swf", flashvars);
});
</script>
<div id="map">
swfObject Aint Working
</div>
Heres the actionscript (this is in my Document class, first thing)
package
{
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import src.GlobalStage;
import src.Map;
import src.Styles;
public class map extends GlobalStage
{
public var xmlDoc = "map.xml";
public function map()
{
var test:TextField = new TextField();
test.x = 50;
test.y = 50;
test.autoSize = TextFieldAutoSize.LEFT;
test.text = "XML Doc: ";
this.addChild(test);
var test2:TextField = new TextField();
test2.x = 50;
test2.y = 80;
test2.multiline = true;
test2.border = true;
test2.autoSize = TextFieldAutoSize.LEFT;
test2.text = "Parameters: \n";
test2.appendText("Total Parameters: ");
this.addChild(test2);
var _params:Object;
if ( this.loaderInfo.parameters.length != null ) {
_params = this.loaderInfo.parameters;
} else {
// run alt code to init
}
for(var pItem:String in _params) {
test2.appendText("Name: " + pItem + " :: " + _params[pItem] + "\n" );
}
if(_params['xml'] != null) xmlDoc = _params['xml'];
test.appendText(xmlDoc);
var map:Map = new Map(xmlDoc);
Now, when i run this on my local test, nothing shows up as per expected, but when it comes to being on the site itself, with a passed flashvar, the xmlDoc remains "map.xml", my counter tells me there are 0 parameters, and of course nothing shows up in my list of parameters.
I have spent 8 hours trying to get this to work, quite frankly I'm losing hair and sleep over this.
loaderInfo.parameters is an Object, and so the condition in this if statement is never likely to be true (unless your flashVars had a param named 'length'):
if (this.loaderInfo.parameters.length != null) {
So instead of checking if the length is not null, just check if the parameters are not null:
if (loaderInfo.parameters) {
loaderInfo.parameters is an object, and it is never null. What you must do is check for your flashvar's existence like this:
if (loaderInfo.parameters.xml)
{
var xmlPath:String = loaderInfo.parameters.xml
// start using xml
}
else
// run alt code to init
}