AIR AS3 for Mobile - Download zip file crash the application - actionscript-3

I've make an application with AIR and ActionScript 3 ( Using the IntelliJ IDE )
At start of the application, it loads some zip file and extracts their files to put them in the local storage. For futur use ( Or an utilisation if the user kills then re-opens the application )
It works correctly without problem the most of the time except that I have, sometimes, with a very low rate of appearence, a crash of the application during the download of those zip files.
The strange thing is these crash can occur directly in the emulator on my computer ( With a message that indicates an error in AIR ).
It is really difficult to check because these crashes may occur, something, like one time on forty launches and seems to never occur when trace() are with the debug mode.
That makes me think it's probably a problem with the speed of the loading, because all trace() slows down the launches and files loading.
Apparently, it's not a memory crash. I've tested and used the same code to load a really high number of same zip together and it doesn't crash.
I can't directly show the code, because it is implanted in a more complex framework.
The concerned code is something near to this :
private static function fileLoad( url:String ):void
{
var loader:URLLoader = new URLLoader();
var header:URLRequestHeader = new URLRequestHeader( "pragma" , "no-cache" );
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener( Event.COMPLETE, complete );
var request:URLRequest = new URLRequest( url );
request.requestHeaders.push( header );
request.method = URLRequestMethod.GET;
loader.load( request );
}
private static function complete( event:Event ):void
{
var file:File;
file = File.applicationStorageDirectory.resolvePath( "ZIP.zip" );
var bytes:ByteArray = event.target.data as ByteArray;
var stream:FileStream = new FileStream();
stream.open( file , FileMode.WRITE );
stream.writeBytes( bytes );
stream.close();
var loadZip:Function = function( event:FZipEvent ):void
{
var zip:FZipFile = event.file;
if ( zip.sizeUncompressed != 0 )
{
var fileData:Object = {};
var file:File = outputFile.resolvePath( zip.filename );
var stream:FileStream = new FileStream();
file.preventBackup = true;
stream.open( file, FileMode.WRITE );
stream.writeBytes( zip.content );
stream.close();
}
};
var inputFile:File = File.applicationStorageDirectory.resolvePath( "ZIP.zip" );
var outputFile:File = File.applicationStorageDirectory.resolvePath( "folderZip" );
var zipFileBytes:ByteArray = event.target.data as ByteArray;
stream = new FileStream();
stream.open( inputFile , FileMode.READ );
stream.readBytes( zipFileBytes );
stream.close();
var zip:FZip = new FZip();
zip.addEventListener( FZipEvent.FILE_LOADED , loadZip );
zip.load( new URLRequest( inputFile.nativePath ) );
}
I don't really expect a total solution but, if you have encountered a similar problem, I'll be thankfull to know what you've done to resolve it.
Thanks a lot

Related

Launch Inno Setup Update from within AIR

I am using Inno Setup to create my installer for a desktop AIR app. I have my desktop app check my database for an app version number to let the user know if there is an update ready to install. I would like to have a pretty seamless update process for the user, so if they want to update, I would like for AIR to download the EXE and then run it.
1.) How do you download big files like an EXE from the web in AIR and do you need to place it someplace specific?
2.) Once the file is downloaded, how do I get AIR to execute the EXE?
Thanks!
public static function download(sourceURL:String, destinationPath:String, complete:Function = null, progress:Function = null, error:Function = null):void
{
var urlReq:URLRequest = new URLRequest(sourceURL);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
if(progress != null) urlStream.addEventListener(ProgressEvent.PROGRESS, progress);
if(error != null) urlStream.addEventListener(IOErrorEvent.IO_ERROR, error);
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
function loaded(event:*):void
{
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
writeFile();
}
function writeFile():void
{
var file:File = new File(destinationPath + sourceURL.slice(sourceURL.lastIndexOf("/"), sourceURL.length));
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(fileData, 0, fileData.length);
fileStream.close();
if(complete != null) complete();
}
}
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
process = new NativeProcess();
process.closeInput();
process.start(nativeProcessStartupInfo);

Get response status code from flash Sound object

I have music player which downloads and plays music (it should play while downloading), currently my code looks like this:
sound = new Sound(new URLRequest(url_stream));
Sometimes server returns 404 (Not Found) and 429 (Too many requests) status codes instead of music file, I'm looking for way to find out response status code in case of playback error, any ideas?
To get the response status, you can use HTTPStatusEvent event with an URLLoader like this :
var sound:Sound
var request:URLRequest = new URLRequest('http://www.example.com/file.mp3')
var loader:URLLoader = new URLLoader()
loader.addEventListener(
HTTPStatusEvent.HTTP_STATUS,
function(event):void {
trace('http status: ' + event.status)
if(event.status == 200){
sound = new Sound(request)
sound.play()
}
}
)
loader.addEventListener(IOErrorEvent.IO_ERROR, function(){})
loader.load(request)
This code is working 100%.
In akmozo's solution, you're downloading the MP3 twice. First to see if the file exists on the server, then once more to play it in the Sound. It would be better to do it like this:
var sound:Sound;
var request:URLRequest = new URLRequest('http://www.example.com/file.mp3');
var loader:URLLoader = new URLLoader();
var httpCode:int;
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,loaderStatus);
loader.addEventListener(Event.COMPLETE,loaderComplete);
function loaderStatus(evt:HTTPStatusEvent):void {
httpCode = evt.status;
}
function loaderComplete(evt:Event):void {
if (httpCode == 200) {
ba:ByteArray = loader.data as ByteArray;
sound = new Sound();
sound.loadCompressedDataFromByteArray(ba,ba.length);
sound.play();
}
}
Although if the URLRequest is cached, maybe it doesn't get downloaded twice.

How to communicate with SWF objects?

I have some flash games (.swf files) embedded in my website.
I'm wondering if I could get data (like the final game score) from them, to create a "top players" database?
Is there any way to get this data from the swf object without recompiling the file?
You could send the data ( the score, for example ) to a php file ( or maybe asp ) and store it in a database.
example:
function SendRequest(dataToBeStoredInDB:URLVariables, callback:Function):void
{
var urlReq:URLRequest = new URLRequest("/path/to/phpfile/on/server.php");
urlReq.method = URLRequestMethod.POST;
urlReq.data = dataToBeStoredInDB;
var loader:URLLoader = new URLLoader(urlReq);
loader.addEventListener( Event.COMPLETE, callback_function );
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.load(urlReq);
}

How do I send a bytearray to server and detect progress?

I am using Flash runtime (flash player 10). I have a flv encoded bytearray which I need to send to the server( simple php, no FMS or socket servers) and save there. I can use the urlLoader and post everything but then i won't get the progress percentage, so instead I tried saving it with a file reference like this:
var url_ref:URLRequest = new URLRequest("save_vid.php");
url_ref.contentType = "multipart/form-data; boundary="+getBoundary();
url_ref.data = _baFlvEncoder.byteArray;
url_ref.method = URLRequestMethod.POST;
var upfileRef:FileReference = new FileReference();
upfileRef.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
upfileRef.addEventListener(Event.COMPLETE, videoUploadComplete);
upfileRef.upload(url_ref);
But when I try this, I am getting an error:
Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful.
Any idea how I can do this?
Try this:
var vars :URLVariables = new URLVariables();
vars.bytearray = _baFlvEncoder.byteArray;
var req :URLRequest = new URLRequest("save_vid.php");
req.method = URLRequestMethod.POST;
req.data = vars;
var ldr :URLLoader = new URLLoader();
ldr.addEventListener( Event.COMPLETE, onLoaded );
ldr.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
ldr.addEventListener( ProgressEvent.PROGRESS, onProgress );
ldr.load( req );
function onProgress( e:ProgressEvent ):void
{
trace( "Progress: " + e.bytesLoaded / e.bytesTotal );
}
and in PHP
$bytearray = $_POST['bytearray']

AS3 functions and accessing variables

I'm trying to create a JW player plugin, a part of the source code is shown below:
public function initPlugin(player:IPlayer, config:PluginConfig):void {
api = player;
var streamUrl:String = 'xxx';
var streamSecret:String = 'xxx';
var xid:String = config['xid'];
var request:URLRequest = new URLRequest("xxx"+xid);
request.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.addEventListener(Event.COMPLETE, completeHandler);
loader.load(request);
var fileName:String, drive:String, userFolder:String, t_hex:String, linkType:String
function completeHandler(evt:Event) {
linkType = evt.target.data.linkType;
fileName = evt.target.data.filename;
drive = evt.target.data.drive;
userFolder = evt.target.data.userFolder;
t_hex = evt.target.data.t_hex;
if (linkType == "1")
{
/*
PHP will generate these variables for the plugin.
fileName, drive, userFolder, t_hex
*/
var relPath:String = "/"+drive+"/"+userFolder+"/"+fileName;
var md5Hash = MD5.encrypt (streamSecret+relPath+t_hex);
var link:String = streamUrl+md5Hash+"/"+t_hex+relPath;
} else
{
}
api.load('http://music-stream.burst-dev.com/test.flv');
api.play();
}
I'm currently stuck on getting api.load('') to actually load the file. I've tested through anthropod and the variables getting added in are a-okay and the link generates perfectly.
I think my error is trying to get api = player to be accessed by function completeHandler, but it is not able to. Anyone got any ideas?
The code above worked, using Anthropod, I found out that it still was a crossdomain issue. I solved it by loading all files under the same URL basename. For example, xxx.burst-dev.com. api.load however can load files abroad, despite the crossdomain need in AS3 files.