AS3 Saving Filestream to file - ios

I am trying to import a SQL database into my Adobe Air iOS app. I have the invoke working and everything seems to work but the new database file can't be read. Below is my code.
function onInvoke(event:InvokeEvent):void{
if(event.arguments && event.arguments.length)
{
contentUri = event.arguments[0] as String;
file_db = new File(contentUri);
fs_db = new FileStream();
fs_db.addEventListener(Event.COMPLETE, import_db);
fs_db.openAsync(file_db, FileMode.READ);
}
}
My import function looks like this:
function import_db(event:Event):void{
fs_db.removeEventListener(Event.COMPLETE, import_db);
var fs:FileStream = new FileStream();
var myfile:File=File.applicationStorageDirectory.resolvePath("testDB.db");
var fileContent:String = fs_db.readUTFBytes(fs_db.bytesAvailable);
fs.open(myfile,FileMode.WRITE);
fs.writeUTFBytes(fileContent);
fs.addEventListener(Event.CLOSE, fileClosed);
fs.close();
function fileClosed(e:Event):void{
// do other stuff
}
}
Every thing seems to execute but when I try to connect to the database, I get SQL error:
Error #2044: Unhandled SQLErrorEvent:. errorID=3138, operation=open , message=Error #3138: File opened is not a database file.
Any guidance is appreciated

Figured it out, read the bytes into a bytearray and then into the file.
var mybytes:ByteArray=new ByteArray();
fs_db.readBytes(mybytes,0,fs_db.bytesAvailable);
fs.openAsync(myfile,FileMode.WRITE);
fs.writeBytes(mybytes,0,mybytes.length);

Related

AS3 - How to load and read XML file on iOS

I'm working on simple iOS game where you have e.g. 10 levels and once you completed one the next level will unlock. I create the xml file here:
private function SaveProgress()
{
addChild(myTextField);
var GameSaveXML:XML =
<LEVEL>
<LEVEL_01>false</LEVEL_01>
<LEVEL_02>false</LEVEL_02>
<LEVEL_03>false</LEVEL_03>
<LEVEL_04>false</LEVEL_04>
<LEVEL_05>false</LEVEL_05>
<LEVEL_06>false</LEVEL_06>
<LEVEL_07>false</LEVEL_07>
<LEVEL_08>false</LEVEL_08>
<LEVEL_09>false</LEVEL_09>
<LEVEL_10>false</LEVEL_10>
</LEVEL>;;
//file.deleteFile();
var file:File = File.documentsDirectory.resolvePath("LevelsSaved.xml");
if (file.exists)
{
trace("EXISTS");
trace(GameSaveXML);
}
else
{
var fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
var outputString:String = '<?xml version="1.0" encoding="utf-8"?>\n';
outputString += GameSaveXML.toXMLString();
fileStream.writeUTFBytes(outputString);
//GameSaveXML.replace(2,<LEVEL_03>true</LEVEL_03>);
trace(GameSaveXML);
fileStream.close();
trace("File Was Created");
}
}
I'm really struggling with loading the file and checking what levels are unlocked (true) and what levels are still locked (false). Can you please help? Thanks a lot!
If you know how to write xml, can't you read it the same way?
var content:String = fileStream.readUTFBytes(fileStream.bytesAvailable);
var xml:XML = new XML(content);
if (xml.LEVEL_01 == 'true') trace('unlocked');
else trace('locked');
or you can use URLLoader to load xml as string
I'm 99% sure I did not undestand the question - sorry then :p

Adobe AIR 3.4 saving/writing XML data to iOS

I'm trying save XML data to an iPad 4 with AIR 3.4 for iOS and really can't tell if this is working or not. No events are being fired apparently. Any help is greatly appreciated.
private function saveData(e:MouseEvent):void {
var name:String = AssetManager.SAVE_ANNOTATIONS_NAME
var file:File = new File()
file = File.applicationStorageDirectory.resolvePath(name + "xml");
var xml:XML = _canvas.getObjectData(FormatType.DEGRAFA);
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeUTF(xml.toString());
fileStream.addEventListener(ProgressEvent.PROGRESS, onFileStream);
fileStream.addEventListener(Event.ACTIVATE, onFileStream);
fileStream.addEventListener(Event.OPEN, onFileStream);
fileStream.addEventListener(Event.DEACTIVATE, onFileStream);
fileStream.addEventListener(IOErrorEvent.IO_ERROR, onFileStream);
fileStream.addEventListener(Event.COMPLETE, onFileStream);
}
protected function onFileStream(event:Event):void
{
trace('filestream event was ' + event)
fileStream.close();
}
I seemed to have fixed it with this:
private function saveFile(event:MouseEvent):void
{
var xml:XML = _canvas.getObjectData(FormatType.DEGRAFA);
trace('xml is ' + xml.toXMLString())
var file:File = File.documentsDirectory.resolvePath("annotations.xml");
var fileStream:FileStream = new FileStream();
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeUTFBytes(xml.toXMLString());
fileStream.addEventListener(Event.CLOSE, fileClosed);
fileStream.close();
function fileClosed(event:Event):void {
trace("File Saved");
}
}
You are writing BEFORE adding the listeners. Proper order should be:
var fileStream:FileStream = new FileStream();
// all the listeners here
fileStream.open(file, FileMode.WRITE);
fileStream.writeUTF(xml.toString());
You must take note of the command you are using to open the file stream. If you use filestream.openAsync then the file stream is opened asynchronously, meaning you will have to wait for the Event.OPEN event on the filestream object. If you use filestream.open, then you can call functions on the filestream object immediately without waiting for an OPEN event. For me the jump to ActionScript, and its asynchronous nature, took some time to get used to.

Adobe AIR Mobile on iOS - processing text very slow

I am writing an iOS app in Flash Builder 4.6 that will need to process a large text file. So far, I am just trying to get the version information from the file, a simple task that runs very fast in the simulator but takes a very long time (on the order of 10 seconds) on my iPad 2.
As the file is large (about 11MB), I am trying to only read far enough into the file to get the version data. Is it possible that the filestream loads the whole file into memory anyway? If so, how do I avoid that?
Note that the code works correctly, and displays the correct version info.
Any advice on how to speed it up would be greatly appreciated.
The file being processed can be found here: http://oanda.sca.org:80/oanda.db
The code is as follows:
Calling code:
protected function view1_viewActivateHandler(event:ViewNavigatorEvent):void
{
var DT:DatabaseTools = new DatabaseTools();
var version:String;
//Get version information from local file:
version = DT.GetLocalVer("oanda.db");
lblLclVer.text=version;
}
Actual function:
public function GetLocalVer(fileName:String):String
{
var out:ByteArray = new ByteArray();
var line_Out:String;
var char:int;
var line:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
var file:File = File.documentsDirectory.resolvePath(fileName);
var lineString:String;
var result:String = "Error";
stream.open(file,FileMode.READ);
var found:Boolean=false;
while((stream.bytesAvailable > 0) && !found)
{
char=stream.readByte();
if(String.fromCharCode(char) == "\n")
{
//reset the line
out=line;
line = new ByteArray();
//process the line to see if its the version info.
lineString=out.toString(); //since the version line never has UTF characters, convert it to a regular string
if(lineString.length > 25) //Any line shorter than this can't be the version line
{
var startOfLine:String = lineString.substr(0,17);
if(startOfLine == " ||C|Last update:")
{
result = lineString.substr(19,6);
found = true;
}
}
}
else
{
line.writeByte(char);
}
}
stream.close();
return result;
}
Thanks.

AS3 Save SWF to iOS device and then load it back into a MovieClip

I have an iOS app that's using AS3 and AIR. I have external swfs downloading from a server and playing properly--all of this works perfectly fine.
I don't want the user to have to download these swfs every time they launch the app, though, so after the swf is downloaded the first time I want to save it to disk. That way I can load it from the local copy when I need it in the future, instead of downloading it again. I found this example online for saving files in AS3:
var file:File = File.applicationStorageDirectory.resolvePath("Swfs/" + "mySwfName" + ".swf");
var wr:File = new File(file.nativePath);
var stream:FileStream = new FileStream();
stream.open(wr, FileMode.WRITE);
stream.writeBytes(SWF_FILE_GOES_HERE, 0, SWF_FILE_DATA_LENGTH_GOES_HERE);
stream.close();
The problem is in the writeBytes line. The sample I found was for saving images to disk, and that line read like this:
stream.writeBytes(imageData, 0, imageData.length);
But I need to do this for a swf, not an image, and I'm not sure how to get the requisite data from my swf file. I've searched online for saving swf files, getting data from swf files, etc... But I haven't found anything. I need to get the swf's data and data length (I'm assuming this is a number of bytes?). Has anyone solved this problem before, or have a resource they can point me in the direction of?
UPDATE: Based on #LondonDrugs_MediaServices' comments, I figured out the writeBytes line:
stream.writeBytes(mySwf.loaderInfo.bytes, 0, mySwf.loaderInfo.bytesTotal);
This seems to work, in as much as it compiles and runs without errors. But when I try to grab the file and put it back into a movie clip, I get this error:
Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
Which implies that the file was not, in fact, saved correctly. When I print the file locations, however, they seem to be right! When I save the file to the applicationStorageDirectory:
/Users/MyName/Library/Preferences/com.appdir/Local Store/Swfs/mySwName.swf
And the filename when I try and load it out of storage and into a movie clip:
/Users/MyName/Library/Preferences/com.appdir/Local Store/Swfs/mySwName.swf
This is the code I'm using to try and load it back into a movie clip:
var videoFileName:String = "Swfs/" + ENVAR.currentVideoSelected + ".swf";
var videoFilePath:File = File.applicationStorageDirectory.resolvePath(videoFileName);
var inFileStream:FileStream = new FileStream();
trace("[Loading] filepath: ", videoFilePath.nativePath);
inFileStream.open(videoFilePath, FileMode.READ);
var fileContents:String = inFileStream.readUTFBytes(inFileStream.bytesAvailable);
inFileStream.close();
var req:URLRequest = new URLRequest(videoFilePath.nativePath);
var mLoader:Loader = new Loader();
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onVideoLoadComplete);
mLoader.load(req);
And my onVideoLoadComplete function contains these lines:
var myMC:MovieClip = e.target.content as MovieClip;
addChild(myMC);
But I'm getting that error 2044 and it doesn't think the file exists. Can anyone spot the problem? Thanks!
You can get the raw bytes of a loaded swf file by using it's loaderInfo.bytes parameter. So for you example you could do this:
var file:File = File.applicationStorageDirectory.resolvePath("Swfs/" + key + ".swf");
var wr:File = new File(file.nativePath);
var stream:FileStream = new FileStream();
stream.open(wr, FileMode.WRITE);
stream.writeBytes(mySwf.loaderInfo.bytes, 0, mySwf.loaderInfo.bytesTotal);
stream.close();
Then to pull it back out into a MovieClip:
var videoFileName:String = "Swfs/" + ENVAR.currentVideoSelected + ".swf";
var videoFilePath:File = File.applicationStorageDirectory.resolvePath(videoFileName);
var inFileStream:FileStream = new FileStream();
inFileStream.open(videoFilePath, FileMode.READ);
var swfBytes:ByteArray = new ByteArray();
inFileStream.readBytes(swfBytes);
inFileStream.close();
var mLoader:Loader = new Loader();
var loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
loaderContext.allowCodeImport = true;
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onVideoLoadComplete);
mLoader.loadBytes(swfBytes, loaderContext);

WinRT StorageFile write downloaded file

I'm struggling with a easy problem. I want to download an image from web using this code:
WebRequest requestPic = WebRequest.Create(#"http://something.com/" + id + ".jpg");
WebResponse responsePic = await requestPic.GetResponseAsync();
Now I wanted to write the WebResponse's stream in a StorageFile (eg. create a file id.jpg in the app's storage), but I haven't found any way to achieve that. I searched the web for it, but no success - all ways incompatible Stream types and so on.
Could you please help?
I have found the following solution, which works and is not too complicated.
public async static Task<StorageFile> SaveAsync(
Uri fileUri,
StorageFolder folder,
string fileName)
{
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
var downloader = new BackgroundDownloader();
var download = downloader.CreateDownload(
fileUri,
file);
var res = await download.StartAsync();
return file;
}
You will need to read the response stream into a buffer then write the data to a StorageFile. THe following code shows an example:
var fStream = responsePic.GetResponseStream();
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("testfile.txt");
using (var ostream = await file.OpenStreamForWriteAsync())
{
int count = 0;
do
{
var buffer = new byte[1024];
count = fStream.Read(buffer, 0, 1024);
await ostream.WriteAsync(buffer, 0, count);
}
while (fStream.CanRead && count > 0);
}
That can be done using the C++ REST SDK in Windows Store Apps. It's explained by HTTP Client Tutorial.

Resources