How to run an external SWF inside a Flex Application? - actionscript-3

EDIT: Due to the answer I change the code posted. I've added the Security.allowDomain("*") line and that line throws me an error. So, how can that be made?
I want to run an Action Script 3.0 Application into a Flex Application. To do this I've done the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication windowComplete="loadSwfApplication()" xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private function loadSwfApplication()
{
// The next line throws me an error.
Security.allowDomain("*");
var urlRequest:URLRequest = new URLRequest("path/to/the/application.swf");
swfLoader.addEventListener(Event.COMPLETE, loadComplete);
swfLoader.load(urlRequest);
}
private function loadComplete(completeEvent:Event)
{
var swfApplication:* = completeEvent.target.content;
swfApplication.init(); // this is a Function that I made it in the Root class of swfApplication
}
]]>
</mx:Script>
<mx:SWFLoader id="sfwLoader"/>
</mx:WindowedApplication>
The problem is that in the calling of swfApplication.init(); the AIR Player throws me an exception:
Security sandbox violation: caller file:///path/to/the/application.swf cannot access Stage owned by app:/SWFApplicationLoader.swf.
This is because somewhere in application.swf I use the stage like this:
if (root.stage != null)
root.stage.addEventListener(Event.REMOVED, someFunction);
root.stage.stageFocusRect = false;
How can I load this swf application and USE the stage without any problems?

You can try to load your SWF temporarily into a ByteArray and then load it with your SWFLoader.
Don't forget to set allowCodeImport to true since your SWF has as code inside.
Of course be sure that your loaded swf is secure enough for your application since it will have access at all your property.
private function loadSwfApplication():void {
// load the file with URLLoader into a bytearray
var loader:URLLoader=new URLLoader();
// binary format since it a SWF
loader.dataFormat=URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onSWFLoaded);
//load the file
loader.load(new URLRequest("path/to/the/application.swf"));
}
private function onSWFLoaded(e:Event):void {
// remove the event
var loader:URLLoader=URLLoader(e.target);
loader.removeEventListener(Event.COMPLETE, onSWFLoaded);
// add an Application context and allow bytecode execution
var context:LoaderContext=new LoaderContext();
context.allowCodeImport=true;
// set the new context on SWFLoader
sfwLoader.loaderContext = context;
sfwLoader.addEventListener(Event.COMPLETE, loadComplete);
// load the data from the bytearray
sfwLoader.load(loader.data);
}
// your load complete function
private function loadComplete(completeEvent:Event):void {
var swfApplication:* = completeEvent.target.content;
swfApplication.init(); // this is a Function that I made it in the Root
// class of swfApplication
}

If they are being loaded from different domains you are going to have to add a security exception - http://livedocs.adobe.com/flex/3/html/help.html?content=05B_Security_08.html
if its being run locally youre probably going to have to add them to the list of trusted files or folders in the settings manager - http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html#117502

Assuming that the external SWF is also in the application directory, you could try loading it using the app:/ scheme:
var urlRequest:URLRequest = new URLRequest("app:/path/application.swf");
That may put it into the same security context as the main application.

One thing you may want to consider is that if you are trying to run a SWF from inside your application directory in AIR, AIR restricts execution of files. If you copy the file to a temp file and the run it (along with allowLoadBytesCodeExecution set to true) then it works.
var file:File = File.applicationDirectory.resolvePath("myFile.swf");
this.tmpFile = File.createTempDirectory().resolvePath("myFile.swf");
file.copyTo(this.tmpFile);
imagePreview.loaderContext = lc;
imagePreview.source = tmpFile.url;

it won't work for Flex Projectors.
Only we use SWFLoader and LocalConnection because they can communicate between external swf and main swf. Thanks for support!
Can you read my tutorial from Adobe's Forum
It is very better than MovieClip or Object-Callers
Thank for resolved solution :)
Best regards, Jens

Related

load unknown number of external images without XML

I need to know how to load unknown number of images from external folder without using XML
help me please,
thank you
So from your comments I'm assuming this is an AIR Application, so you can access the filesystem via File class.
First of all, you need to get a File object that points to your folder, the easiest way is to hardcode it. A slightly more complex approach would involve opening a dialog, where the user can select his desired folder (using File.browseForOpen).
Let's take the easy route and define a constant path to the folder, here it's a folder called "images" in the users documents folder:
File imageFolder = File.documentsDirectory.resolvePath("images");
Once we have a folder instance, we can use the getDirectoryListing method to list all files within that folder. Here's an example:
// create a vector that will contain all our images
var images:Vector.<File> = new Vector.<File>();
// first, check if that folder really exists
if(imageFolder.exists && imageFolder.isDirectory){
var files:Array = imageFolder.getDirectoryListing();
for each(var file:File in files){
// match the filename against a pattern, here only files
// that end in jpg, jpeg, png or gif will be accepted
if(file.name.match(/\.(jpe?g|png|gif)$/i)){
images.push(file);
}
}
}
// at this point, the images vector will contain all image files
// that were found in the folder, or nothing if no images were found
// or the folder didn't exist.
To load the files into your application, you can do something like this:
for each(var file:File in images){
// use a FileStream to read the file data into a ByteArray
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
var bytes:ByteArray = new ByteArray();
stream.readBytes(bytes);
stream.close();
// create a loader and load the image into it
var loader:Loader = new Loader();
// use the loadBytes method to read the data
loader.loadBytes(bytes);
// you can add the loader to the scene, so that it will be visible.
// These loaders will all be at 0, 0 coordinates, so maybe change
// the x and y coordinates to something more meaningful/useful.
this.addChild(loader);
}
Can you elaborate a little bit better the question? If it's a user action (i.e. the user needs to upload some photos) I'd use the File API - you can see examples here - otherwise, if it's from the server side I'd use a PHP or Phyton script.
Assuming that your application is Air (Desktop application), this code will be useful:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
public function init():void{
var fs:FileStream = new FileStream();
var f:File = new File("c:/imgTest.jpg");
var b:ByteArray = new ByteArray();
fs.open(f, FileMode.READ);
fs.readBytes(b,0,fs.bytesAvailable);
idImg.source = b;
fs.close();
}
]]>
</mx:Script>
<mx:Image id="idImg" width="100%" height="100%"/>
</mx:WindowedApplication>
Place an image in c:/imgTest.jpg. Note that this image is outside from your project path.
You have other options to load images, but these must be accessible by URL, or should be in the path of the project.
Here a links that will be usefull for load images in Flex Air and Web:
Working with File objects in AIR
Image as ByteArray in Flex
Image Control
Programatically load images in Flex.
Note: i tried only with JPG files, i do not know if this works with other types.

Load External Swf From Link [As3]

I am trying to call a swf from a link in as3. I searched on internet and i used this code
var my_Loader:Loader = new Loader();
var my_url:URLRequest=new URLRequest("http://gurselgunacar.web44.net/flash/yalitimhesabi.swf");
my_Loader.contentLoaderInfo.addEventListener(Event.COMPLETE, finishLoading);
my_Loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
my_Loader.load(my_url);
function finishLoading(loadEvent:Event) {
addChild(loadEvent.currentTarget.content);
}
function errorHandler(errorEvent:Event):void {
trace("file missing");
}
as3 call link but i cant do anything in swf. In output flash give security error. And i tried crossdomain.xml thing and it didnt work :S
The file http://gurselgunacar.web44.net/crossdomain.xml does not exists. You should create one.
The Loader will always look for a crossdomain.xml file at the target server.
Humm. Try to add these Security things:
Security.allowDomain("*");
Security.loadPolicyFile("http://gurselgunacar.web44.net/crossdomain.xml");
And use this in the URLRequest:
var my_url:URLRequest=new URLRequest("http://gurselgunacar.web44.net/flash/yalitimhesabi.swf?" + new Date().getTime()); //this will avoid caching old swf.
I tested on a EXE projector and it seems to work.

How to access variables of the 'main' SWF from a loaded SWF by SWFLoader?

I'm working on a website built in Flex, but the SWF file after compiling is very large. The websites has multiple pages.
So I thought to create a new MXML project for every new page and load it with SWFLoader.
I've found this example:
public function extSwfLoaded(evt:Event):void {
var sysmgr:SystemManager = (extSwf.content as SystemManager);
sysmgr.addEventListener(FlexEvent.APPLICATION_COMPLETE, function(event:FlexEvent):void {
var sysmgr:SystemManager = (event.currentTarget as SystemManager);
var swfApp:Application = (sysmgr.application as Application);
}
});
public function gotoPage(page:String):void {
extSwf.addEventListener(Event.INIT, extSwfLoaded);
var now:Date = new Date();
switch(page) {
case "register":
openedPage = "register";
extSwf.load('modules/register.swf?anticache=' + now.getTime());
break;
}
}
And in the MXML:
<mx:SWFLoader id="extSwf" complete="extSwfLoaded(event)" width="100%" />
<s:Label text="Register" useHandCursor="true" buttonMode="true" click="gotoPage('register')" />
This works perfect. The content of modules/register.swf is showed at the place of the extSwf SWFLoader.
But: I've no idea how to interact with the 'main' SWF and the loaded SWF file.
I have some global variables that I want to send to every loaded SWF file
(and some variables that I want to send from the loaded SWF file to the 'main' SWF file).
A website said that I can send these variables by loading modules/register.swf?var1=hi&var2=hello, but someone who can see the HTTP headers (for example with Live HTTP Headers in Firefox) can see all these variables.
So, is it possible to load a SWF file and send them some variables? And when I have a new global variable, I don't have to open and edit and recompile every MXML project?
Thank you very much!
It looks like this can show the variables of my 'main' MXML.
import mx.controls.Alert;
import mx.core.FlexGlobals;
Alert.show(FlexGlobals.topLevelApplication.myvar);
And for using public functions:
FlexGlobals.topLevelApplication.myFunction();
I just needed the right keywords (top level application) to search for it on the internet.

How to get all definitions in an ApplicationDomain of a loaded SWF?

When you load a SWF into another, the loader SWF can get specific definitions from the loaded SWF using ApplicationDomain.getDefinition(name:String). For example:
package
{
// ... imports
public class SWFLoader extends Sprite
{
private var loadedAppDomain:ApplicationDomain;
public function SWFLoader()
{
var request:URLRequest = new URLRequest("test.swf");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTestLoadComplete);
loader.load(request);
}
private function onTestLoadComplete(event:Event):void
{
var loaderInfo:LoaderInfo = LoaderInfo(event.target);
loadedAppDomain = loaderInfo.applicationDomain;
// Here we can get ANY defined symbol (class, namespace or function according to Adobe Flash help)
var someSymbolClass:Class = Class(loadedAppDomain.getDefinition("SomeSymbol"));
var someSymbolSprite:Sprite = Sprite(new someSymbolClass());
addChild(sprite);
}
}
}
How can I get all of the definitions in a SWF, without specifying each explicitly?
As of Flash Player 11.3, you can use ApplicationDomain.getQualifiedDefinitionNames().
See the official documentation for the method and this blog post about the Flash Player release.
EDIT: This is the quickest solution to your problem : http://www.bytearray.org/?p=175
Hi, you could use this library : https://github.com/claus/as3swf/wiki/
Don't have the time to do deeper test, but here is what i found :
1 - I have created a .swf containing in the library 2 exported MC, $Test and $Test2
2 - Once the .swf loaded by a Loader, i run this code :
var swf : SWF = new SWF(loader.contentLoaderInfo.bytes);
trace(swf);
3 - In the output you'll notice theses lines :
[76:SymbolClass]
Symbols:
[0] TagID: 2, Name: $Test2
[1] TagID: 1, Name: $Test
I think that there is a way to obtain this info directly thru the library API
You have to put the loaded SWF in the current ApplicationDomain.
Use ApplicationDomain.currentDomain to do that, on the ContextLoader info.
loader.load(request, new ContextLoader(false, ApplicationDomain.currentDomain));
It should work.
Following from the answer I received from a previous question I asked here a few days ago (it's about SWC , but in your case, it doesn't really make a difference )
Working with SWCs - getDefinitionByName issue
If both SWFs share the same ApplicationDomain, you should be able to access the loaded SWF classes directly by doing this:
//provided that SomeSymbol extends Sprite...
var someSymbolSprite:Sprite =new SomeSymbol();
On the other hand, you won't be able to do this
var SomeSymbol:Class = getDefinitionByName("SomeSymbol");
unless you create a library of objects from the loaded SWF
var ssym:SomeSymbol;
Check the above link for more details.

Saving XML file in AS3 is possible

var xml:XML = <myXml>
<item prop="1" />
<item prop="2" />
</myXml>;
I need to save as xml file in local harddisk(project directory).
Is it possible to save in as3 itself?
I threw this together, and sure enough you can save to .XML using the following as a minimalist example.
package com.hodgedev.xmlcreator
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.ByteArray;
import flash.net.FileReference;
/**
* ...
* #author Brian Hodge (brian#hodgedev.com)
*/
public class Main extends Sprite
{
private var _xml:XML;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//Calling the save method requires user interaction and Flash Player 10
stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
_xml= <xml>
<test>data</test>
</xml>;
}
private function _onMouseDown(e:MouseEvent):void
{
var ba:ByteArray = new ByteArray();
ba.writeUTFBytes(_xml);
//ba.
var fr:FileReference = new FileReference();
fr.addEventListener(Event.SELECT, _onRefSelect);
fr.addEventListener(Event.CANCEL, _onRefCancel);
fr.save(ba, "filename.xml");
}
private function _onRefSelect(e:Event):void
{
trace('select');
}
private function _onRefCancel(e:Event):void
{
trace('cancel');
}
}
}
There are some things to note.
You require Flash Player 10 to use the save method of the FileReference class.
In order to do anything that INVOKES a prompt, Flash requires user interaction like keyboard or mouse input.
In the above I listen for MouseEvent.MOUSE_DOWN on the stage to serve as the USER INTERACTION which is required to invoke the save prompt.
I setup a basic XML structure within the code (this will typically come from and external source and will work fine both ways.
A ByteArray is created and the XML is written to the ByteArray.
The save method of the FileReference class requires a ByteArray and default save name be passed as the two parameters.
I hope this helps.
if you want to store it locally (on the client PC) , you can use a local shared object. Refer to this tutorial
I'm sorry, your question isn't very clear.
Are you asking if you can save a file to the hard drive from within a compile SWF written in AS3?
Or are you asking if you can include a raw XML file in your AS3 project without needing to write it out as a variable?
If you meant the former, no -- not without Adobe AIR. You can save data locally as a SharedObject, but not as an arbitrary file in the file system.
If the latter, then yes -- you must embed the file just as you would embed another resource (such as an image or a sound). However, it looks like there might be a bug in Flash that makes this non-trivial to figure out how to do.
This link might be of help to you.
[Embed(source='../../../../assets/levels/test.xml', mimeType="application/octet-stream")]
public static const Level_Test:Class;
And then to parse the XML:
var ba:ByteArray = (new Levels.Level_Test()) as ByteArray;
var s:String = ba.readUTFBytes( ba.length );
xml = new XML( s );
Apologies if neither of those questions are what you were actually asking.
Cheers!