URLRequest or Loader simply not working on some computers? - actionscript-3

So my problem may be a little bigger than that, but I'm not certain. I'm creating a custom flash photo viewer for a client that dynamically loads the images with Loader objects. It takes a folder name in a specified directory on the server and calls a php page (using URLRequest) to get the workable contents of the folder. And then it loads it up from that array.
Here's the problem: it works FINE on my machine and every machine I've tested it on, but it DOESN'T work on my client's machine or some of his customer's machines. The loader bar that's at the bottom of the screen doesn't start to fill, which means that the images aren't starting to even load, and the status bar indicates that it continues to wait for a the server, yet never finishes waiting. This is consistent on a single machine, but varies across machines.
I've added diagnostics (a custom class I made to track certain vars and collect errors) to the thing to catch any errors, but it reports nothing on my client's machine. I've added flash version checking code, so the possibility of a lower version messing it up is gone...
I guess my question is, is there anything (security, environment, etc) that I could have overlooked that doesn't allow request objects or something to work on certain machines?? I've been ripping my hair out trying to figure this out!
My code (relevant sections):
public static const LOADLIMIT:int = 4;
public var paramObj:Object;
private var imageRequests:Vector.<URLRequest>;
private var loaderObj:Vector.<Loader>;
private var nextToLoad:int = -1;
//...
public function Player(){
//...
paramObj = loaderInfo.parameters;
if (!paramObj.root) paramObj.root = "http://site.com/images/";
paramObj.imgloc = paramObj.imgloc;
var res = bootstrapImages(paramObj.imgloc);
if (res is String){
loadErrorMsg.text = res;
loadErrorMsg.visible = true;
log.log(res);
}
//...
}
private function bootstrapImages(imgloc:String):*{
try{
if (!imgloc) return "No image location specified";
var req:URLRequest = new URLRequest(paramObj.root+"getdirlist.php?name="+imgloc);
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, directoryLoaded);
loader.addEventListener(IOErrorEvent.IO_ERROR, function(ex:IOError){
loadErrorMsg.text = "Error retreiving album data.";
loadErrorMsg.visible = true;
log.log(ex);
});
loader.load(req);
} catch (ex:Error){
log.log(ex); throw ex;
}
}
private function directoryLoaded(e:Event){
try{
//directory will come down as a json array
trace(e.target.data);
try {
var items:Array = JSON.decode(e.target.data);
} catch (ex:Error){
trace (ex.getStackTrace());
loadErrorMsg.text = "Error parsing album data.";
loadErrorMsg.visible = true;
log.log(ex);
return;
}
if (items.length == 0){
loadErrorMsg.text = "Invalid album name";
loadErrorMsg.visible = true;
log.log("Items length is 0.");
return;
}
imageRequests = new Vector.<URLRequest>();
loaderObj = new Vector.<Loader>();
for each(var item:String in items){
imageRequests.push(new URLRequest(paramObj.root+"coffeeimages/"+paramObj.imgloc+"/"+item));
loaderObj.push(null);
}
//...show UI...
for (var i:int = 0; i < LOADLIMIT; i++){
imageLoaded(null);
}
} catch (ex:Error){
log.log(ex); throw ex;
}
}
private function imageLoaded(e:Event){
try{
//if this was called as a result of the load event, start the slideshow! :D
if (e != null && e.target != null) {
//stage.addChild((e.target as LoaderInfo).loader);
trace(loaderObj[0]);
if (loaderObj[0] != null && //if the first image is loaded
loaderObj[0].contentLoaderInfo.bytesLoaded >= loaderObj[0].contentLoaderInfo.bytesTotal){
trace(loaderObj[0].contentLoaderInfo.bytesLoaded, loaderObj[0].contentLoaderInfo.bytesTotal);
loadErrorMsg.visible = false;
playSlideshow(true);
}
}
trace((e)?e.target:null, loaderObj);
nextToLoad++;
if (nextToLoad >= imageRequests.length) return;
var r:URLRequest = imageRequests[nextToLoad];
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(ex:ErrorEvent){
loadErrorMsg.text = "Error parsing image data.";
loadErrorMsg.visible = true;
log.log(ex);
});
l.load(r);
loaderObj[nextToLoad] = l;
log.addObjectWatch(l);
} catch (ex:Error){
log.log(ex); throw ex;
}
}
Also, here's the player live on the site. Ctrl+Alt+Home brings up my diagnostics panel. Please tell me if it doesn't work for you as well, so I can be more worried about this... :/ Thanks.
Edit: I have added more debugging information. Turns out that on the computers that cannot load it, they are getting an HTTP status 0 returned when trying to bootstrap the album information. I have no idea what that means...

So, the problem was a matter of the URL its requesting...
My client was typing "www.site.com", while my code was requesting to "site.com". To Adobe, this is a cross site request, and NOT ALLOWED by default. One solution (and probably the easiest one) is to add a file called "crossdomain.xml" to the root folder of the website. Flash looks for this file when making a request. One example that worked for me is as follows:
//crossdomain.xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.site.com" secure="false"/>
</cross-domain-policy>
Other solutions involve redirecting to one of the two ("site.com" redirects to "www.site.com"), or doing url rewriting, or getting url that they entered.

A few things I noticed, you are only listening for Event.COMPLETE and IOErrorEvent.IO_ERROR. I'd suggest also listening for HTTPStatusEvent.HTTP_STATUS, Event.OPEN, though I haven't added those in, they may provide useful information if you still aren't getting anywhere.
You should not need a LoaderContext object if you are only loading images and not accessing their content, so that (security) really should not be a problem. You should definitely separate out your logic in imageLoaded so that it is not both the initiator and the completion handler for your Loaders.
Anyway, no clue if this will be of use to you, but I've made your code substantially more readable and reworked some things that made little sense.
public static const LOADLIMIT:int = 4;
private var paramObj:Object;
private var imageRequests:Vector.<URLRequest>;
private var loaderObj:Vector.<Loader>;
private var nextToLoad:int = -1;
public function Player(){
paramObj = loaderInfo.parameters;
//what is this all about, your backup URL is useless?
if (!paramObj.root) {
paramObj.root = "http://site.com/images/";
}
var res = bootstrapImages();
if (res.length > 0){
loadErrorMsg.text = res;
loadErrorMsg.visible = true;
//log.log kills me
log.log(res);
}
}
private function bootstrapImages():String {
try {
var req:URLRequest = new URLRequest(paramObj.root + "getdirlist.php?name=" + paramObj.imgloc);
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, directoryLoaded);
loader.addEventListener(IOErrorEvent.IO_ERROR, dataIOError);
loader.load(req);
} catch (ex:Error) {
log.log(ex);
}
return "";
}
private function directoryLoaded(e:Event):void{
trace(e.target.data);
try {
var items:Array = JSON.decode(e.target.data);
} catch (ex:Error){
trace (ex.getStackTrace());
loadErrorMsg.text = "Error parsing album data.";
loadErrorMsg.visible = true;
log.log(ex);
return;
}
if (items.length == 0){
loadErrorMsg.text = "Invalid album name";
loadErrorMsg.visible = true;
log.log("Items length is 0.");
return;
}
imageRequests = new Vector.<URLRequest>();
loaderObj = new Vector.<Loader>();
for each(var item:String in items){
imageRequests.push(new URLRequest(paramObj.root+"coffeeimages/"+paramObj.imgloc+"/"+item));
loaderObj.push(new Loader());
}
for (var i:int = 0; i < LOADLIMIT; i++){
loadNextImage();
}
}
private function loadNextImage():void {
nextToLoad++;
if (nextToLoad < imageRequests.length) {
loaderObj[nextToLoad].contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
loaderObj[nextToLoad].contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, dataIOError);
try {
loaderObj[nextToLoad].load(imageRequests[nextToLoad]);
}
catch (e:Error) {
log.log(ex);
}
log.addObjectWatch(loaderObj[nextToLoad]);
}
}
private function dataIOError(e:IOError):void {
loadErrorMsg.text = "IOError: " + e.errorID + " - " + e.name + ", " + e.message;
loadErrorMsg.visible = true;
log.log(ex);
}
private function imageLoaded(e:Event){
//Start the slideshow if the first image has loaded
loadNextImage();
if (e.target == loaderObj[0]) {
trace(loaderObj[0].contentLoaderInfo.bytesLoaded, loaderObj[0].contentLoaderInfo.bytesTotal);
loadErrorMsg.visible = false;
playSlideshow(true);
}
}
Edit: You may simply wish to scrap your loading code entirely and instead use Bulk Loader

I like the crossdomain.xml solution mentioned above, but we had a similar problem on our client PC's. The problem was that adblocker browser plugins were blocking the URLRequest of the actionscript. We are currently finding a solution to this.

Related

dispatch change value and start tween

I try to make simple scorebug. It’s feed from external XML file.
I want to start an animation when score changing, but i doesn’t found event listener or dispatcher to get change of value.
var myTimer:Timer = new Timer(100);
myTimer.addEventListener(TimerEvent.TIMER, timerListener);
myTimer.start();
function timerListener (e:TimerEvent):void
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("Xml.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
function processXML (e:Event):void
{
var myXML:XML = new XML(e.target.data);
ShotClock.text = myXML.timestamp;
GameClock.text = myXML.Clock;
HS.HomeScore.text = myXML.HomeScore;
AS.AwayScore.text = myXML.AwayScore;
Period.text = myXML.Period;
AwayTeam.text = myXML.AwayName;
HomeTeam.text = myXML.HomeName;
}
if ( (myXML.HomeScore).CHANGE )
{ var myTween:Tween = new Tween(HS.HomeScore, "alpha", Strong.easeIn, 0, 1, 1, true); }
}
You need to change the logic of loading. Instead of starting timed loadings, which won't be accurate 100 ms anyway, could lag, could fail, could arrive in order other than you issued them, etc., you need a single-thread asynchronous loop that does, simply, the following:
Start data loading.
(async pause)
Handle the loaded data.
Get XML data from loaded text.
Parse XML attributes.
Check if the score variable changed and trigger the things you want to.
Wait 100 ms.
(async pause)
Go to step №1.
Something like that:
var theLoader:URLLoader;
var theScore:Number = 0;
var theTimer:Timer;
// Start the tracking routine.
trackNext();
function trackNext():void
{
theLoader = new URLLoader;
theLoader.addEventListener(Event.COMPLETE, onXML);
// Error tracking is a must or the logic flow
// might just stop when you least expect it to.
theLoader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
theLoader.load(new URLRequest("xml.xml"));
}
function onXML(e:Event):void
{
// Sanity check. There should be only one valid URLLoader instance.
if (e.target != theLoader)
{
return;
}
var X:XML;
try
{
X = new XML(theLoader.data);
}
catch (fail:Error)
{
// Processing the case where data is loaded successfully,
// but it is not a valid XML String.
onError(e);
return;
}
// Here's the place for your code
// that extracts data from XML.
// ...
// Get the new score value.
var aScore:Number = X.HomeScore;
// Compare it to previous value.
if (aScore != theScore)
{
// ATTENTION!!! THIS IS THE PLACE YOU ARE LOOKING FOR!!!
// Trigger things if the new score is any different.
// ...
// Keep the new score value.
theScore = aScore;
}
finishLoading();
}
// This method just ignores an error, think of it
// as of blank to process the exceptional cases.
function onError(e:Event):void
{
// Sanity check. There should be only one valid URLLoader instance.
if (e.target != theLoader)
{
return;
}
finishLoading();
}
// Call it finishLoading(true) to stop the tracking routine.
function finishLoading(thenstop:Boolean = false):void
{
// Dispose of the URLLoader instance if any.
if (theLoader)
{
var aLoader:URLLoader = theLoader;
theLoader = null;
aLoader.removeEventListener(Event.COMPLETE, onXML);
try
{
aLoader.close();
}
catch (fail:Error)
{
// Do nothing about it.
}
}
finishTimer();
if (thenstop)
{
return;
}
// Wait 100 ms to give Flash Player a breather
// before starting to load the file once more.
theTimer = new Timer(100, 1);
theTimer.addEventListener(TimerEvent.TIMER, onTime);
theTimer.start();
}
function finishTimer():void
{
// Dispose of the Timer instance if any.
if (theTimer)
{
theTimer.removeEventListener(TimerEvent.TIMER, onTime);
theTimer.stop();
theTimer = null;
}
}
function onTime(e:TimerEvent):void
{
// Now go for the next iteration.
finishTimer();
trackNext();
}

Error hanlder for FileStream - AS3 AIR

I'm saving an object to a file using FileStream. The object I'm saving has variables in it:
var saveObj:Object = new Object()
saveObj['FirstName']="Georges"
saveObj['LastName']="St-Pierre"
MY question is this: How do I make an error handler for a variable missing when I load the File? For example 'Firstname' is missing. How do I do that? This is the code I have but it doesn't work.
private function F_loadData():void {
folder = File.documentsDirectory.resolvePath("saved projects");
var file:File = folder.resolvePath("mySave.adktf");
var stream:FileStream = new FileStream();
stream.addEventListener(Event.COMPLETE, completeHandler);
stream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
stream.openAsync(file, FileMode.READ);
var myLoadedObj:Object = stream.readObject();
stream.close()
trace(myLoadedObj.MiddleName)
}
private function completeHandler(event:Event):void {
trace("load Complete")//not final. Just for testing
}
private function progressHandler(event:ProgressEvent):void {
// ...
}
//I was hoping the error would call this function
private function errorHandler(event:IOErrorEvent):void {
trace("Error found")//not final. Just for testing
}
trace(myLoadedObj.MiddleName) should return an error and i was hoping that it would call the error Handler function that I made, but it didn't. It still returns an error. So how and what type of error handler should I use?
Since you are opening your file asynchronously, you need to wait to use readObject until after the complete event.
The error handler you've defined is only applicable to the loading of the file. SO if there is a problem opening the file the error handler will be called, any other kind of error is outside that scope.
Try something like this:
private var stream:FileStream;
private function F_loadData():void {
folder = File.documentsDirectory.resolvePath("saved projects");
var file:File = folder.resolvePath("mySave.adktf");
if(file.exists){
stream = new FileStream();
stream.addEventListener(Event.COMPLETE, completeHandler);
stream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
stream.openAsync(file, FileMode.READ);
//now wait for it to load
}else{
//file doesn't exist, do something
}
}
private function completeHandler(e:Event):void {
trace("load Complete")//not final. Just for testing
var myLoadedObj:Object = stream.readObject();
stream.close();
stream = null;
if(!myLoadedObj.MiddleName || myLoadedObj.MiddleName == ""){
//Middle name is missing or empty, do something
}
if(!myLoadedObj.FirstName || myLoadedObj.FirstName == ""){
//First name is missing or empty, do something
}
}
You may be better suited to using a custom class for your save object, something like this:
package {
public class SaveObject {
public var middleName:String;
public var lastName:String;
//any other properties
public function validate():Boolean {
//write some validation
//if you want lazy validation, you could do this: (untested)
for (var i in obj){
if(obj[i] is String && (obj[i] == null || obj[i] == "")){
return false;
}
}
return true;
}
}
}
Then, you can do this: (in your constructor)
flash.net.registerClassAlias("SaveData",SaveData);
Then you can do the following:
var mySaveData:SaveData = new SaveData();
//set properties
stream.writeObject(mySaveData);
//then later
var mySaveData:SaveData = stream.readObject();
if(!mySaveData.validate()){
//do something, it's invalid
}

actionscript 3.0 - p2p filesharing troubles (max upload file size)

i've designed a p2p apliccation which can transfer files without a server. and everything works fine. i can transfer files between peers. but as it turns out if file size is greater than 16mb (coz the biggest file i could transfer had a size of 15810 kb) it does't transfer to peer. this is the code i'm using:
private function browseFile(farIds:String = ""):void {
fIds = farIds;
file = new FileReference();
file.addEventListener(Event.SELECT, selectHandler);
file.browse();
}
private function selectHandler(event:Event):void {
var btn = getChild("browseFile_" + fIds)
if (btn && btn.alpha) btn.alpha = 0.5;
file = FileReference(event.target);
file.addEventListener(ProgressEvent.PROGRESS, progressHandler);
file.addEventListener(Event.COMPLETE, completeHandler);
file.load();
}
private function progressHandler(event:ProgressEvent):void{
ExternalInterface.call("fileLoadProgress", event.target.name, event.bytesTotal, event.bytesLoaded)
}
private function completeHandler(event:Event):void{
ExternalInterface.call("onFileLoaded")
var fileData:Object = new Object();
fileData.file = event.target.data
fileData.name = event.target.name;
var btn = getChild("browseFile_" + fIds)
if (btn && btn.alpha) btn.alpha = 1;
sendSomeData(fileData, fIds, "receiveFile");
}
public function receiveFile(info:Object, peerID:String):void{
ExternalInterface.call("alert", "receivedFile")
}
private function sendSomeData(data,farIds:String,func:String = "receiveSomeData"):void{
for(var id:String in sendStreams){
sendStreams[id].send(func, data, myPeerID);
}
}
can you tell me how can i allow transferring all files of any sizes?
thanks for your help!
You can split the file in chunks of say 8KB, and send them one by one. However you must check for the order of received chunks and any possible losses on the way.

AS3 multiple file download, check when completed?

I am looping through a small array of file names to grab from a remote server and save locally. This bit works OK.
The problem is, I need to run my next function when the downloads are complete.
Currently, my function, lets call it step2(), gets called before all the FileStreams can finish (infact, its called before that function even starts!)
I read that there is a complete event listener when using openAsynch, but I need to check that all files, e.g. 3 remote swfs) have been written and then start step2() function.
How can I go about this?
Code below:
function onPlaylistComplete(e:Event)
{
var myArray:Array = new Array();
for each(var i in list_of_files)
{
myArray.push(i);
}
for(i = 0; i < myArray.length; i++)
{
swfItem = myArray[i];
var urlString:String = site_url + myArray[i];
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
urlStream.addEventListener(Event.COMPLETE, urlStreamComplete(swfItem));
urlStream.load(urlReq);
}
function urlStreamComplete(swfItem):Function
{
var downloadSwf:Function = function (event:Event):void {
var fileData:ByteArray = new ByteArray();
var stream = event.target;
stream.readBytes(fileData, 0, stream.bytesAvailable);
try {
var f : File = File.documentsDirectory.resolvePath(swfItem);
var fs : FileStream = new FileStream();
fs.addEventListener(Event.COMPLETE, fileCompleteHandler);
fs.openAsync(f, FileMode.WRITE);
fs.writeBytes(fileData);
}
catch (err : Error) {
trace(err.message);
}
}
return downloadSwf;
}
function fileCompleteHandler(e:Event):void {
e.target.close();
}
step2(); // this seems to run before UrlStreamComplete()
}
Problem with your for loop it will never work with Async model. so better need work to with recursive function.
downloadAllFiles method second arg that is function called when all download are completed.Then you can call step2() or whatever may be.
Make sure if any problem while download file like IOErrorEvent,etc...
downloadAllFiles(myArray,function():void
{
step2();
});
function downloadAllFiles(myArray:Array, complete:Function):void
{
if(myArray && myArray.length == 0)
{
if(complete)
complete.call();
return;
}
swfItem = myArray.shift();
var urlString:String = site_url + swfItem;
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
urlStream.addEventListener(Event.COMPLETE, function (event:Event):void
{
var fileData:ByteArray = new ByteArray();
var stream = event.target;
stream.readBytes(fileData, 0, stream.bytesAvailable);
try {
var f : File = File.documentsDirectory.resolvePath(swfItem);
var fs : FileStream = new FileStream();
fs.addEventListener(Event.CLOSE, function(closeEvent:Event):void
{
downloadAllFiles(myArray,complete);
return;
});
fs.openAsync(f, FileMode.WRITE);
fs.writeBytes(fileData);
}
catch (err : Error)
{
trace(err.message);
}
});
urlStream.load(urlReq);
}
Can't you just move step2(); at the end of fileCompleteHandler function?
Because at this point step2(); is called right after going through for(i = 0; i < myArray.length; i++)
loop (Which is way to early).
What you are missing is a way to check that all files from your list are loaded, 3vliguy is right and your step2(); should be in the complete handler but, not alone, you have to also test if ALL files are loaded. you can do it in various ways, e.g. use file counter and when it is 0 (all files loaded) you will execute step2() else you will ignore it and just decrease counter.
p.s. the Raja Jaganathan way will work as well, only it is queued loading whereas with the counter you can start loading of all files at the beginning.

AS3: Shared Objects Issue

Slight problem i have been pondering on, i have a class that loads a text from a url as a means to sync the time.
The swf file can be on the same page multiple times, but i want it to check to see if one of the swf is sync'ing, if so then wait for it to complete and load its sync'd value (rather then query the url itself), so that they are all sync'd to the same value (of the 1st swf file to load).
I am trying this using Shared Objects, which looks a little like this (snippets):
public function sync():void
{
sharedObject = SharedObject.getLocal("synctime", "/");
trace(sharedObject.data.startOfRequest, sharedObject.data.endTime);
if ( ((new Date().getTime() - 10000) < sharedObject.data.startOfRequest) && (sharedObject.data.endTime !== undefined))
{
loadUTCFromSharedObject();
}
else if ( ((new Date().getTime() - 10000) < sharedObject.data.startOfRequest) && (sharedObject.data.endTime == undefined ) )
{
timer.addEventListener(TimerEvent.TIMER, loadUTCFromSharedObject);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, startSync);
timer.start();
} else {
startSync()
}
}
private function startSync(e:Event = null)
{
var syncRequest:URLRequest = new URLRequest(TIMEURL + "?cb=" + Math.random());
var syncTimeLoader:URLLoader = new URLLoader();
syncTimeLoader.dataFormat = URLLoaderDataFormat.TEXT;
syncTimeLoader.addEventListener(Event.COMPLETE, syncTimeComplete );
syncTimeLoader.addEventListener(IOErrorEvent.IO_ERROR, syncTimeFailed );
sharedObject.clear();
startOfRequest = new Date();
sharedObject.data.startOfRequest = startOfRequest.getTime();
sharedObject.flush();
syncTimeLoader.load(syncRequest);
}
private function loadUTCFromSharedObject(e:Event = null):void
{
var sharedObjectCheck:SharedObject = SharedObject.getLocal("synctime", "/");
trace (sharedObject.data.endTime, sharedObjectCheck.data.endTime);
if ( sharedObject.data.endTime !== undefined )
{
timer.removeEventListener(TimerEvent.TIMER, loadUTCFromSharedObject);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, startSync);
dispatchEvent( new LoadUTCTimeEvent(LoadUTCTimeEvent.SYNC_COMPLETE, null, null, sharedObject, true));
trace(sharedObject.data.UTCOffset);
}
}
private function syncTimeComplete(event:Event):void
{
var loadedText:URLLoader = URLLoader(event.target);
dispatchEvent( new LoadUTCTimeEvent(LoadUTCTimeEvent.SYNC_COMPLETE, loadedText.data, startOfRequest, sharedObject, false));
}
Event Dispatcher:
public function LoadUTCTimeEvent(eventStatus:String, timeString:String = null, startOfRequest:Date = null, sharedObject:SharedObject = null, loadFromSharedObject:Boolean = false):void
{
super(eventStatus);
if (eventStatus == SYNC_COMPLETE) {
if (loadFromSharedObject == true) {
time = sharedObject.data.syncTime;
UTCOffset = sharedObject.data.UTCOffset;
}
else
{
//...snip....//
sharedObject.data.UTCOffset = UTCOffset;
sharedObject.data.syncTime = time;
sharedObject.data.endTime = curDate.getTime();
sharedObject.flush(1000);
}
}
}
The problem i am getting is that the 1st swf creates the sharedobject fine, but the second one reads the endTime as undefined, unless i refresh the page (i.e it doesnt pick up live changes). Is this method not posible, should i try another aproach?
Thanks in advance.
Edit: decided to add another stack to explain a little more:(as3) Sync data between 3 or more identical flash objects on the same page
you can call a javascript function to do the locking if you stuck with this solution
Okay, use localconnection
Typically, you should not use Local SharedObjects to sync things. The flush() command has never worked for me in the way you are intending it to.