Doing some development on the apolmb project I thought about a way to make the local filesystem accessible to an OpenLaszlo application. Since the Flash Player version 10 seems only to be able to load and save local files, but not get directory listings, I installed Adobe Air 1.5.3 SDK and Runtime on my Ubuntu machine, integrated it with the help of Aptana in Eclipse, started a new Air HTML/JavaScript project and embedded the OpenLaszlo-compiled SWF inside.
It resulted in Air application, which prints the content of local files. The Air package is available here. The readLocalFile function will return the content of any file on your local disk (e.g. "/var/log/auth.log" or "C:/autoexec.bat")
Bridging Air and OpenLaszlo with Javascript
The HTML container inside the Air project provides access to the to the local filesystem through the AIR API. Embedding the SWF with OpenLaszlos lz.embed.swf function provided in the embed-compressed.js makes it possible to call the JS-functions in the HTML container with lz.Browser.callJS() and receive the return values. Heres the code:
Adobe Air HTML container code (airpolmb.html):
<html>
<head>
<title>OpenLaszlo App in Air Runtime / JavaScript Bridge</title>
<script type="text/javascript" src="lib/air/AIRAliases.js"></script>
<script type="text/javascript" src="lps/includes/embed-compressed.js"/>
<script type="text/javascript">
// reads the content of a local text file
function readLocalFile(fpath){
var f = air.File.applicationDirectory.resolvePath(fpath);
var fs = new air.FileStream();
fs.open(f, air.FileMode.READ);
var content = fs.readUTFBytes(fs.bytesAvailable);
fs.close();
return content;
}
</script>
</head>
<body>
<script type="text/javascript">
lz.embed.swf({url: 'airtest.lzx.swf10.swf', allowfullscreen: 'false', bgcolor: '#ffffff',
width: '100%', height: '100%', id: 'lzapp', accessible: 'false',
cancelmousewheel: false});
lz.embed.lzapp.onloadstatus = function loadstatus(p) {
// called with a percentage (0-100) indicating load progress
}
lz.embed.lzapp.onload = function loaded() {
// called when this application is done loading
}
</script>
</body>
</html>
OpenLaszlo code (airtest.lzx):
<canvas height="100%" width="100%" title="Airtest" proxied="false">
<method name="receivedFromJavaScript" args="data">
<![CDATA[
Debug.write("Response data: ");
Debug.write(data);
this.response.setAttribute("text", data);
]]>
</method>
<simplelayout axis="y" spacing="10" />
<view height="10"></view>
<view x="10">
<simplelayout axis="x" spacing="10" />
<text>JS function: </text>
<edittext name="func" width="220">readLocalFile</edittext>
<text> argument: </text>
<edittext name="arg" width="220">LocalFile.txt</edittext>
<button text="call"
onclick="lz.Browser.callJS(parent.func.getValue(),
canvas.receivedFromJavaScript, parent.arg.getValue())"/>
</view>
<text x="10" text="Response data:"/>
<text x="10" name="response" multiline="true" resize="true"/>
</canvas>
Alternative way without lz.embed
A different way leading to nearly the same results is to totally leave the lz.embed stuff out, directly import the class flash.external.ExternalInterface in the LZX code and go further using call and callback methods directly. In this case the response value is delivered by the callback function instead of being included in the return value.
airpolmb-alt.html:
<html>
<head>
<title>OpenLaszlo App in Air Runtime / JavaScript Bridge Alternative</title>
<script type="text/javascript" src="lib/air/AIRAliases.js"></script>
<script type="text/javascript">
// returns the SWF object node
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
// reads the content of a local text file
function readLocalFile(fpath){
var f = air.File.applicationDirectory.resolvePath(fpath);
var fs = new air.FileStream();
fs.open(f, air.FileMode.READ);
var content = fs.readUTFBytes(fs.bytesAvailable);
fs.close();
thisMovie("lzapp").getJSData(content);
return content;
}
</script>
</head>
<body>
<object id="lzapp" type="application/x-shockwave-flash" width="100%" height="100%">
<param name="movie" value="app:/airtest-alt.lzx.swf10.swf"/>
<param name="wmode" value="opaque"/>
</object>
</body>
</html>
airtest-alt.lzx:
<canvas height="100%" width="100%" title="Airtest-AS3" proxied="false">
<method name="receivedFromJavaScript" args="data">
<![CDATA[
Debug.write("Response data: ");
Debug.write(data);
this.response.setAttribute("text", data);
]]>
</method>
<class name="FlashUtil" extends="node" >
<passthrough>
import flash.external.ExternalInterface;
</passthrough>
<method name="callJS" args="...rest" allocation="class" >
ExternalInterface.call.apply(ExternalInterface, rest);
Debug.write(ExternalInterface, rest);
</method>
<method name="initJSCallback" args="...rest" allocation="class" >
ExternalInterface.addCallback.apply(ExternalInterface, rest);
Debug.write('Init callback');
</method>
</class>
<script>
lz.FlashUtil.initJSCallback("getJSData", canvas.receivedFromJavaScript);
</script>
<simplelayout axis="y" spacing="10" />
<view height="10"></view>
<view x="10">
<simplelayout axis="x" spacing="10" />
<text>JS function: </text>
<edittext name="func" width="220">readLocalFile</edittext>
<text> argument: </text>
<edittext name="arg" width="220">LocalFile.txt</edittext>
<button text="call"
onclick="lz.FlashUtil.callJS(parent.func.getValue(), parent.arg.getValue())"/>
</view>
<text x="10" text="Response data:"/>
<text x="10" name="response" multiline="true" resize="true"/>
</canvas>
During my investigation this two posts in the OpenLaszlo forum helped me the most.
Thanks to everybody in the OpenLaszlo community and at Laszlo Systems for sharing this great framework and all the help and ideas with all of us.
Comments
Anonymous (not verified)
Thu, 2011-02-03 21:35
Permalink
can i also save a file with this code
it seems that if I substitute fs.FileMode.READ with WRITE
that the example does not work as expected.
i cannot make it write a file.
maybe you can help me under
mark.scheel@gmx.de
Add new comment