General experience building HTML-based applications is suggested. For more details on getting started with this Quick Start, refer to Building the Quick Start sample applications with HTML.
Additional Requirements
Intermediate
Note: This application requires you to have a webcam installed, and you must have access to a PHP-enabled web server.
The PhotoUpload sample application, shown in Figure 1, demonstrates the following features of working with files in Adobe AIR:
This sample application includes the following files:
This sample application lets you capture images from a web cam and upload the captured images (stored as JPEG files) to a web server.
Photo Uploader uses the JPGEncoder class of a SWF file to convert data to JPEG format. The JPGEncoder class is published at the ActionScript 3.0 Corelib project (located at http://code.google.com/p/as3corelib).
Before running the application (PhotoUploadHTML.air), install the index.php file (included with the source files in the PHP directory) in the http://localhost/PhotoSyncUpload/ folder of your PHP-enabled web server. Also, make sure that a webcam is installed on your computer.
To test the application:
For more information about using AIR classes, see the Adobe AIR Language Reference for HTML Developers.
The appInit() method in the Uploader.js file uses two classes that are documented in the ActionScript 3.0 documentation: the Camera class and the Video class. The camera object (an instance of the Camera class) is assigned a webcam on the user’s computer by calling the getCamera() method of the Camera class. If no camera is present, the application notifies the user by calling the alert() function. The video object (an instance of the Video class) is the ActionScript 3.0 display object that is assigned to display the images captured by the camera.
camera = window.runtime.flash.media.Camera.getCamera();
if (camera)
{
video = new window.runtime.flash.media.Video();
video.attachCamera(camera);
camera.addEventListener(air.ActivityEvent.ACTIVITY, setSize);
}
else
{
alert("No cameras are available.");
}
The setSize() function sets the height and width of the video, and then calls the shoot() function:
function setSize()
{
video.width = camera.width * 2;
video.height = camera.height * 2;
shoot(false);
}
The shoot() function calls the flasher() function which simulates a camera flash by quickly rendering an opaque white NativeWindow to fill the screen:
function shoot(flash)
{
if (flash)
{
flasher();
}
bmd = new window.runtime.flash.display.BitmapData(video.width, video.height);
bmd.draw(video);
saveTemp();
}
function flasher()
{
var windowInitOpts = new air.NativeWindowInitOptions();
windowInitOpts.systemChrome = air.NativeWindowSystemChrome.NONE;
windowInitOpts.type = air.NativeWindowType.LIGHTWEIGHT;
var flashCube = new air.NativeWindow(windowInitOpts);
flashCube.x = 0;
flashCube.y = 0;
flashCube.width = air.Capabilities.screenResolutionX;
flashCube.height = air.Capabilities.screenResolutionY;
flashCube.visible = true;
setTimeout(closeFlash, 100, flashCube);
}
function closeFlash(flashCube) {
flashCube.close();
}
The flash parameter of the shoot method is set to false when the application first calls the method during the initialization (in the appInit() method).
The shoot() method then captures the image in the video object, saving it to a BitmapData object, bmd. The flash.display.BitmapData class is described in the ActionScript 3.0 documentation.
bmd = new window.runtime.flash.display.BitmapData(video.width, video.height);
bmd.draw(video);
When the application initializes and when the user clicks the Preview button, the saveTemp() method saves the image to a JPEG file which is then loaded into the img image.
The application must convert the BitmapData data contained in the bmd object into JPEG format. The JPGEncoder ActionScript 3.0 class, published at the corelib project (located at at http://code.google.com/p/as3corelib) does just that. The JPGEncoderLib.swf file, provided with the source files in the swf directory, contains that JPGEncoder class, and this HTML-based application makes the classes in that SWF file available to JavaScript code by loading the SWF file using the following script tag (in the index.html file):
<script src="swf/JPGEncoderLib.swf" type="application/x-shockwave-flash"></script>
The saveTemp() function saves the JPEG data to a temporary file (which is created by calling air.File.createTempFile()). Data is saved to the file by creating a FileStream object and calling the writeBytes() method of that object. The temp file is then loaded into the img image in the document. The image data is converted to a ByteArray object containing JPEG-encoded data by calling the encode() method of a JPGEncoder object:
function saveTemp()
{
tempFile = air.File.createTempFile();
temps.push(tempFile);
saveJPEG(tempFile);
img.src = "";
img = window.document.getElementById("img");
img.src = tempFile.url;
img.width = 320;
img.height = 240;
}
function saveJPEG(file) {
stream = new air.FileStream();
stream.open(file, air.FileMode.WRITE);
var data = getJPEGData(bmd);
stream.writeBytes(data, 0, data.length);
stream.close();
return file;
}
function getJPEGData(bmd) {
var jpegEncoder = new window.runtime.com.adobe.images.JPGEncoder();
return jpegEncoder.encode(bmd);
}
When the user clicks the Save button, the save() method saves the image to a JPEG file in the images subdirectory of the application resource directory. The name of the file is based on a timestamp provided by a Date object’s time property:
function save()
{
var timestamp = new Date().getTime().toString();
var path = "images/" + timestamp + ".jpg";
file = air.File.applicationStorageDirectory.resolvePath(path);
saveJPEG(file);
}
The Uploader.as file contains code that uploads files to a web server. The list of saved files is stored in the files array (an array of File objects). The upload() method looks through the list of files in the images subdirectory of the application storage directory:
function upload()
{
totalSize = 0;
files = new Array();
var dir = air.File.applicationStorageDirectory.resolvePath("images");
var allNodes = dir.getDirectoryListing();
for (var i = 0; i < allNodes.length; i++)
{
file = allNodes[i];
if (!file.isDirectory)
{
files.push(file);
totalSize += file.size;
}
}
url = UPLOAD_URL
uploadedSoFar = 0;
uploadNext();
}
The uploadNext() function extracts one File object from the files array, and calls the uploadFile() function, which uploads the file:
function uploadNext()
{
if (files.length > 0)
{
currentFile = files.pop();
uploadFile(currentFile);
}
}
function uploadFile(file)
{
var urlRequest = new air.URLRequest(url);
urlRequest.method = air.URLRequestMethod.POST;
file.addEventListener(air.ProgressEvent.PROGRESS, uploadProgress);
file.addEventListener(air.Event.COMPLETE, uploadComplete);
file.addEventListener(air.SecurityErrorEvent.SECURITY_ERROR, uploadError);
file.addEventListener(air.HTTPStatusEvent.HTTP_STATUS, uploadError);
file.addEventListener(air.IOErrorEvent.IO_ERROR, uploadError);
file.upload(urlRequest, "uploadfile");
}
The ploadFile() function sets a number of event listeners for the File object being uploaded:
function uploadProgress(event)
{
var uploadedAmt = uploadedSoFar + event.bytesLoaded;
event.bytesLoaded = uploadedAmt;
event.bytesTotal = totalSize;
air.trace("Progress", event.bytesLoaded, event.bytesTotal);
}
function uploadComplete(event)
{
uploadedSoFar += currentFile.size;
var newLocation = currentFile.parent.resolvePath("uploaded/" + currentFile.name);
uploadNext();
}
function uploadError(event)
{
var errorStr = event.toString();
air.trace("Error uploading: " + currentFile.nativePath + "\n Message: " + errorStr);
}
Note that the uploadComplete() function—the event handler that is called when a file is uploaded—calls the uploadNext() function to upload the next file (if there is one).
The PHP page you posted on your web server recognizes the string as its cue to accept the file provided as POST data as a file to be uploaded (and saved on the web server, in an “uploaded” subdirectory).
The appInit() function sets up an event listener for the exiting event, which is dispatched by the NativeApplication object when the application exits:
air.NativeApplication.nativeApplication.addEventListener(air.Event.EXITING, appExiting);
The NativeApplication object dispatches the exiting event when the user closes the main. The appExiting() function handles the exiting event, saving the array of temporary files used during the session before the application actually closes:
function appExiting(event)
{
for (i = 0; i < temps.length; i++)
{
tempFile = temps[i];
tempFile.deleteFile();
}
}