AS3 iOS : Loading external swf - ios

I'm trying to load a swf in another using AIR3.6.
I duplicated the code I found here http://blogs.adobe.com/airodynamics/2012/11/09/packaging-and-loading-multiple-swfs-in-air-apps-on-ios/ but in vain. It does'nt work.
So I think I didn't understand part of the procedure.
That what I have done :
• I have a first fla I can correctly publish for iOS.
• In this fla I have this code :
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest("test.swf");
var _lc:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.load(mRequest);
function onCompleteHandler(loadEvent:Event)
{
addChild(loadEvent.currentTarget.content);
}
• In the publish settings I went to the General tab and I included my second swf : test.swf
• The second swf (test.swf). I published it with AIR 3.6 for iOS.
It has no actionscript at all. There is only a green shape in it.
• When I test my first fla, the second one is correctly loaded.
• When I publish it in my iPad, the second swf is NOT loaded.
Can someone tells me where I was wrong ?
Thanks.

All right, 10 seconds after publishing my question, I found my solution.
I only forgot to put the _lc:LoaderContext in the mLoader.load().
So here is it :
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest("test.swf");
var _lc:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.load(mRequest, _lc);
function onCompleteHandler(loadEvent:Event)
{
addChild(loadEvent.currentTarget.content);
}
Note to moderators : Not sure this will be helpfull for anyone, but I don't know how to delete a post.

Related

Security Error when trying to load ByteArray from mediaPromise

in a mobile application i need to send an image which the user either took with the camera or picked from a cameraroll.
I am using the starling framework and feathersUI ( although i think this does not matter to problem )
When the mediapromise is loaded using loadFilePromise i use the following code to deal with the image data:
_mediaLoader = new Loader()
//loading the filePromise from CameraRoll
_mediaLoader.loadFilePromise(_mediaPromise);
_mediaLoader.contentLoaderInfo.addEventListener(starling.events.Event.COMPLETE, onLoadImageComplete);
private function onLoadImageComplete(event:flash.events.Event=null):void {
//creating the starling texture to display the image inside the application
var texture:Texture = Texture.fromBitmapData(Bitmap(_mediaLoader.content).bitmapData, false, false, 1);
//now trying to load the content into a bytearray to send to the server later
var bytes:ByteArray=_mediaLoader.contentLoaderInfo.bytes;
}
the last line of code results in a Security error:
Error #2044: Unhandled SecurityErrorEvent:. text=Error #2121: Security sandbox violation: app:/myapp.swf: http://adobe.com/apollo/[[DYNAMIC]]/1 cannot access . This may be worked around by calling Security.allowDomain.
I tried
Security.allowDomain("*")
as a test
but then i get:
SecurityError: Error #3207: Application-sandbox content cannot access this feature.
As a workaround i write my own png ByteArray inside the Application from the loaders BitmapData using Adobes PNGEncoder Class:
var ba:ByteArray=PNGEncoder.encode(Bitmap(_mediaLoader.content).bitmapData)
But this takes a significant amount of time ...
I also tried the FileReference to load the image but
_mediaPromise.file
and
_mediaPromise.relativePath
are both null.
What am I doing wrong? Or is this a known problem ?
Thanks!
Hello I have found a solution based on a post about the processing of exif data mentioned here: http://blogs.adobe.com/cantrell/archives/2011/10/parsing-exif-data-from-images-on-mobile-devices.html
the crucial code
private function handleMedia(event:MediaEvent):void{
_mediaPromise=event.data as MediaPromise;
_imageBytes=new ByteArray()
var mediaDispatcher:IEventDispatcher = _mediaPromise.open() as IEventDispatcher;
mediaDispatcher.addEventListener(ProgressEvent.PROGRESS, onMediaPromiseProgress);
mediaDispatcher.addEventListener(flash.events.Event.COMPLETE, onMediaPromiseComplete);
};
private function onMediaPromiseProgress(e:ProgressEvent):void{
var input:IDataInput = e.target as IDataInput;
input.readBytes(_imageBytes, _imageBytes.length, input.bytesAvailable);
};
private function onMediaPromiseComplete(e:flash.events.Event):void{
_mediaLoader = new Loader();
_mediaLoader.loadBytes(_imageBytes)
};
works like a charm for me on ipad and iphone.

Firefox bootstrapped extension: Get native HWND handle of the browser window

I have an external application and I want it to display some information on top of the browser window. My bootstrapped extension needs to pass the browser window handle (native HWND) to my application, along with some other useful information about the window. I'm able to do the communication between them, the only thing that is missing is a way to get the native HWND of the Firefox window.
I read a lot about it and although I belive it's possible, I couldn't find a working solution. Here's what I've tried so far:
This one should give me nsIBaseWindow, so I could get nsIBaseWindow.nativeHandle or nsIBaseWindow.ParentNativeWindow, but no success:
var window = SomeDOMWindow; // Informative
var baseWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIXULWindow)
.docShell
.QueryInterface(Components.interfaces.nsIBaseWindow);
The above code is widely spread on forums, but I couldn't get it to work for me.
The other one does not seem to be much accurate since it gets the HWND based on the window's class and title, which can lead to wrong results:
Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("user32.dll");
var fww = lib.declare("FindWindowW", ctypes.winapi_abi,
ctypes.voidptr_t, ctypes.jschar.ptr, ctypes.jschar.ptr);
var sfw = lib.declare("SetForegroundWindow", ctypes.winapi_abi,
ctypes.int32_t, ctypes.voidptr_t);
var hwnd = fww("MozillaWindowClass", document.title);
setTimeout(function() {
sfw(hwnd);
lib.close();
}, 3000);
Any help would be appreciated.
window must be a root one (i.e. an instance of ChromeWindow)
The following code should work
var win = Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var basewindow = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.nsIBaseWindow;
var nativehandle = basewindow.nativeHandle;
The problem was that I was querying the wrong interface from the subject param in the xul-window-registered observer. I need to get an nsIDOMWindow instead of an nsIXULWindow so the first code mentioned in my question works. So now I'm doing the following, with some piece of code #Noit suggested:
observe: function(subject, topic, data) {
var newWindow = subject.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
var basewindow = newWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.nsIBaseWindow;
var nativehandle = basewindow.nativeHandle;
}
And it works!
Thank you very much for your help.
I also just came across this, it might be nice:
Cu.import("resource://gre/modules/ctypes.jsm");
/*start getcursorpos*/
var lib = ctypes.open("user32.dll");
/*foreground window stuff*/
var FindWindowA = lib.declare('FindWindowA', ctypes.winapi_abi, ctypes.uint32_t, ctypes.jschar.ptr, ctypes.jschar.ptr)
var GetForegroundWindow = lib.declare('GetForegroundWindow', ctypes.winapi_abi, ctypes.uint32_t)
function doFindWindow() {
var wm = Cc['#mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
var title = wm.getMostRecentWindow('navigator:browser').gBrowser.contentDocument.title;
Cu.reportError('title=' + title)
var ret = FindWindowA('', title + ' - Mozilla Firefox');
//var ret = GetForegroundWindow();
Cu.reportError(ret);
}
/*end foreground window stuff*/
The code in the answer of user 'paa' worked until Firefox version 69.
If you execute it in Firefox 70 you will get an exception:
TypeError: win.QueryInterface is not a function
This is strange because the variable win has the same content in Firefox 69 and 70.
When I execute alert(win) I get: "[object ChromeWindow]" in both browsers.
And alert(win.document.title) displays correctly the title of the document in both browsers.
I downloaded the sourcecode of both Firefox versions to compare them and possibly find the cause. But the source code of Firefox is huge (2 Gigabyte) and nearly completely free of comments. I found that I'm wasting my time with that approach.
It is extremely difficult to understand sourcecode of Firefox which runs spread over multiple processes which communicate with each other. It seems that the content of the variable win corresponds to the C++ class mozIDOMWindowProxy or nsChromeOuterWindowProxy. But these seem to be only wrapper classes for other classes. Finally I gave up trying to understand Firefox sourcecode.
But playing around for some hours I finally found a solution by try and error.
It is even simpler:
var baseWindow = win.docShell
.treeOwner
.nsIBaseWindow;
It works on Firefox 70 up to 79 (which is currently the latest version). However this new code does not run on Firefox versions <= 62. On Firefox 62 or older you get the error
TypeError: win.docShell is undefined
So the Firefoxes from 63 to 69 allow both versions of code. Maybe in version 70 the QueryInterface() has been removed because it is not needed anymore and has become legacy?
NOTE: In Firefox 68 they made another change. Now there are 2 native windows: The toplevel 'MozillaWindowClass' now has a child window 'MozillaCompositorWindowClass' which runs in another process and draws the web content.

Load and reload external SWF in AIR for iOS

I found several info on how to load one or more external SWF files, packaged with my AIR iOS App, the actual working code is:
var myUrlRequest:URLRequest = new URLRequest(mySWF);
var myLoaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null);
var loader: Loader = new Loader();
loader.load(myUrlRequest, myLoaderContext);
Object(root).MK.addChild(loader)
It works on Android devices and on Windows PC, but on iOS it loads the external SWFs only the first time. In my project I have several buttons that loads an external SWF, but each button works only the first time.
Any idea? It seems very unuseful if I can't reload an SWF.
If you can't load something a second time, perhaps it would be best to simply cache it and make a point of only loading it once?
A good way to handle this would be to load the SWF files into separate movieclips the first time and then when needing to "load" them anytime after that, just show those movieclips that already have the SWF files loaded in them.
You can't load a SWF file that contains any ActionScript ByteCode (ABC) then unload it and reload it on iOS. If you attempt to do this, the runtime throws error 3764.
I had problems loading SWF's even without code a second time. The solution I found depended on whether the code was from the application area (packaged with the app) or loaded externally (either from the web or downloaded into the caches folder).
I wrote an extended post about here, if you're interested: http://www.eqsim.com/blog/?p=400
In a nutshell, here is my code for setting the path:
var moduleDirectoryPath = "/modules/";
if (externalContent == FROM_CACHE) {
moduleDirectoryPath = File.cacheDirectory.url + moduleDirectoryPath;
} else if (externalContent == FROM_WEB) {
moduleDirectoryPath = "http://our-online-content.com" + moduleDirectoryPath;
}
then here is my code for preparing the path, if the SWF is from the app area or otherwise (cache or web):
if (loadFromApp) {
path = moduleDirectoryPath + module_folder + "/" + module + "?nf="+getTimer();
} else {
path = moduleDirectoryPath + module_folder + "/" + module;
}
Finally, my loading statements:
request = new URLRequest(path);
request.cacheResponse = false;
request.useCache = false;
_lc = new LoaderContext(false, ApplicationDomain.currentDomain, null);
moduleLoader.load(request, _lc);
and now I can load SWF's and reload them (more importantly). Of course the SWF's do not have bytecode in them.

How to implement IndexDB in IOS

I am developing a mobile application using phonegap, Initially I have developed using WEBSQL but now I m planning to move it on INDEXDB. The problem is it does not have direct support on IOS , so on doing much R&D I came to know using IndexedDB Polyfil we can implement it on IOS too
http://blog.nparashuram.com/2012/10/indexeddb-example-on-cordova-phonegap.html
http://nparashuram.com/IndexedDBShim/
Can some please help me how to implement this as there are not enough documentation for this and I cannot figure out a any other solution / api except this
I have tested this on safari 5.1.7
Below is my code and Error Image
var request1 = indexedDB.open(dbName, 5);
request1.onsuccess = function (evt) {
db = request1.result;
var transaction = db.transaction(["AcceptedOrders"], "readwrite");
var objectStore = transaction.objectStore("AcceptedOrders");
for (var i in data) {
var request = objectStore.add(data[i]);
request.onsuccess = function (event) {
// alert("am again inserted")
// event.target.result == customerData[i].ssn;
};
}
};
request1.onerror = function (evt) {
alert("IndexedDB error: " + evt.target.errorCode);
};
Error Image
One blind guess
Maybe your dbName contains illegal characters for WebSQL database names. The polyfill doesn't translate your database names in any kind. So if you create a database called my-test, it would try to create a WebSQL database with the name my-test. This name is acceptable for an IndexedDB database, but in WebSQL you'll get in trouble because of the - character. So your database name has to match both, the IndexedDB and the WebSQL name conventions.
... otherwise use the debugger
You could set a break point onto your alert(...); line and use the debugger to look inside the evt object. This way you may get either more information about the error itself or more information to share with us.
To do so, enable the development menu in the Safari advanced settings, hit F10 and go to Developer > Start debugging JavaScript (something like that, my Safari is in a different language). Now open then "Scripts" tab in the developer window, select your script and set the break point by clicking on the line number. Reload the page and it should stop right in your error callback, where you can inspect the evt object.
If this doesn't help, you could get the non-minified version of the polyfill and try set some breakpoints around their open function to find the origin of this error.
You could try my open source library https://bitbucket.org/ytkyaw/ydn-db/wiki/Home. It works on iOS and Android.

Flash Media Server & AS3: Publishing works, recording doesn't

I'm currently having an issue with FMS4 developer edition on both Linux (x64) and Windows XP (x86).
When I stream a webcam using ns.publish("foobar", "live") I can watch the live stream on another client, however when i use ns.publish("foobar", "record"); neither broadcasting nor recording works.
Using the "live" parameter the client appears in the log files and in the administration console as "publishing", using "record" the client appears as "idle".
Is there anything I need to configure besides LIVE_DIR in fms.ini?
Is this a restriction in the developer edition?
Is there something else I'm missing?
Here is the relevant part of the code (condensed):
var camLive:Camera = Camera.getCamera();
var nc:NetConnection = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
var ns:NetStream;
nc.connect("rtmp://192.168.1.63/live/");
function netStatusHandler(event:NetStatusEvent):void {
if (event.info.code == "NetConnection.Connect.Success") {
ns = new NetStream(nc);
ns.attachCamera(camLive);
ns.publish("foobar", "record");
}
}
Thanks in advance!
Fabian
The problem is the live application. You can create an empty folder inside "applications", call it "test", then stream to "rtmp://192.168.1.63/test" with parameter "record". According to forums.adobe.com/thread/827134?tstart=0

Resources