Hi I am writing a flex application that has a MainMovie that loads flex programs (ChildMovie) depending on what the user selects in the MainMovie. below is some pseudocode to help me describe my problem hopefully.
class MainMovie{
private var request:URLRequest = new URLRequest();
public function callPHPfile(param:String, loader:URLLoader,
handlerFunction:Function):void {
var parameter:URLVariables=new URLVariables();
parameter.param = param;
request.method = URLRequestMethod.POST;
request.data = parameter;
request.url = php file on server;
loader.addEventListener(Event.COMPLETE, handlerFunction);
loader.load(request);
}
}
Class ChildMovie {
private var loaderInChild:URLLoader = new URLLoader();
public function handlerInChild(e:Event):void {
process data....
loaderInChild.removeEventListerner(Event.COMPLETE, handlerInChild);
}
private function buttonClickHandler(e:Event):void{
Application.application.callPHPfile(param, loaderInChild, handlerInChild)
}
}
I can see that the callPHPfile function is being executed and received xml data from in httpFox, the problem is that the code in the handlerInChild function is not being executed. What am I doing wrong here?
It was a runtime error. I forgot that i uninstalled flash player debugger in firefox and it didn't show. in the handlerInChild function, there is a line
var data:XML = loader.data;
it should be
var data:XML = XML(loader.data);
and the code will run as expected.
Related
I have this code:
public function Json2Me(_urlJSON:String) {
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest();
request.url = _urlJSON;
loader.addEventListener(Event.COMPLETE, onLoaderComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR,informadorIO);
loader.load(request);
}
private function onLoaderComplete(e:Event):void{
var loader:URLLoader = URLLoader(e.target);
JSONEnviado = com.adobe.serialization.json.JSON.decode(loader.data);
dispatchEvent(new Event("LanzaJSON"));
}
public function informadorIO(e:Event):void{
trace(e);
}
I need to protect my code against connection lost, so what I have to do to keep my project running?
You can catch the IO errors on url loader:
loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
private function ioErrorHandler(event:IOErrorEvent):void {
// URLLoader io failed
trace("ioErrorHandler: " + event);
// retry Json2Me maybe? How many times before you fail completely? Notify user?
Json2Me("https://someurl.com/xxxxx")
}
Also the uncaughtErrorEvents on the Loader/LoaderInfo can catch things like not even having a network connection.
LoaderInfo.uncaughtErrorEvents: to detect uncaught errors in code
defined in the same SWF. Loader.uncaughtErrorEvents: to detect
uncaught errors in code defined in the SWF loaded by a Loader object.
Example:
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
private function onUncaughtError(e:UncaughtErrorEvent):void {
e.preventDefault();
trace("onUncaughtError!!! - " + e.toString());
// Notify user of failure?...
}
You can also use a HTTPStatusEvent which can give use the returned HTTP status ( or even the returned HTTP response headers for an AIR app ) :
var url_loader:URLLoader = new URLLoader()
url_loader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, on_http_status); // works only for AIR
url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status);
url_loader.load(new URLRequest('http://www.example.com'))
function on_http_status(e:HTTPStatusEvent): void
{
trace(e.type); // gives, for example : httpStatus
trace(e.status); // gives, for example : 200
}
Hope that can help.
I have found Firebase, and it looks excellent for javascript / HTML5 usage.
But I was wondering if there is also an Actionscript API?
E.g
var myRootRef = new Firebase('https://myprojectname.firebaseIO-demo.com/');
myRootRef.set('Hello World!');
var dataRef = new Firebase('https://SampleChat.firebaseIO-demo.com/users/fred/name/first');
dataRef.on('value', function(snapshot) {
alert('fred’s first name is ' + snapshot.val());
});
So to set data and have listeners for updated data etc.
Thanks for any help
Matt
Doesn't look like there is an AS3 api available but the good news is that they have a rest api which is cross platform that you can write an AS3 wrapper around. (https://www.firebase.com/docs/rest-api.html) That is what I plan to do. I Want to use it with GameBuilder Studio.
If you are planning on embedding your application inside a web page (that you create) you could use an external javascript interface and communicate to firebase through that.
I'm planning on doing this myself to see how it turns out.
Connecting to Firebase using ActionScript 3 only requires the use of URLRequest and URLLoader. The following examples cover the 4 basic operations (CRUD).
To read data from an specific node from your Firebase database:
private function loadNews():void
{
var request:URLRequest = new URLRequest("https://<YOUR-PROJECT-ID>.firebaseio.com/<Node_to_read>.json");
var loader:URLLoader = new URLLoader();
loader.addEventListener(flash.events.Event.COMPLETE, newsLoaded);
loader.load(request);
}
private function newsLoaded(event:flash.events.Event):void
{
trace(event.currentTarget.data);
var rawData:Object = JSON.parse(event.currentTarget.data);
}
To insert data to a specific node:
private function saveEntry(title:String, description:String):void
{
var myObject:Object = new Object();
myObject.title = title;
myObject.description = description;
myObject.timestamp = new Date().getTime();
var request:URLRequest = new URLRequest("https://<YOUR-PROJECT-ID>.firebaseio.com/<Node_to_insert>.json");
request.data = JSON.stringify(myObject);
request.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.addEventListener(flash.events.Event.COMPLETE, entrySent);
loader.load(request);
}
private function entrySent(event:flash.events.Event):void
{
trace(event.currentTarget.data);
}
To delete a specific node:
private function deleteEntry():void
{
var header:URLRequestHeader = new URLRequestHeader("X-HTTP-Method-Override", "DELETE");
var request:URLRequest = new URLRequest("https://<YOUR-PROJECT-ID>.firebaseio.com/<Node_to_delete>.json");
request.method = URLRequestMethod.POST;
request.requestHeaders.push(header);
var loader:URLLoader = new URLLoader();
loader.addEventListener(flash.events.Event.COMPLETE, entryDeleted);
loader.load(request);
}
private function entryDeleted(event:flash.events.Event):void
{
trace(event.currentTarget.data);
}
To update/modify data to a specific node:
private function updateEntry(title:String, description:String):void
{
var header:URLRequestHeader = new URLRequestHeader("X-HTTP-Method-Override", "PATCH");
var myObject:Object = new Object();
myObject.title = title;
myObject.description = description;
var request:URLRequest = new URLRequest("https://<YOUR-PROJECT-ID>.firebaseio.com/journal/<Node_to_modify>.json");
request.data = JSON.stringify(myObject);
request.method = URLRequestMethod.POST;
request.requestHeaders.push(header);
var loader:URLLoader = new URLLoader();
loader.addEventListener(flash.events.Event.COMPLETE, entryUpdated);
loader.load(request);
}
private function entryUpdated(event:flash.events.Event):void
{
trace(event.currentTarget.data);
}
If you want further information I have written detailed Firebase REST guides and examples on how to use ActionScript 3 and Firebase.
I am trying to use the imdb API, in this case: http://imdbapi.org/
I need to search for a movie by name and get a json, then load an image with the poster obtained.
I'll be using as3 - flex to generate an Air package.
I tried this example, but can't seem to get it right.
import flash.net.*;
var url:String = "http://imdbapi.org/";
var request:URLRequest = new URLRequest(url);
request.method = URLRequestMethod.GET;
var variables:URLVariables = new URLVariables();
variables.name = "Pulp fiction";
request.data = variables;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onComplete);
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.load(request);
function onComplete (event:Event):void {
trace(event.target.data);
}
Perhaps you could enlight me with an example of connecting to the api and retrieving that json so that I can load an image with the poster and generate my air package.
Many thanks!
The API seems to want the movie in the q param so change this
variables.name = "Pulp fiction";
to :
variables.q = "Pulp fiction";
To verify : http://imdbapi.org/?q=Pulp%20Fiction
From there getting the poster URL is just a matter of reading the correct property from the JSON string.
private function onComplete (event:Event):void {
var data:Array = JSON.parse(event.target.data);
if(data && data.length)
{
var movie:Object = data[0];
trace(movie.poster);
}
}
private function getTitle(src:String):String{
var urlLoader:URLLoader = new URLLoader();
var rssURLRequest:URLRequest = new URLRequest(src);
var rss:XML = new XML;
var t:String = src;
urlLoader.addEventListener(Event.COMPLETE,
function(event:Event):void{
rss = XML(urlLoader.data);
t = rss.channel.title.toString();
});
return t;
}
I'm aware that this code doesn't work because the anonymous function doesn't work until after t is returned. How would I make it so that it works?
You won't be able to return the loaded data from this method. The reason for this is because the loading is asynchronous and doesn't not block the execution of subsequent code. Your best option is to move the vars out of the scope of the function and to write a second function to handle the COMPLETE event.
Something like the following should work:
var rss:XML;
var t:String;
var path:String = "some path";
var urlLoader:URLLoader = new URLLoader();
private function getTitle(src:String):String
{
urlLoader.load( new URLRequest( src ) );
urlLoader.addEventListener(Event.COMPLETE, onComplete );
}
private function onComplete(event:Event):void
{
rss = XML(urlLoader.data);
t = path + rss.channel.title.toString();
}
I realize that this doesn't really answer the question directly, though it is the best practice for handling data loading. If you really want to stop any code from executing before the data is loaded, it may be possible use a while loop after the addEventListener line to halt the player from until the data is loaded. This should probably be considered a not so elegant hack though.
private function getTitle(src:String):String
{
var urlLoader:URLLoader = new URLLoader();
var rssURLRequest:URLRequest = new URLRequest(src);
var rss:XML = new XML;
var t:String = src;
var complete:Boolean;
urlLoader.addEventListener(Event.COMPLETE,
function(event:Event):void
{
rss = XML(urlLoader.data);
t = rss.channel.title.toString();
complete = true;
});
while( !complete ) { /* sleep hack */ }
return t;
}
I haven't tested this, but it seems like it could work. The first example is recommended.
I try to download an external SWF and run it within the AIR security sandbox.
this is the code of the AIR application:
public class Downloader extends Sprite
{
private static const REMOTE_FILE:URLRequest = new URLRequest("http://myserver.com/downloadable.swf");
private var _main:NativeWindow;
public function Downloader()
{
var loader:URLLoader = new URLLoader(REMOTE_FILE);
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, downloadComplete);
}
private function downloadComplete(e:Event):void{
var ba:ByteArray = e.target.data;
var stream:FileStream = new FileStream();
var file:File = File.applicationStorageDirectory.resolvePath("downloadable.swf");
stream.open(file, FileMode.WRITE);
stream.writeBytes(ba);
stream.close();
loadAndRunSwf();
}
private function loadAndRunSwf(){
this._main = new NativeWindow();
this._main.width = 1024;
this._main.height = 768;
////obsolete?
//var context:LoaderContext = new LoaderContext();
//context.allowLoadBytesCodeExecution = true;
//context.applicationDomain = ApplicationDomain.currentDomain;
var file:File = File.applicationStorageDirectory.resolvePath("downloadable.swf");
var loader:Loader = new Loader();
loader.load(new URLRequest(file.url)/*,context*/);
this._main.stage.addChild(loader);
this._main.activate();
}
}
Code of the downloadable.swf:
public class Downloadable extends Sprite
{
private var _btn:Button = new Button();
private var _baseFolder:File = new File("app-storage:/");
public function downloadable_test()
{
this.addChild(_btn);
_btn.label = "access Harddisk";
...
}
}
so now, If I run Downloader, it will download the swf and try to run it, but i'll get an exception in Downloadable on the line
private var _baseFolder:File = new File("app-storage:/");
the error:
SecurityError: file
at runtime::SecurityManager$/checkPrivilegeForCaller()
So - what Do I need to do to prevent such security errors? I want my remote SWF to be treated as native code running in the same security sandbox as the AIR code.
I'm not sure about Android, but for the regular web player you would need to specify SecurityDomain.currentDomain for the securityDomain of the Loader's context for the loaded code to be considered equal to the loader in terms of permissions. Also note that for reasons impossible to explain, if you use SecurityDomain when loading from the file system on PC Flash Player will complain.
However complicated, the Flash Player security is often a security by obscurity... So, if it doesn't work the way you coded it, try Loader.loadBytes() "workaround".
function loadAndRunSwf()
{
var context:LoaderContext=new LoaderContext(false);
context.allowCodeImport=true;
var ba:ByteArray=new ByteArray();
var file:File = File.applicationStorageDirectory.resolvePath("downloadable.swf");
var fileStream:FileStream=new FileStream();
var loader:Loader = new Loader();
fileStream.open(file,"read");
fileStream.readBytes(ba);
ba.position=0;
loader.loadBytes(ba,context);
this._main = new NativeWindow();
this._main.width = 1024;
this._main.height = 768;
this._main.stage.addChild(loader);
this._main.activate();
}