The application I’ve described in the previous section now runs as a desktop application. It doesn't leverage any of the Adobe AIR APIs. Now imagine that you want the application to write to the local file system. The Adobe AIR API provides the File, FileStream, and FileMode classes to accomplish this task. Again, leveraging your existing web development skills, you can add just a few lines of JavaScript to utilize these classes and write data to the local disk (see fileio.html in the sample files folder).
// Create a reference to a place on disk to store the data
// Create a string of text to store in the file
// Create a stream for use in writing the data
var file = air.File.desktopDirectory.resolvePath( 'hello.txt' );
var msg = 'Hello world, from AIR!';
var stream = new air.FileStream();
// Open the stream for writing
// Write the name value to the file using system encoding
// Close the stream
stream.open( file, air.FileMode.WRITE );
stream.writeMultiByte( msg, air.File.systemCharset );
stream.close();
Realistically, this data will likely come from some service endpoint as XML, using the XMLHttpRequest (XHR) class. Again, with Adobe AIR, developers are free of the traditional domain security limitations and their applications can request data from any endpoint. What if the remote server is down? What if the network cable is inoperative? These types of desktop deployment challenges are handled by the Adobe AIR network/service monitor class, see network.html and servicemonitor.swf in the sample files.
// Specify what URL to monitor
var endpoint = new air.URLRequest( SERVICE_URL );
// Create the object to monitor the endpoint
// Call a function when the network status changes
// Start listening for a network change
monitor = new air.URLMonitor( endpoint );
monitor.addEventListener( air.StatusEvent.STATUS, doStatus );
monitor.start();
...
var xhr = null;
// The network is available
if( monitor.available )
{
// Create the object for the data request
xhr = new XMLHttpRequest();
// Listen for the various changes during the request
xhr.onreadystatechange = function()
{
var file = null;
var stream = null;
// When the data has been retrieved
if( xhr.readyState == 4 )
{
// Create a reference to a location on disk
file = air.File.desktopDirectory.resolvePath( LOCAL_FILE );
// Create the file IO stream
// Open the stream for writing
// Write the response data (text)
// Close the stream
stream = new air.FileStream();
stream.open( file, air.FileMode.WRITE );
stream.writeMultiByte( xhr.responseText, air.File.systemCharset );
stream.close();
}
}
// Open the network connection and send the request
xhr.open( 'GET', DATA_URL, true );
xhr.send( null );
}
In the case that network connectivity cannot be achieved, perhaps the application could offer a means to drag and drop data directly. Although drag-and-drop inside the browser has been possible for a while, drag-and-drop that extends beyond the browser is among the core features of Adobe AIR. There's even support for the various types of data that might be dragged into (or out of) an application from the OS itself. In addition to text, this includes file lists, bitmap data, and URLs. If you’re following along, open dragdrop.html in the provided sample files folder.
// Called when a mouse drag gesture is over the application
function doOver( e )
{
// Check the types of data being dragged
for( var t = 0; t < e.dataTransfer.types.length; t++ )
{
// Make sure there is a type you can handle
f( e.dataTransfer.types[t] == 'application/x-vnd.adobe.air.file-list' )
{
// Tell WebKit to avoid the default behavior (ignore)
e.preventDefault();
}
}
}
// Called when a mouse gesture drops data on the application function doDrop( e )
{
var data = null;
var elem = null;
var file = null;
var list = null;
var stream = null;
// Get the list of files that were dropped
list = e.dataTransfer.getData( 'application/x-vnd.adobe.air.file-list' );
// Iterate through the list of dropped files
for( var f = 0; f < list.length; f++ )
{
// Create a new file IO stream
// Open the current file in the iteration
// Read the contents as text data into a variable
// Close the stream
stream = new air.FileStream();
stream.open( list[f], air.FileMode.READ );
data = stream.readMultiByte( stream.bytesAvailable, air.File.systemCharset );
stream.close();
// Create a new HTML DIV to hold the data
// Put the data in the DIV and append it to the document
elem = document.createElement( 'div' );
elem.innerText = data;
document.body.appendChild( elem );
}
}
Now that the application can manage data through file IO, network service requests, and native drag-and-drop support, there might be a reason to add data storage that's a little more robust than CSV, XML, or plain text. The open source relational database SQLite is included as part of Adobe AIR and it offers high performance data storage and retrieval via ANSI SQL-92 complaint syntax (see feeds.db in the sample files). This not only includes support for text and numeric values, but also for binary data (BLOB). The code below is available in the provided sample files. Open database.html to see the entire file.
// Called when the document finishes loading
function doLoad()
{
var ship = air.File.applicationDirectory.resolvePath( DATABASE_FILE );
var store = air.File.applicationStorageDirectory.resolvePath( DATABASE_FILE );
// Put the database in a writable place first
if( !store.exists)
{
ship.copyTo( store );
}
// INFO: air.trace( 'Database at: ' + store.nativePath );
// Open a connection to the SQLite database
db = new air.SQLConnection();
db.addEventListener( air.SQLEvent.OPEN, doDbOpen );
db.open( store, air.SQLMode.CREATE );
}
What you have now is a web application, developed using standard web development technologies, that has integrated desktop features. This relatively simple example takes on features that simply aren't possible in the web browser. Although it doesn't replace the browser itself, features such as file IO, network awareness, and native drag-and-drop support readily extend an existing web presence to the desktop.