flex FileReference load complete event never fired - apache-flex

I have an image which will be uploaded twice by flash. Besides, I'll do some resizing & compression stuff. So I have to load the data and create a BitmapData object.
_fileRef.addEventListener(Event.Complete, onLoadComplete);
_fileRef.load();
The problem is the complete event is never fired which could be checked from log message in console. What are the possibilities that such an event failed to be triggered?
my real code is shown as below:
private function prepareImage():void
{
_compressionFactor = 82;
if(as3_jpeg_wrapper==null)
{
as3_jpeg_wrapper = clibinit.init();
}
_fileRef.addEventListener(Event.COMPLETE, onImageComplete);
_fileRef.load();
}
private var tempLoader:Loader;
private var tempData:ByteArray;
private function onImageComplete(event:Event):void
{
Utils.log("loading data completed");
tempData = event.currentTarget.data;
_fileRef.removeEventListener(Event.COMPLETE,onImageComplete);
tempLoader = new Loader;
tempLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,onImageLoaded);
tempLoader.loadBytes(tempData);
}
The fact is that the log message "loading data completed" is never printed. I've traced the whole process, flash stucked here. The function prepareImage is called via:
Utils.log("We'll resize & compress the picture to be uploaded");
prepareImage();

Related

Activity Indicator is not visible on xaml page in xamarin.forms?

I have an activity indicator on xaml page. Initially its IsVisible property is false. I have a button on page. When user click on button it calls a web service to get data. I change the value of IsVisible property to true before calling the service so that activity indicator starts to display on page and after successful calling of service I change its value to again false so that it doesn't show any more on page.
But it is not working. I know the actual problem. When we call the web service the UI thread gets block and it doesn't show the activity indicator.
How I can enable the UI thread when web service gets called so that activity indicator can show on page until we get the data?
Try making your webservice call into an async and await it.
Depending on how you've structured things you may have to use a TaskCompletionSource as the following example demonstrates.
In this example when the button is clicked, the button is made invisible, and the ActivityIndicator is set to IsRunning=True to show it.
It then executes your long running task / webservice in the function ExecuteSomeLongTask using a TaskCompletionSource.
The reason for this is that in our button click code, we have the final lines:-
objActivityIndicator1.IsRunning = false;
objButton1.IsVisible = true;
That stop the ActivityIndicator from running and showing, and also set the button back to a visible state.
If we did not use a TaskCompletionSource these lines would execute immediately after calling the ExecuteSomeLongTask if it was a normal async method / function, and would result in the ActivityIndicator not running and the button still being visible.
Example:-
Grid objGrid = new Grid()
{
};
ActivityIndicator objActivityIndicator1 = new ActivityIndicator();
objGrid.Children.Add(objActivityIndicator1);
Button objButton1 = new Button();
objButton1.Text = "Execute webservice call.";
objButton1.Clicked += (async (o2, e2) =>
{
objButton1.IsVisible = false;
objActivityIndicator1.IsRunning = true;
//
bool blnResult = await ExecuteSomeLongTask();
//
objActivityIndicator1.IsRunning = false;
objButton1.IsVisible = true;
});
objGrid.Children.Add(objButton1);
return objGrid;
Supporting function:-
private Task<bool> ExecuteSomeLongTask()
{
TaskCompletionSource<bool> objTaskCompletionSource1 = new TaskCompletionSource<bool>();
//
Xamarin.Forms.Device.StartTimer(new TimeSpan(0, 0, 5), new Func<bool>(() =>
{
objTaskCompletionSource1.SetResult(true);
//
return false;
}));
//
return objTaskCompletionSource1.Task;
}
You need to do your work in an asynchronous way. Or in other words: Use Asnyc & Await to ensure, that you UI works well during the call.
You can find more informations in the Xamarin Docs.
async and await are new C# language features that work in conjunction
with the Task Parallel Library to make it easy to write threaded code
to perform long-running tasks without blocking the main thread of your
application.
If you need further asistance, please update your question and post your code or what you have tried so far.

Titanium - Webview is not rendered when is loaded by async callback

I have loop that for each item that call a async request to server, create a view with a webview for later add in a scrollview after calc the positions. In the callback, I get the server data and give to webview.
When the load method takes a little longer to perform (In a slow connection, for example), the webview is not rendered.
This happens many times in the device, but few times in the simulator. But, to simulate easily, just put a breakpoint in the load method, delaying the execution.
I suspect that there is a problem when rendering an already added webview.
I simplified the code in a one block for better understanding:
function createView(){
var view = Ti.UI.createView({
//...
});
var webview = Ti.UI.createWebView({});
view.add(webview);
//Callback to process webview content after receive the server data
view.load = function(serverData){
webview.setUrl(serverData.url);
webview.addEventListener('beforeload', function(){
webview.evalJS("var value="+serverData.value+";");
});
};
return view;
};
var views = new Array();
for(i=0;i < data.length;i++){
views[i] = createView();
//Async request to server
var req = Ti.Network.createHTTPClient();
req.onload = function(){
result = JSON.parse(this.responseText);
views[i].load(result);
}
req.open("POST", "http://myserver.com.br/myservice");
req.send({myParam: data[i].value});
}
var scrollView = Ti.UI.createScrollView({
//...
});
for(i=0;i < views.length;i++){
//Calc the positions, not relevant
views[i].width = calculedValue;
views[i].height = calculedValue;
scrollView.add(views[i]);
}
win.add(scrollView);
Im using Titanium SDK 1.8.2 and running on iPad 2 with iOS 5.0.1.
I solved the problem evaluating the javascript data on the callback instead of on event listener
view.load = function(serverData){
webview.setUrl(serverData.url);
//Not on event 'beforeload'
//webview.addEventListener('beforeload', function(){ not on
webview.evalJS("var value="+serverData.value+";");
//});
};
I think that this is related with the UI thread is not called sometimes on event listener

FileReference.download() not working

I'm building a Flex app which requires me to download files.
I have the following code:
public function execute(event:CairngormEvent) : void
{
var evt:StemDownloadEvent = event as StemDownloadEvent;
var req:URLRequest = new URLRequest(evt.data.file_path);
var localRef:FileReference = new FileReference();
localRef.addEventListener(Event.OPEN, _open);
localRef.addEventListener(ProgressEvent.PROGRESS, _progress);
localRef.addEventListener(Event.COMPLETE, _complete);
localRef.addEventListener(Event.CANCEL, _cancel);
localRef.addEventListener(Event.SELECT, _select);
localRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityError);
localRef.addEventListener(IOErrorEvent.IO_ERROR, _ioError);
try {
localRef.download(req);
} catch (e:Error) {
SoundRoom.logger.log(e);
}
}
As you can see, I hooked up every possible event listener as well.
When this executes, I get the browse window, and am able to select a location, and click save. After that, nothing happens.
I have each event handler hooked up to my logger, and not a single one is being called! Is there something missing here?
The problem seems to be with my command being destroyed before this could finish.
For a proof of concept, I set my localRef variable to be static instead of an instance variable, and everything went through successfully! I guess Cairngorm commands kill themselves asap!

AS3: Loading bytes from multiple sources

I am loading multiple images into a class instance and I would like to keep track of how large the complete amount of loaded data is at any given point.
I have grabbed the totalbytes from my directory of images via a PHP script... but collecting the new bytes from the ProgressEvent on each image seems tricky for some reason.
Let's assume that the totalBytes variable is correct and that I am totally unfamiliar with the way that ProgressEvent works...
Does an event get fired every time ProgressEvent gets a new byte?
If not, how do I keep track of the current total bytes?
I'm sure I've got it wrong, but here's what I am trying:
public function thumbProgress(e:ProgressEvent):void
{
//trying to check for a new data amount, in case the progress event updates
//insignificantly
if(e.bytesLoaded != this.newByte)
{
this.newByte = this.currentLoadedBytes - e.bytesLoaded;
this.currentLoadedBytes += this.newByte;
this.textprog.text = this.currentLoadedBytes.toString() + " / " + this.totalBytes.toString();
this.newByte = e.bytesLoaded;
}
if(this.currentLoadedBytes >= this.totalBytes)
{
this.textprog.text = "done loading.";
}
}
Are you using a flash.display.Loader to load your images? Then you can use the Loader.contentLoaderInfo.bytesTotal property, which should contain the right number of bytes once the image has finished loading. The Loader.contentLoaderInfo property references the LoaderInfo instance of the loaded content, which contains a lot of data about the file, such as total size, the amount that have finished loading, and the URL from which it was loaded. Check out the LoaderInfo reference.
Sum the values of this property for all of your loaders, to get the total amount of loaded data, e.g. in the COMPLETE handler for each loader.
Cheers
Maybe this isn't exactly an answer to your question, but I suggest that you take a look at bulk-loader library. It will greatly simplify loading multiple assets. Here is a quick and dirty example of usage. We've got simple application with progressbar and we want to update progressbar as images are downloaded.
<mx:Script>
<![CDATA[
import br.com.stimuli.loading.BulkProgressEvent;
import br.com.stimuli.loading.BulkLoader;
private function init():void {
loadImages();
}
private function loadImages():void {
var loader : BulkLoader = new BulkLoader("main-site");
loader.add("http://www.travelblog.org/Wallpaper/pix/tb_turtle_diving_sipadan_malaysia.jpg", {id:"a"});
loader.add("http://www.travelblog.org/Wallpaper/pix/tb_fiji_sunset_wallpaper.jpg", {id:"b"});
loader.addEventListener(BulkLoader.COMPLETE, onAllLoaded);
loader.addEventListener(BulkLoader.PROGRESS, onAllProgress);
loader.addEventListener(BulkLoader.ERROR, onAllError);
loader.start();
}
private function onAllLoaded(evt : BulkProgressEvent):void {
}
private function onAllProgress(evt : BulkProgressEvent):void {
progressBar.setProgress(evt.ratioLoaded * 100, progressBar.maximum);
}
private function onAllError():void {
}
]]>
</mx:Script>
<mx:ProgressBar x="304" y="360" width="582" id="progressBar" mode="manual" minimum="0" maximum="100"/>

Flex 3 multiple upload progress monitoring

I have a Flex3 application which has to be capable of uploading multiple files and monitoring each files individual progress using a label NOT a progress bar.
My problem is that a generic progress handler for the uploads has no way (that I know of) of indicating WHICH upload it is that is progressing. I know that a file name is available to check but in the case of this app the file name might be the same for multiple uploads.
My question: With a generic progress handler how does one differentiate between 2 multiple uploads with the same file name?
EDIT: answerers may assume that I am a total newb to Flex... because I am.
I use this:
private function _addFileListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.OPEN, this._handleFileOpen);
dispatcher.addEventListener(Event.SELECT, this._handleFileOpen);
dispatcher.addEventListener(Event.CANCEL, this._handleFileCancel);
dispatcher.addEventListener(ProgressEvent.PROGRESS, this._handleFileProgress);
dispatcher.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,this._handleFileComplete);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, this._handleError);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this._handleError);
}
where "dispatcher" is the file:
for (var i:uint = 0; i < fileList.length; i++) {
file = FileReference(fileList[i]);
this._addFileListeners(file);
this._pendingFiles.push(file);
}
and a sample handler:
private function _handleFileOpen(e:Event):void {
var file:FileReference = FileReference(e.target);
...
}
I'm not sure how you want to differentiate between two files with the same name. In my case, I send the files in a queue. So there's only ever 1 file being uploaded at a time. (pendingFiles).
If you are listening for ProgressEvents, these events have a currentTarget attribute that would have a reference to the object that has registered the event listener.
I'm assuming you know which file-uploading object goes with each object in the first place.
EDIT: Example using FileReference:
import flash.net.FileReference;
import flash.events.ProgressEvent;
import flash.utils.Dictionary;
public var files:Dictionary = new Dictionary(); // This will hold all the FileReference objects
public function loadFile(id:String):void
{
var file:FileReference = new FileReference();
// Listen for the progress event on this FileReference... will call the same function for every progress event
file.addEventListener(ProgressEvent.PROGRESS, onProgress);
// TODO: listen for errors and actually upload a file, etc.
// Add file to the dictionary (as key), with value set to an object containing the id
files[file] = { 'id': id };
}
public function onProgress(event:ProgressEvent):void
{
// Determine which FileReference dispatched thi progress event:
var file:FileReference = FileReference(event.target);
// Get the ID of the FileReference which dispatched this function:
var id:String = files[file].id;
// Determine the current progress for this file (in percent):
var progress:Number = event.bytesLoaded / event.bytesTotal;
trace('File "' + id + '" is ' + progress + '% done uploading');
}
// Load some files:
loadFile('the first file');
loadFile('the second file');
I ended up creating my own class that manages events for each uploading file

Resources