16 November 2009
You should be familiar with Flex and with compiling a basic native C-based application.
Intermediate
Adobe AIR 2 applications can be packaged and delivered via a native installer application, such as an EXE installer file on Windows or a DMG file on Mac OS. Such applications have the ability to launch and communicate with native processes, using the NativeProcess class. This example application shows how to package an AIR application in a native installer. The AIR application launches a native application, which is installed with the AIR application. The Windows version of the AIR application includes an EXE file and the Mac OS version includes a native Mac OS application. In each case, the AIR application communicates with the native application using the standard input (STDIN) and standard output (STDOUT) streams.
The AIR application launches and communicates with the native application by using the ActionScript NativeProcess class. Native process launching and communication are available for AIR applications that use the extended desktop profile. These are applications that are packaged into native application installer applications (rather than via a cross-platform AIR file).
The NativeProcessTestFlash.fla file defines the user interface for the application. It also references the NativeProcessFlash.as file as the source of the document class for the application. Upon application initialization, the constructor method (in the NativeProcessFlash class) checks whether the AIR application supports the native process API:
if(NativeProcess.isSupported)
{
launchEchoTest();
}
else
{
textReceived.text = "NativeProcess not supported.";
}
If the application supports the native process API, then the launchEchoTest() method sets up the native process.
The launchEchoTest() method points to the appropriate version of the executable file (for Mac or Windows):
var file:File = File.applicationDirectory;
file = file.resolvePath("NativeApps");
if (Capabilities.os.toLowerCase().indexOf("win") > -1)
{
file = file.resolvePath("Windows/bin/echoTestWin.exe");
}
else if (Capabilities.os.toLowerCase().indexOf("mac") > -1)
{
file = file.resolvePath("Mac/bin/echoTestMac");
}
The launchEchoTest() method then passes that file reference as the executable property of a NativeFileStartupInfo object. And the method creates a new NativeProcess object:
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
process = new NativeProcess();
The launchEchoTest() method then sets up an event listener for the STDOUT stream of the native process:
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
The launchEchoTest() method then sets up an event listener for the standardInputProgress event of the native process. The NativeProcess object dispatches this event when the data written to the STDIN stream is flushed:
process.addEventListener(ProgressEvent.STANDARD_INPUT_PROGRESS, inputProgressListener);
The launchEchoTest() method then starts the native process:
process.start(nativeProcessStartupInfo);
The FLA file includes basic user interface controls. It lets the user define text to send to the STDIN stream of the native application. And it includes a text area for displaying content from the application’s STDOUT stream.
When the user clicks the Submit button, the writeData() method sends text to the STDIN stream of the native application. It sends the string from the textToSend control, using the writeUTF() method of the standardInput property of the NativeProcess object, and closes the STDIN stream:
process.standardInput.writeUTF(textToSend.text + "\n");
process.closeInput();
When the STDIN stream closes, it received data on the stream. The native process then echoes the text back to the AIR application, via its STDOUT stream. The application then closes.
The AIR application's onOutputData() method is the event handler for the standardOutputData event of the NativeProcess object. It relays the STDOUT text to the user interface:
textReceived.text = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
var date:Date = new Date();
dateField.text = date.toString();
The onOutputData() method then restarts the native process by calling the launchEchoTest() method:
launchEchoTest();
The application descriptor file uses the AIR 2 namespace. This gives the application access to the native process API, which is introduced in Adobe AIR 2:
application xmlns="http://ns.adobe.com/air/application/2.0beta2"
Note: This namespace will change after the beta release. It will not include "beta2" at the end.
The application descriptor file also includes the following definition:
<supportedProfiles>extendedDesktop</supportedProfiles>
This line of code ensures that the application will not run if packaged inadvertently as an AIR file. It can only be packaged into a native installer application. This puts the application in the extended desktop profile, which grants it the ability to call the native process API.
The source files include source C code for the native versions of application. The NativeApps/Mac/src/echoTestMac.c file is the source C code for the Mac version. The NativeApps/Windows/src/echoTestMac.c file is the source C code for the Windows version.
Both the Mac and Windows version of the application simply listen on the STDIN stream of the application and echo lines sent back to the STDOUT stream.
The Mac code includes the following lines:
#define BUFFER_SIZE 8192
int main(int argc, char** argv)
{
char buf[BUFFER_SIZE];
int cnt;
while ( !feof(stdin))
{
cnt = read(STDIN_FILENO, buf, sizeof buf);
if (-1 == cnt)
{
perror("read");
exit(1);
}
if (0 == cnt)
{
// eof reached...
exit(0);
}
write(STDOUT_FILENO, buf, cnt );
}
return 0;
}
The Windows code includes the following lines:
#define BUFFER_SIZE 8192
extern int _setmode( int, int );
extern int _fileno( FILE* );
void terminalHandler( int sig )
{
fclose( stdout );
exit(1);
}
int main(int argc, char** argv)
{
char buf[BUFFER_SIZE];
int cnt;
int bytesRead = 0;
_setmode( _fileno( stdin ), _O_BINARY );
_setmode( _fileno( stdout ), _O_BINARY );
signal( SIGABRT, terminalHandler );
signal( SIGTERM, terminalHandler );
signal( SIGINT, terminalHandler );
// close the pipe to exit the app
while ( !feof( stdin ) )
{
cnt = fread( buf, sizeof( char ), BUFFER_SIZE, stdin);
if ( ferror( stdin ))
{
perror("read failed");
exit(1);
}
fwrite( buf, sizeof( char ), cnt, stdout );
}
return 0;
}
Compile the C code into a native application for the operating systems your application will target. The source files for this sample include compiled versions for Windows and Mac OS.
When you test the application, the application has access to the native process API. When you package the application in a native installer version, it also has access to the native process API.
The extended desktop profile is the only profile supported for this application. This ensures that the application will not run if packaged inadvertently as an AIR file. It can only be packaged into a native installer application. When debugging an application that is limited to the extended desktop profile, the debugger knows to grant it access to the native process API.
If your application settings do not limit the application to the extended desktop profile, you can still debug with native profile functionality. To do this, invoke ADL from the command line and include the –profile extendedDesktop argument.
When packaging the application, you will create a native installer application file. This file is an EXE installer file on Windows, and it is a DMG file on Mac OS.
For more information, refer to the following documentation: