**I have an air app for iOS I have been developing. I am trying to capture a picture, save the file to the storage directory (not Camera Roll), and save the file name in an sqlite db.
I have tried so many different variations of this, but when it comes to writing the filestream to save the app hangs. Testing on iPad 3. Does ANYONE have a suggestion? This has been driving me nuts for days. I have searched the web but I am stumped.**
public var temp:File; // File Object to save name in database
protected function selectPicture():void
{
myCam = new CameraUI();
myCam.addEventListener(MediaEvent.COMPLETE, onComplete);
myCam.launch(MediaType.IMAGE);
}
protected function onComplete(event:MediaEvent):void {
//imageProblem.source = event.data.file.url;
var cameraUI:CameraUI = event.target as CameraUI;
var mediaPromise:MediaPromise = event.data;
var mpLoader:Loader = new Loader();
mpLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMediaPromiseLoaded);
mpLoader.loadFilePromise(mediaPromise);
}
private function onMediaPromiseLoaded(e:Event):void
{
var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo;
mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded);
this.imageProblem.source = mpLoaderInfo.loader;
var stream:FileStream = new FileStream();
stream.addEventListener(Event.COMPLETE, showComplete);
stream.addEventListener(IOErrorEvent.IO_ERROR, showError);
try{
this.messages.text = "Starting";
stream.open( temp, FileMode.WRITE );
stream.writeBytes(mpLoaderInfo.bytes);
stream.close();
}catch(e:Error){
this.messages.text = e.message;
}
}
protected function showError(e:IOErrorEvent):void{
this.messages.text = e.toString();
}
protected function showComplete(e:Event):void{
this.messages.text = "Completed Writing";
this.imgName.text = temp.url;
imagefile = temp;
deleteFlag = 1;
}
Application hangs due to you are trying to use file operation in Sync mode.
You need to use Async Mode operation instead of sync mode file operation.
stream.openAsync( temp, FileMode.WRITE );
Try with this
var stream:FileStream = new FileStream();
stream.addEventListener(Event.COMPLETE, showComplete);
stream.addEventListener(IOErrorEvent.IO_ERROR, showError);
stream.openAsync( temp, FileMode.WRITE );
stream.writeBytes(mpLoaderInfo.bytes);
stream.close();
Note when using async operation you need not use try catch.For handling error listen IOErrorEvent will catch if any error occurs.
I finally got this to work, I added comments below in the code to explain why it wasn't working.
public var temp:File;
protected function selectPicture():void
{
myCam = new CameraUI();
myCam.addEventListener(MediaEvent.COMPLETE, onComplete);
myCam.launch(MediaType.IMAGE);
}
protected function onComplete(event:MediaEvent):void {
//imageProblem.source = event.data.file.url;
var cameraUI:CameraUI = event.target as CameraUI;
var mediaPromise:MediaPromise = event.data;
var mpLoader:Loader = new Loader();
mpLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMediaPromiseLoaded);
mpLoader.loadFilePromise(mediaPromise);
}
private function onMediaPromiseLoaded(e:Event):void
{
var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo;
mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded);
this.imageProblem.source = mpLoaderInfo.loader;
/// Here was the solution
var bitmapDataA:BitmapData = new BitmapData(mpLoaderInfo.width, mpLoaderInfo.height);
bitmapDataA.draw(mpLoaderInfo.content,null,null,null,null,true);
/// I had to cast the loaderInfo as BitmapData
var bitmapDataB:BitmapData = resizeimage(bitmapDataA, int(mpLoaderInfo.width / 4), int(mpLoaderInfo.height/ 4)); // function to shrink the image
var c:CameraRoll = new CameraRoll();
c.addBitmapData(bitmapDataB);
var now:Date = new Date();
var f:File = File.applicationStorageDirectory.resolvePath("IMG" + now.seconds + now.minutes + ".jpg");
var stream:FileStream = new FileStream()
stream.open(f, FileMode.WRITE);
// Then had to redraw and encode as a jpeg before writing the file
var bytes:ByteArray = new ByteArray();
bytes = bitmapDataB.encode(new Rectangle(0,0, int(mpLoaderInfo.width / 4) , int(mpLoaderInfo.height / 4)), new JPEGEncoderOptions(80), bytes);
stream.writeBytes(bytes,0,bytes.bytesAvailable);
stream.close();
this.imgName.text = f.url;
imagefile = f;
deleteFlag = 1;
}
Related
I have a small png image I like to show in an imageview using Xamarin.Android.
I am downloading the file using the following code:
private void Download()
{
var url = "https://hns.d7u.de/v4/images/hvvstoerungen_facebook.png";
var directory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/myapp/";
var fileName = url.Substring(url.LastIndexOf("/") +1);
var path = directory + fileName;
System.Net.WebClient wC = new System.Net.WebClient();
wC.Headers.Add(System.Net.HttpRequestHeader.AcceptEncoding, "gzip");
wC.DownloadDataCompleted += WC_DownloadDataCompleted;
wC.DownloadDataAsync(new Uri(url), path);
}
private void WC_DownloadDataCompleted(object sender, System.Net.DownloadDataCompletedEventArgs e)
{
var path = e.UserState.ToString();
var bytes = e.Result;
if (File.Exists(path))
File.Delete(path);
if (!File.Exists(path))
File.WriteAllBytes(path, bytes);
}
It is stored at /data/user/0/myapp/files/hns/hvvstoerungen_facebook.png and a File.Exists(...) returns a true for that path. So I am sure, that the file is downloaded and it exists.
When I want to show it in the ImageView, I do it like this:
if (System.IO.File.Exists(imageFilePath))
{
Android.Net.Uri andrUri = Android.Net.Uri.Parse(imageFilePath);
ImageIcon.SetImageURI(andrUri);
//Also not working:
//Bitmap bitmap = BitmapFactory.DecodeFile(imageFilePath);
//ImageIcon.SetImageBitmap(bitmap);
//And also not working:
//Android.Net.Uri andrUri = Android.Net.Uri.Parse(imageFilePath);
//Bitmap bmp = BitmapFactory.DecodeStream(Android.App.Application.Context.ContentResolver.OpenInputStream(andrUri));
//ImageIcon.SetImageBitmap(bmp);
}
The Output windows shows the following when the image should be shown:
02-01 23:41:24.770 E/Drawable(19815): Unable to decode stream:
android.graphics.ImageDecoder$DecodeException: Failed to create image
decoder with message 'unimplemented'Input contained an error. 02-01
23:41:24.770 W/ImageView(19815): resolveUri failed on bad bitmap uri:
/data/user/0/myapp/files/hns/hvvstoerungen_facebook.png
But I cannot figured out what exactly this means.
One additional thing is: If I run the app in a brand new Android Emulator instance, this image and all other of its kind are not shown.
If I run the app in an old Android Emulator instance, where the app was already running before but on Android.Forms basis, the old images that were known by the old project are shown while the newly downloaded images are not. All images are in the same folder and I cannot see any differences between them.
Does anyone has an Idea?
Edit:
My working version has the following Download() Method instead:
private void Download()
{
var noCompression = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".zip", ".7z", ".mp3", ".mp4" };
var url = "https://hns.d7u.de/v4/images/hvvstoerungen_facebook.png";
var directory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/myapp/";
var fileName = url.Substring(url.LastIndexOf("/") +1);
var path = directory + fileName;
System.Net.WebClient wC = new System.Net.WebClient();
if (!noCompression.Contains(url.Substring(url.LastIndexOf('.'))))
wC.Headers.Add(System.Net.HttpRequestHeader.AcceptEncoding, "gzip");
wC.DownloadDataCompleted += WC_DownloadDataCompleted;
wC.DownloadDataAsync(new Uri(url), path);
}
You could try the code below.
Download the image from Url:
public Bitmap GetImageBitmapFromUrl(string url)
{
Bitmap imageBitmap = null;
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
return imageBitmap;
}
Usage:
bitmap = GetImageBitmapFromUrl("https://hns.d7u.de/v4/images/hvvstoerungen_facebook.png");
And save the image as png:
void ExportBitmapAsPNG(Bitmap bitmap)
{
var folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
filePath = System.IO.Path.Combine(folderPath, "test.png");
var stream = new FileStream(filePath, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Png, 100, stream);
stream.Close();
}
Usage:
ExportBitmapAsPNG(bitmap);
Check the file exists or not and set into the imageview:
if (File.Exists(filePath))
{
Bitmap myBitmap = BitmapFactory.DecodeFile(filePath);
imageview.SetImageBitmap(myBitmap);
}
I've seen this question asked here already : Web Audio API Memory Leaks on Mobile Platforms but there doesn't seem to be any response to it. I've tried lots of different variations - setting variables to null once I'm finished with them, or declaring the variables within scope, but it appears that the AudioContext (or OfflineAudioContext ) is not being Garbage collected after each operation. I'm using this with Phonegap, on an IOS, so the browser is safari. Any ideas how to solve this memory leak?
Here is my code:
function readVocalsToBuffer(file){
console.log('readVocalsToBuffer');
var reader = new FileReader();
reader.onloadend = function(evt){
var x = audioContext.decodeAudioData(evt.target._result, function(buffer){
if(!buffer){
console.log('error decoding file to Audio Buffer');
return;
}
window.voiceBuffer = buffer;
loadBuffers();
});
}
reader.readAsArrayBuffer(file);
}
function loadBuffers(){
console.log('loadBuffers');
try{
var bufferLoader = new BufferLoader(
audioContext,
[
"."+window.srcSong
],
createOffLineContext
);
bufferLoader.load()
}
catch(e){
console.log(e.message);
}
}
function createOffLineContext(bufferList){
console.log('createOfflineContext');
offline = new webkitOfflineAudioContext(2, window.voiceBuffer.length, 44100);
var vocalSource = offline.createBufferSource();
vocalSource.buffer = window.voiceBuffer;
vocalSource.connect(offline.destination);
var backing = offline.createBufferSource();
backing.buffer = bufferList[0];
backing.connect(offline.destination);
vocalSource.start(0);
backing.start(0);
offline.oncomplete = function(ev){
vocalSource.stop(0);
backing.stop(0);
vocalSource.disconnect(0);
backing.disconnect(0);
delete vocalSource;
delete backing;
delete window.voiceBuffer;
window.renderedFile = ev.renderedBuffer;
var bufferR = ev.renderedBuffer.getChannelData(0);
var bufferL = ev.renderedBuffer.getChannelData(1);
var interleaved = interleave(bufferL, bufferR);
var dataview = encodeWAV(interleaved);
window.audioBlob = new Blob([dataview], {type: 'Wav'});
saveFile();
}
offline.startRendering();
}
function interleave(inputL, inputR){
console.log('interleave');
var length = inputL.length + inputR.length;
var result = new Float32Array(length);
var index = 0,
inputIndex = 0;
while (index < length){
result[index++] = inputL[inputIndex];
result[index++] = inputR[inputIndex];
inputIndex++;
}
return result;
}
function saveFile(){
offline = null;
console.log('saveFile');
delete window.renderedFile;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFSSuccess, fail);
}
I've been trying to save file from server to an ios device using urlstream but it doesn't work (it works fine on android devices . I tried using(documentsDirectory) but it doesn't work too .I used many other methods like (file.download ) and others but none is working . Any help please
I am using flash pro cs6 .
script sample :
import flash.filesystem.*;
import flash.events.ProgressEvent;
var urlString:String = "http://example.sample.mp3";
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
urlStream.load(urlReq);
function loaded(event:Event):void {
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
writeAirFile();
}
function writeAirFile():void {
var file:File = File.applicationStorageDirectory.resolvePath("sample.mp3");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(fileData, 0, fileData.length);
fileStream.close();
trace("The file is written.");
}
function progressHandler(event:Event):void {
trace ("progressHandler: " + event);
}
Tested on iOS
_urlString = "http://example.sample.mp3";
_urlReq = new URLRequest(_urlString);
_urlStream = new URLStream();
_urlStream.addEventListener(flash.events.ProgressEvent.PROGRESS, progressHandler, false, 0, true);
_urlStream.addEventListener(flash.events.Event.COMPLETE, saveFileToDisc, false, 0, true);
_urlStream.addEventListener(flash.events.IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
_urlStream.load(_urlReq);
private function progressHandler(evt:flash.events.ProgressEvent):void {
trace("progress: " + event.target.progress);
}
private function errorHandler(evt:flash.events.IOErrorEvent):void {
//do something
}
private function saveFileToDisc(event:flash.events.Event):void {
_fileData = new ByteArray();
_urlStream.readBytes(_fileData, 0, _urlStream.bytesAvailable);
_file = File.applicationStorageDirectory.resolvePath("sample.mp3");
_file.preventBackup = true;
_writeFileStream.addEventListener(flash.events.IOErrorEvent.IO_ERROR, filestreamErrorHandler, false, 0, true);
_writeFileStream.addEventListener(flash.events.Event.CLOSE, fileSaved, false, 0, true);
_writeFileStream.openAsync(_file, FileMode.UPDATE);
_writeFileStream.writeBytes(_fileData, 0, _fileData.length);
_writeFileStream.close();
}
private function filestreamErrorHandler(evt:flash.events.IOErrorEvent):void {
//do something
}
private function fileSaved(closeEvent:flash.events.Event):void {
//trace("file saved");
_writeFileStream.removeEventListener(flash.events.IOErrorEvent.IO_ERROR, filestreamErrorHandler);
_writeFileStream.removeEventListener(flash.events.Event.CLOSE, fileSaved);
_urlString = null;
_urlReq = null;
_urlStream = null;
_file = null;
_fileData.length = 0;
_fileData = null;
}
Two obvious problems:
This line: urlStream..addEventListener(ProgressEvent.PROGRESS, progressHandler); has ' .. ' which is wrong.
Also you never write anything into your ByteArray.
set the 3rd parameter to 0 to make sure to read the entire data:
urlStream.readBytes(fileData, 0, 0); //0 = read all
Besides URLStream is not meant for that type of operation (it is meant to stream the loading of binary data). I personally do this using URLLoader (loading in binary) and everything works perfectly and save copy on folder.
I'm using the AS3 code below to take a photo throught the cameraUI. Everything works fine on the Android but when I test on the iPad I get an error when trying to load the saved image. The ioErrorHandler1 returns:
ioErrorHandler: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2124: Loaded file is an unknown type. URL: app-storage:/myImage.jpg" errorID=2124]
Anyone know why? (as mentioned it works on Android). Here's the code:
function imageCaptured( event:MediaEvent ):void
{
trace( "Media captured..." );
var imagePromise:MediaPromise = event.data;
dataSource = imagePromise.open();
if( imagePromise.isAsync )
{
trace( "Asynchronous media promise." );
eventSource = dataSource as IEventDispatcher;
imageLoader = new Loader();
imageLoader.contentLoaderInfo.addEventListener( Event.COMPLETE, asyncImageLoaded );
imageLoader.addEventListener( IOErrorEvent.IO_ERROR, cameraError );
imageLoader.loadFilePromise( imagePromise );
}
else
{
trace( "Synchronous media promise." );
imageLoader.loadFilePromise( imagePromise );
showMedia( imageLoader );
}
}
function asyncImageLoaded( event:Event ):void
{
readMediaData();
}
function readMediaData():void
{
var image:Bitmap = Bitmap(imageLoader.content);
var bitmap:BitmapData = image.bitmapData;
image.width = 100;
image.height = 100;
this.addChild(image);
var imageBytes:ByteArray = new ByteArray();
dataSource.readBytes( imageBytes );
var file:File = File.applicationStorageDirectory.resolvePath("myImage.jpg");
// create a file stream
var fs:FileStream=new FileStream();
// open the stream for writting
fs.openAsync(file, FileMode.WRITE);
// write the string data down to the file
fs.writeBytes(imageBytes);
// ok close the file stream
fs.close();
fs.addEventListener(Event.CLOSE,function(event:Event):void {
var mLoader=new Loader();
var mRequest:URLRequest = new URLRequest(file.url);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (event:Event):void{
showMediaLoad(mLoader);
});
mLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler1);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
mLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
mLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
mLoader.load(mRequest);
})
trace("saved");
}
You might need to encode your ByteArray before saving it as a jpeg.
Here's a snippet of code I used a while back...
import com.adobe.images.JPGEncoder;
private var f:File;
private var stream:FileStream;
private var j:JPGEncoder;
private var image:Bitmap = Bitmap(imageLoader.content);
private var urlRequest:URLRequest;
private var loader:Loader;
function saveImage():void {
f = File.documentsDirectory.resolvePath("logo.jpg");
stream = new FileStream();
stream.open(f, FileMode.WRITE);
j = new JPGEncoder(80);
var bytes:ByteArray = j.encode(image.bitmapData);
stream.writeBytes(bytes, 0, bytes.bytesAvailable);
stream.close();
stream.openAsync(f, FileMode.READ);
stream.addEventListener(Event.COMPLETE, loadImage, false, 0, true);
}
private function loadImage(e:Event):void {
stream.removeEventListener(Event.COMPLETE, loadImage);
stream = null;
//now load the image
if (f.exists == true) {
urlRequest = new URLRequest(f.url);
loader = new Loader;
loader.load(urlRequest);
loader.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent):void{ trace(e) });
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, ImageLoaded, false, 0, true);
}
}
private function ImageLoaded(e:Event):void {
addChild(loader);
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, ImageLoaded);
}
I found a solution. It works without jpgencoder if I put an eventlistener on the eventSource. I'm posting it here if anyone else could use the solution:
The imageCaptured function is updated like this:
if( imagePromise.isAsync )
{
trace( "Asynchronous media promise." );
var eventSource:IEventDispatcher = dataSource as IEventDispatcher;
eventSource.addEventListener( Event.COMPLETE, onMediaLoaded );
}
And then the image is save in this function:
function onMediaLoaded( event:Event ):void
{
trace("Media load complete");
var imageBytes:ByteArray = new ByteArray();
dataSource.readBytes( imageBytes );
var file:File = File.applicationStorageDirectory.resolvePath("myImage.jpg");
// create a file stream
var fs:FileStream=new FileStream();
// open the stream for writting
fs.openAsync(file, FileMode.WRITE);
// write the string data down to the file
//fs.writeBytes(imageBytes);
fs.writeBytes(imageBytes);
// ok close the file stream
fs.close();
fs.addEventListener(Event.CLOSE, function(e:Event):void {
var mLoader=new Loader();
var mRequest:URLRequest = new URLRequest(file.url);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (event:Event):void{
showMediaLoad(mLoader);
});
mLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler1);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
mLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
mLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
mLoader.load(mRequest);
}
Does anyone have any experience with the Camera APIs in Flex 4.6 with iOS? I'm running into a lot of setup issues and the documentation is lacking. I'm trying to setup an image upload component where a user can either capture a new photo or choose an existing from their library.
For capturing, there seems to be a huge hang (like 10 seconds where the app just sits non-responsive) when the image is being saved as a JPEG, and I'm using the Alchemy swc.
private var cam:CameraUI;
protected function takePhotoHandler(event:MouseEvent):void
{
if(CameraUI.isSupported) {
cam = new CameraUI();
cam.addEventListener(MediaEvent.COMPLETE, mediaEventComplete);
cam.launch(MediaType.IMAGE);
}
}
protected function mediaEventComplete(e:MediaEvent):void
{
cam.removeEventListener(MediaEvent.COMPLETE, mediaEventComplete);
status.text = "Media captured..." ;
var imagePromise:MediaPromise = e.data;
var loader:Loader = new Loader();
if(imagePromise.isAsync) {
status.text = "Asynchronous media promise." ;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, asyncImageLoadHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, asyncImageErrorHandler);
loader.loadFilePromise(imagePromise);
} else {
status.text = "Synchronous media promise.";
loader.loadFilePromise(imagePromise);
img.source = loader.content;
saveImage(loader.contentLoaderInfo);
}
}
protected function asyncImageLoadHandler(e:Event):void
{
status.text = "Media loaded in memory.";
img.source = e.currentTarget.loader.content;
saveImage(e.currentTarget.loader.contentLoaderInfo);
}
protected function saveImage(loaderInfo:LoaderInfo):void
{
if(CameraRoll.supportsAddBitmapData){
var bitmapData:BitmapData = new BitmapData(loaderInfo.width, loaderInfo.height);
bitmapData.draw(loaderInfo.loader);
d_trace("bitmapDraw");
//var c:CameraRoll = new CameraRoll();
//c.addBitmapData(bitmapData);
d_trace("writing to disk");
var f:File = File.applicationStorageDirectory.resolvePath("temp");
var stream:FileStream = new FileStream()
stream.open(f, FileMode.WRITE);
d_trace("encoding start");
var baSource: ByteArray = bitmapData.clone().getPixels( new Rectangle( 0, 0, loaderInfo.width, loaderInfo.height) );
var bytes: ByteArray = as3_jpeg_wrapper.write_jpeg_file(baSource, loaderInfo.width, loaderInfo.height, 3, 2, 80);
d_trace("encoding end");
stream.writeBytes(bytes,0,bytes.bytesAvailable);
stream.close();
d_trace(f.url);
img.source = f.url;
d_trace("UPLOADING START");
f.addEventListener(Event.COMPLETE,uploadCompleteHandler);
f.addEventListener(Event.OPEN,openUploadHandler);
f.upload(urlRequest);
}
}
For choosing from the library, I can't get a file reference to actually start the upload. When the select is made, the mediaPromise.file value is null. mediaPromise.isAsync is true and I can attach a loader listener but that only returns the contentLoaderInfo, which has no reference to the actual File or a FileRefernce, so I can't call the upload method without creating a temp image, which seems expensive and crazy.
protected function chooseImage(): void {
if(CameraRoll.supportsBrowseForImage) {
var roll: CameraRoll = newCameraRoll();
roll.addEventListener( MediaEvent.SELECT, roll_selectHandler );
var options:CameraRollBrowseOptions = new CameraRollBrowseOptions();
roll.browseForImage(options);
}}
private function roll_selectHandler( event: MediaEvent ): void
{
var imagePromise:MediaPromise = event.data;
if(imagePromise.isAsync) {
// Here's where I get. Not sure how to get the reference to the file I just selected.
}}
Any help would be appreciated.
Thanks!
I think I found a solution for works for my case so I wanted to share it in case it can help someone out. shaunhusain's post definitely got me moving in the right direction. I was able to avoid using the Alchemy swc all together which saves a TON of time in the app. The key is this AS3 library I found that formats a URLRequest in a way that mimics a standard file upload POST operation. Here's the basic outline:
I have a small component called 'status' thats an overlay with an icon and status text for the user. When a user wants to add a photo, they get a ViewMenu with the choices to get the photo from their library or take a new photo. The meat of the code is below.
//IMAGE HANDLING
//Helpful Links:
//http://www.quietless.com/kitchen/dynamically-create-an-image-in-flash-and-save-it-to-the-desktop-or-server/
//http://stackoverflow.com/questions/597947/how-can-i-send-a-bytearray-from-flash-and-some-form-data-to-php
// GET WRAPPER CLASS Here: http://code.google.com/p/asfeedback/source/browse/trunk/com/marston/utils/URLRequestWrapper.as
//This part is basically all based on http://www.adobe.com/devnet/air/articles/uploading-images-media-promise.html
protected var cameraRoll:CameraRoll = new CameraRoll();
//User choose to pick a photo from their library
protected function chooseImage():void {
if( CameraRoll.supportsBrowseForImage )
{
cameraRoll.addEventListener( MediaEvent.SELECT, imageSelected );
cameraRoll.addEventListener( Event.CANCEL, browseCanceled );
cameraRoll.addEventListener( ErrorEvent.ERROR, mediaError );
cameraRoll.browseForImage();
} else {
trace( "Image browsing is not supported on this device.");
}
}
//User choose to take a new photo!
protected var cameraUI:CameraUI = new CameraUI();
protected function captureImage():void
{
if( CameraUI.isSupported )
{
trace( "Initializing..." );
cameraUI.addEventListener( MediaEvent.COMPLETE, imageSelected );
cameraUI.addEventListener( Event.CANCEL, browseCanceled );
cameraUI.addEventListener( ErrorEvent.ERROR, mediaError );
cameraUI.launch( MediaType.IMAGE );
} else {
trace( "CameraUI is not supported.");
}
}
private function browseCanceled (e:Event):void
{
trace ("Camera Operation Cancelled");
}
private function mediaError (e:ErrorEvent):void
{
trace ("mediaError");
}
private var dataSource:IDataInput;
private function imageSelected( event:MediaEvent ):void
{
trace( "Media selected..." );
var imagePromise:MediaPromise = event.data;
dataSource = imagePromise.open();
if( imagePromise.isAsync )
{
trace( "Asynchronous media promise." );
var eventSource:IEventDispatcher = dataSource as IEventDispatcher;
eventSource.addEventListener( Event.COMPLETE, onMediaLoaded );
} else {
trace( "Synchronous media promise." );
readMediaData();
}
}
private function onMediaLoaded( event:Event ):void
{
trace("Media load complete");
readMediaData();
}
private function readMediaData():void
{
var imageBytes:ByteArray = new ByteArray();
dataSource.readBytes( imageBytes );
upload(imageBytes);
}
//OK Here's where it gets sent. Once the IDataInput has read the bytes of the image, we can send it via our custom URLRequestWrapper
//which will format the request so the server interprets it was a normal file upload. Your params will get encoded as well
//I used Uploadify this time but I've used this Wrapper class in other projects with success
protected function upload( ba:ByteArray, fileName:String = null ):void
{
if( fileName == null ) //Make a name with correct file type
{
var now:Date = new Date();
fileName = "IMG" + now.fullYear + now.month +now.day +
now.hours + now.minutes + now.seconds + ".jpg";
}
var loader:URLLoader = new URLLoader();
loader.dataFormat= URLLoaderDataFormat.BINARY;
var params:Object = {};
params.name = fileName;
params.user_id = model.user.user_id;
var wrapper:URLRequestWrapper = new URLRequestWrapper(ba, fileName, null, params);
wrapper.url = "http://www.your-domain.com/uploadify.php";
loader.addEventListener( Event.COMPLETE, onUploadComplete );
loader.addEventListener(IOErrorEvent.IO_ERROR, onUploadError );
loader.load(wrapper.request);
}
private function onUploadComplete(e:Event):void
{
trace("UPLOAD COMPLETE");
var bytes:ByteArray = e.currentTarget.data as ByteArray;
//Most likely you'd want a server response. It will be returned as a ByteArray, so you can get back to the string:
trace("RESPONSE", bytes.toString());
}
private function onUploadError(e:IOErrorEvent):void
{
trace("IOERROR", e.text);
}