Reputation: 164
Using the final release of Flash Builder 4.7, AIR 3.5, Flex 4.6.0 (build 23201), and run/debugging fast-build to an iPad2 MC981LL running iOS 6.0.1 (10A523)
I've wasted a day and more on what I should think should be fairly straightforward, but at this point I'm at a complete loss. Any help appreciated.
I'm getting no error messages. The file exists after this runs, however the size is only 128 bytes. Needless to say it cannot be read in as anything but NULL. I've even instantiated an Object() in the writeObject function just to make certain it wasn't my more complex object that was causing the difficulties (also I temporarily left the bitmapData and thumbnail properties blank for simplicity). No dice.
I've included every bit of relevant code except my attempts to read back in the object.
Needless to say this started out as a simple class with a read and a write function, and grew more elaborate as I tried and tried to get usable information back as to why it was failing. Originally there were no trace statements, no custom even and dispatcher, no try,catch,finally, and no event listeners for something, anything to give me a clue.
Also, I'm probably doing the whole custom event/handler/listener/dispatcher wrong because the statusMessage in the class that gets the whole ball rolling (last code block at the bottom) displays "Saving Image and Thumbnail to Library" but never ever "File Saved to Library"
Any help is greatly appreciated.
Here's my trace:
[SWF] PictureToolsOnTheMoveMakeIt.swf - 4,154,904 bytes after decompression
FileSerializer FUNCTION writeObjectToFile()
FileStream.openAsync(write) finally
FileStream.writeError() finally
The FileSerializer class:
package classes
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.errors.*;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import events.FileSerializerEvent;
import vo.PTotmImageVO;
[Event(name = "writeComplete", type = "events.FileSerializerEvent")]
[Event(name = "readComplete", type = "events.FileSerializerEvent")]
public class FileSerializer extends EventDispatcher
{
private var fileStream:FileStream = new FileStream();
public function FileSerializer(target:IEventDispatcher=null)
{
super(target);
} // End CONSTRUCTOR FileSerializer
public function writeObjectToFile(ptotmImageVO:PTotmImageVO, fnam e:String):void
{
trace("FileSerializer FUNCTION writeObjectToFile()");
var file:File = File.applicationStorageDirectory.resolvePath(ptotmImageVO.userid+"-"+ptotmImageVO.timestamp+".PTotmImageVO");
fileStream.addEventListener(Event.CLOSE, close);
fileStream.addEventListener(IOErrorEvent.IO_ERROR, ioErrorEventHandler);
try
{
fileStream.openAsync(file, FileMode.WRITE);
}
catch (e:SecurityError)
{
// The file location is in the application directory, and the fileMode parameter is set to "append",
// "update", or "write" mode.
trace("FileStream.openAsync(write) SecurityError "+e);
}
finally
{
trace("FileStream.openAsync(write) finally");
}
try
{
fileStream.writeObject(ptotmImageVO);
}
catch (e:IOError)
{
// The file has not been opened; the file has been opened, but it was not opened with write capabilities;
// or for a file that has been opened for synchronous operations (by using the open() method), the file
// cannot be written (for example, because the file is missing).
trace("FileStream.writeObject() IOError "+e);
}
finally
{
trace("FileStream.writeObject() finally");
}
} // End FUNCTION writeObjectToFile
protected function close(e:Event):void
{
trace("FileSerializer FUNCTION close()");
dispatchEvent(new FileSerializerEvent(FileSerializerEvent.WRITE_COMPLETE, null,true,true));
} // End FUNCTION close
protected function ioErrorEventHandler(event:Event):void
{
trace("FileSerializer FUNCTION ioErrorEventHandler()");
} // End FUNCTION ioErrorEventHandler
public function readObjectFromFile(fname:String):Object
{
var file:File = File.applicationStorageDirectory.resolvePath(fname);
if(file.exists)
{
var obj:Object;
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.COMPLETE, readComplete);
fileStream.open(file, FileMode.READ);
obj = fileStream.readObject();
fileStream.close();
return obj;
}
return null;
} // End FUNCTION readObjectFromFile
protected function readComplete(event:Event):void
{
dispatchEvent(new FileSerializerEvent(FileSerializerEvent.READ_COMPLETE, event.target));
} // End FUNCTION readComplete
} // End CONSTRUCTOR FileSerializer
} // End PACKAGE classes
ValueObject Class:
package vo
{
import flash.display.BitmapData;
[remoteClass(alias="PTotmImageVO")]
public class PTotmImageVO
{
public var userid:String;
public var thumbnail:BitmapData;
public var image:BitmapData;
public var timestamp:Number;
public var description:String;
public var type:String;
public function PTotmImageVO()
{
} // End Constructor PTotmImageVO
} // End Class PTotmImageVO
} // End Package vo
Event Class FileSerializerEvent:
package events
{
import flash.events.Event;
public class FileSerializerEvent extends Event
{
public static const WRITE_COMPLETE:String = "writeComplete";
public static const READ_COMPLETE:String = "readComplete";
public function FileSerializerEvent(type:String, data:*=null, bubbles:Boolean = true, cancelable:Boolean = true)
{
super(type, bubbles, cancelable);
switch(type)
{
case WRITE_COMPLETE:
break;
case READ_COMPLETE:
break;
}
}
}
}
Finally, the code where I create the object, instantiate the class and invoke the class's writeObjectToFile() function using the created object:
private var ptotmImageVO:PTotmImageVO = new PTotmImageVO();
private var fileSerializer:FileSerializer = new FileSerializer();
protected function createThumbnail():void
{
thumbBmpData = ImageResizer.bilinearIterative(bmpData, borderRect.width, borderRect.height, ResizeMath.METHOD_LETTERBOX , true, 3);
saveImageToLibrary();
}
protected function saveImageToLibrary():void
{
statusMessage.text = "Saving Image and Thumbnail to Library...";
ptotmImageVO.userid = parentApplication.userid;
ptotmImageVO.description = "";
ptotmImageVO.timestamp = new Date().getTime();
// ptotmImageVO.thumbnail = thumbBmpData;
// ptotmImageVO.image = bmpData;
ptotmImageVO.type = "PictureTools - On The Move - Photo Entity";
fileSerializer.addEventListener(FileSerializerEvent.WRITE_COMPLETE, saveComplete);
fileSerializer.writeObjectToFile(ptotmImageVO, ptotmImageVO.userid+"-"+ptotmImageVO.timestamp+".PTotmImageVO");
}
protected function saveComplete(event:FileSerializerEvent):void
{
statusMessage.text = "File Saved to Library";
}
Ah, well. Might as well provide all the information. This is the class in which I'm trying to read in the objects as I plan to use an itemRenderer to display them in a Tile Layout (hopefully the new DataGrid in Apache Flex 4.9 soon)...
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="drawBackground()"
click="refreshFileListing()">
<fx:Script>
<![CDATA[
import spark.components.VGroup;
import classes.FileSerializer;
import events.FileSerializerEvent;
import vo.PTotmImageVO;
[Bindable]
private var file:File = File.applicationStorageDirectory;
[Bindable]
private var directoryListing:String = new String();
private var files:Array;
private var fs:FileSerializer = new FileSerializer();
public function refreshFileListing():void
{
files = file.getDirectoryListing();
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.nativePath -- "+file.nativePath);
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.isDirectory -- "+file.isDirectory);
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.name -- "+file.name);
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.getDirectoryListing -- "+file.getDirectoryListing());
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing -- files.length -- "+files.length);
var objects:Array = new Array();
for (var i:uint = 0; i < files.length; i++)
{
fs.addEventListener(FileSerializerEvent.READ_COMPLETE, fileReadComplete);
var f:String = files[i].name;
var o:PTotmImageVO = fs.readObjectFromFile(f) as PTotmImageVO;
objects.push(o); // Desperate at this point pretty much trying nonsense
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing in for() -- o -- "+o);
// This is destined for an itemRenderer if ever I can get an object serialized to file and read back in.
// var b:BitmapData = o.thumbnail as BitmapData;
//
// var img:Image = new Image();
// img.source = b;
//
// var l:Label = new Label();
// l.text = files[i].name;
//
// var vg:VGroup = new VGroup();
// vg.addElement(img);
// vg.addElement(l);
//
// tg.addElement(vg);
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing in for()#1 -- count/name/size -- "+i+". "+files[i].name+" "+files[i].size+"bytes");
}
for(var k:uint = 0; k<objects.length; k++)
{
trace("MyLibraryPhotoPanel FUNCTION refreshFileListing in for()#2 -- file object in Array -- "+k+". "+objects[k]);
}
} // End FUNCTION refreshFileListing
protected function fileReadComplete(event:FileSerializerEvent):void
{
trace("MyLibraryPhotoPanel FUNCTION FileReadComplete");
} // End FUNCTION fileReadComplete
protected function drawBackground():void
{
with(graphics)
{
beginFill(0xffffff,0);
drawRect(0,0,parent.width,parent.height);
endFill();
}
} // End FUNCTION drawBackground
]]>
</fx:Script>
<s:VGroup id="tg" height="100%" width="100%">
</s:VGroup>
</s:Group>
And the trace output:
[SWF] PictureToolsOnTheMoveMakeIt.swf - 4,152,506 bytes after decompression
FileSerializer FUNCTION writeObjectToFile()
FileStream.openAsync(write) finally
FileStream.writeObject() finally
FileSerializer FUNCTION writeObjectToFile()
FileStream.openAsync(write) finally
FileStream.writeObject() finally
MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.nativePath -- /var/mobile/Applications/926FFAF1-3FBE-4854-A61C-3BB8A3752D50/Library/Application Support/org.PictureTools.Apps.PictureToolsOnTheMoveMakeIt.debug/Local Store
MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.isDirectory -- true
MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.name -- Local Store
MyLibraryPhotoPanel FUNCTION refreshFileListing -- file.getDirectoryListing -- [object File],[object File]
MyLibraryPhotoPanel FUNCTION refreshFileListing -- files.length -- 2
MyLibraryPhotoPanel FUNCTION refreshFileListing in for() -- o -- null
MyLibraryPhotoPanel FUNCTION refreshFileListing in for()#1 -- count/name/size -- 0. 000000-1357831345565.PTotmImageVO 117bytes
MyLibraryPhotoPanel FUNCTION refreshFileListing in for() -- o -- null
MyLibraryPhotoPanel FUNCTION refreshFileListing in for()#1 -- count/name/size -- 1. 000000-1357831356829.PTotmImageVO 117bytes
MyLibraryPhotoPanel FUNCTION refreshFileListing in for()#2 -- file object in Array -- 0. null
MyLibraryPhotoPanel FUNCTION refreshFileListing in for()#2 -- file object in Array -- 1. null
Upvotes: 1
Views: 658
Reputation: 164
Resolved. The Metadata tag is [RemoteClass... not [remoteClass as was shown in the example code I began working from. As the compiler doesn't check these tags, and making up your own tag isn't technically an error, there will -NEVER- be any diagnostic data from which to work.
Upvotes: 1