Chapter 1: Introducing native extensions
for Adobe AIR
Native Extensions for Adobe AIR are code libraries that contain native code wrapped with an ActionScript API. You
can use native extensions in an AIR application to access platform features not supported by AIR, to benefit from
native-code-level performance for critical algorithms, and to reuse existing native code libraries.
About native extensions
What is Adobe AIR?
Adobe® AIR® is a cross-operating system runtime that allows content developers to build rich Internet applications
(RIAs). The developers can deploy the RIAs to the desktop, mobile devices, and digital home devices. AIR applications
can be built using Adobe® Flex® and Adobe® Flash® (SWF-based) and also with HTML, JavaScript, and Ajax (HTMLbased). For more information about the Adobe Flash Platform tools that you can use to build AIR applications, see
Adobe Flash Platform tools for AIR development in Building Adobe AIR Applications.
1
What is Adobe ActionScript?
SWF-based AIR applications can use Adobe ActionScript® 3.0. ActionScript 3.0 is an object-oriented language that can
add interactivity and data-handling to RIAs. For more information about the language, see
and ActionScript 3.0 Developer's Guide.
ActionScript provides many built-in classes. For example, MovieClip, Array, and NetConnection are built-in
ActionScript classes. Additionally, a content developer can create application-specific classes. Sometimes an
application-specific class derives from a built-in class.
The runtime executes the code in ActionScript classes. The runtime also executes JavaScript code that is used in
HTML-based applications.
Learning ActionScript 3.0
What is a native extension?
A native extension is a combination of:
• ActionScript classes.
• Native code. Native code is defined here as code that executes outside the runtime. For example, code that you write
in C is native code. On some platforms, Java code is supported in extensions. For the purpose of this
documentation, this is also considered “native” code.
Reasons to write a native extension include the following:
• A native code implementation provides access to device-specific features. These device-specific features are not
available in the built-in ActionScript classes, and are not possible to implement in application-specific ActionScript
classes. The native code implementation can provide such functionality because it has access to device-specific
hardware and software.
• A native code implementation can sometimes be faster than an implementation that uses only ActionScript.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Introducing native extensions for Adobe AIR
• A native code implementation allows you to reuse existing code.
For example, you could create a native extension that allows an application to do the following:
• make a mobile device vibrate.
• interact with device-specific libraries and features.
When you have finished your ActionScript and native implementations, you package your extension. Then, an AIR
application developer can use the package to call your extension’s ActionScript APIs to execute device-specific
functionality. The extension runs in the same process as the AIR application.
Native extensions versus the NativeProcess ActionScript class
ActionScript 3.0 provides a NativeProcess class. This class lets an AIR application execute native processes on the host
operating system. This capability is similar to native extensions, which provide access to device-specific features and
libraries. When deciding on using the NativeProcess class versus creating a native extension, consider the following:
• Only the extendedDesktop AIR profile supports the NativeProcess class. Therefore, for applications with the AIR
profiles
• Native extension developers often provide native implementations for various platforms, but the ActionScript API
they provide is typically the same across platforms. When using the NativeProcess class, ActionScript code to start
the native process can vary among the different platforms.
• The NativeProcess class starts a separate process, whereas a native extension runs in the same process as the AIR
application. Therefore, if you are concerned about code crashing, using the NativeProcess class is safer. However,
the separate process means that you possibly have interprocess communication handling to implement.
mobileDevice and extendedMobileDevice, native extensions are the only choice.
2
Native extensions versus ActionScript class libraries (SWC files)
The most important difference between a native extension and a SWC file is that the SWC file contains no native code.
Therefore, if you determine that you can accomplish your goal without native code, use a SWC file rather than a native
extension.
More Help topics
About SWC files
Supported devices
You can create native extensions for the following devices:
• Android devices, starting with AIR 3 and Android 2.2.
• iOS devices, starting with AIR 3 and iOS 4.0
• iOS Simulator, starting with AIR 3.3
• Blackberry PlayBook, starting with AIR 2.7
• Windows desktop devices that support AIR 3.0
• Mac OS X desktop devices that support AIR 3.0
An extension can target multiple platforms. For more information, see “Targeting multiple platforms” on page 5.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Introducing native extensions for Adobe AIR
Supported device profiles
The following AIR profiles support native extensions:
• extendedDesktop, starting in AIR 3.0
• mobileDevice, starting in AIR 3.0
More Help topics
AIR profile support
Native extensions architecture
Architecture overview
AIR allows an extension to do the following:
• Call functions implemented in native code from ActionScript.
• Share data between ActionScript and the native code.
• Dispatch events from the native code to ActionScript.
When you create a native extension, you provide the following:
3
• ActionScript extension classes that you define. These ActionScript classes use the built-in ActionScript APIs that
allow access to and data exchange with native code.
• A native code implementation. The native code uses native code APIs that allow access to and data exchange with
your ActionScript extension classes.
• Resources, such as images, that the ActionScript extension class or the native code uses.
Your native extension can target multiple platforms. When it does, you can provide a different set of ActionScript
extension classes and a different native code implementation for each target platform. For more information, see
“Targeting multiple platforms” on page 5.
The following illustration shows the interactions between the native extension, the AIR runtime, and the device.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Introducing native extensions for Adobe AIR
AIR application
Extension resources
ActionScript
extension classes
Device operating system and libraries
Native extension architecture
(for example, images)
Native
implementation
extension
AIR runtime
Native code programming languages
Adobe AIR provides native code APIs that your native code implementation uses for interacting with the ActionScript
extension classes. These APIs are available in:
4
• the C programming language.
• Java
Your native code implementation uses either the C APIs or the Java APIs, but not both, for interacting with the
ActionScript extension classes. However, the rest of your native code implementation does not have to exclusively use
the same language as the APIs. For example, a developer using the C API can also use:
• C++
• Objective-C
• assembler code to take advantage of highly optimized routines
The following table shows which extension API to use depending on the target device:
DeviceNative code API to use
Android devicesJava API with the Android SDK.
C API with the Android NDK.
iOS devicesC API
Blackberry PlayBookC API
Windows desktop devices C API
Mac OS X desktop devices C API
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Introducing native extensions for Adobe AIR
Targeting multiple platforms
A native extension often targets multiple platforms. For example, an extension can target devices running iOS and
devices running Android. In this case, your ActionScript class implementation and your native code implementation,
including the native code language, can vary based on the target platform.
A best practice is for your ActionScript extension classes to provide the same ActionScript public interfaces regardless
of their implementation. By keeping the public interfaces the same, you have a true cross-platform native extension. If
the ActionScript public interfaces are the same, but the ActionScript implementation is different, you create a different
ActionScript library for each platform.
You can also create extensions that do not have a native code implementation for some target platforms. Such an
extension is useful in the following situations:
• When only some target platforms support a native implementation of the desired functionality.
An extension can use a native implementation on those platforms, but use an ActionScript-only implementation
on other platforms. For example, consider one platform that provides a specialized mechanism for communication
between computer processes. The extension for that platform has a native implementation. The same extension for
another platform is ActionScript-only, using ActionScript Socket classes.
When application developers use the extension, they can write one application without knowing how the extension
is implemented on the different target platforms.
5
• When testing an extension.
Consider a native extension that uses a specific feature of a mobile device. You can create an ActionScript-only
extension for the desktop. Then, an application developer can use the desktop extension for simulation testing
during development before testing on the real target device. Similarly, as an extension developer, you can test the
ActionScript side of your extension before involving your native code implementation.
When you publish an extension, you specify the target platforms in an extension descriptor file in a <platform>
element. Each
<platform> element named default. The default platform has an ActionScript-only implementation to use on all
platforms not specified with a
<platform> element names a target, such as iPhone-ARM or Windows-x86. You can also specify a
<platform> element. For more information, see “Native extension descriptor files” on
page 72.
Note: The implementation for at least one targeted platform must contain native code. If no targeted platforms require
native code, then using native extensions is not the correct choice. In such cases, create a SWC library.
Extension availability at runtime
A native extension is available at runtime to an application in one of the following ways:
Application-bundling The extension is packaged with the AIR application, and installed with the application onto the
target device. An extension package typically contains the native and ActionScript implementations for multiple
platforms, but can contain only one platform’s native and ActionScript implementations. Sometimes the extension
package also contains an ActionScript-only implementation for unsupported platforms or for test platforms.
Device-bundling The extension is installed independently of any AIR application in a directory on the target device.
To use device-bundling, you typically work with the device manufacturer to install the extension on the device.
The following table shows which devices support application-bundling and device-bundling:
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Introducing native extensions for Adobe AIR
Application-bundlingDevice bundling
AndroidYesNo
iOSYesNo
Blackberry PlayBookYesYes
WindowsYesNo
Mac OS XYesNo
Extension contexts
A native extension is loaded once each time an application runs. However, to use the native implementation, the
ActionScript part of your extension calls a special ActionScript API to create an extension context.
A native extension can do either of the following.
• Create only one extension context.
Only one extension context is typical for a simpler extension that provides only one set of functions in the native
implementation.
• Create multiple extension contexts that co-exist.
Multiple extension contexts are useful to associate ActionScript objects with native objects. Each association
between an ActionScript object and a native object is one extension context instance. These extension context
instances can have different context types. The native implementation can provide a different set of functions for
each context type.
6
Each extension context can have context-specific data that you define and use in your native implementation.
An extension context can only be created by the ActionScript code in an extension. It cannot be created by the native
code or by the application code.
Task overview to create a native extension
To create a native extension, do the following tasks:
1 Define the methods and properties of the ActionScript extension classes.
2 Code the ActionScript extension classes.
See “Coding the ActionScript side” on page 7.
3 Code the native implementation.
See “Coding the native side with C” on page 15 and “Coding the native side with Java” on page 30.
4 Build the ActionScript side and the native side, create an extension descriptor file, and package the extension and
its resources.
See “Packaging a native extension” on page 39 for all devices.
5 Document the public interfaces of the ActionScript extension class.
Typically, as with any software development, working through these steps is an iterative process.
Last updated 1/27/2017
Chapter 2: Coding the ActionScript side
A native extension is made of two parts:
• ActionScript extension classes you define.
• A native implementation.
The ActionScript extension classes access and exchange data with the native implementation. This access is provided
with the ActionScript class ExtensionContext. Only ActionScript code that is part of an extension can access the
ExtensionContext class methods.
Coding the ActionScript side of your extension includes the following tasks:
• Declaring the public interfaces of your ActionScript extension class.
• Using the static method ExtensionContext.createExtensionContext() to create an ExtensionContext
instance.
• Using the call() method of the ExtensionContext instance to call methods in the native implementation.
• Adding event listeners to the ExtensionContext instance to listen for events dispatched from the native
implementation.
• Using the dispose() method to delete the ExtensionContext instance.
• Sharing data between the ActionScript side and the native side. The data shared can be any ActionScript object.
• Using the getExtensionDirectory() method to access the directory in which the extension is installed. All
information and resources related to the extension are in this directory. (An exception to this rule exists for iOS
devices.)
For examples of native extensions, see Native extensions for Adobe AIR.
7
For more information about the ExtensionContext class, see the ActionScript 3.0 Reference for the Adobe Flash
Platform.
Declare the public interfaces
The first step in creating a native extension is determining the extension’s public interfaces. Application code uses
these public interfaces to interact with the extension. ActionScript code goes in files with the .as extension. Create a .as
file with your class definition. For example, the following code shows the declaration of a simple TVChannelController
extension class, without yet filling in its implementation. This simple class allows an application to manipulate the
channel setting on a hypothetical TV.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the ActionScript side
package com.example {
public class TVChannelController extends EventDispatcher {
public function TVChannelController() {
}
public function set currentChannel(channelToSet:int):void {
}
public function get currentChannel():int {
}
}
}
Note: When designing your public interfaces, consider whether you will release subsequent versions of your extension. If
so, consider backward compatibility support in your initial design. For more information about backward compatibility
issues for device-bundled extensions, see
“Native extension backward compatibility” on page 13.
Check for native extension support
8
A best practice is to always define a public interface that provides a handshake between the native extension and the
AIR application. Instruct AIR application developers using your extension to check this method before calling any
other extension method.
For example, consider an ActionScript extension class public interface called isSupported(). The isSupported()
method allows an AIR application to make logic decisions based on whether the device on which the application is
running supports the extension. If
isSupported() returns false, the AIR application must decide what to do without
the extension. For example, the AIR application can decide to exit.
Create an ExtensionContext instance
To begin working with the native implementation, the ActionScript extension class uses the ExtensionContext static
method
package com.example {
}
createExtensionContext(). This method returns a new instance of the ExtensionContext class.
public class TVChannelController extends EventDispatcher {
In this example, the constructor calls createExtensionContext(). Although your extension classes can call
createExtensionContext() in any method, typically a constructor or other initialization method calls it. Save the
returned ExtensionContext instance in a data member of the class.
Note: Calling createExtensionContext() as part of a static data member’s definition is not recommended. Doing so
means that the runtime creates the extension context earlier than the application needs it. If the application’s execution
path does not eventually use the extension, creating the context wastes device resources.
The method createExtensionContext() takes two parameters: an extension ID and a context type.
The extension ID
The method createExtensionContext() takes a String parameter that is the identifier, or name, of the extension.
This name is the same name you use in the extension descriptor file in the
descriptor file when you package your extension). The application developers also use this name in the
element in their application descriptor file. If an extension with the specified name is not available, then
createExtensionContext() returns Null.
To avoid name conflicts, Adobe recommends using reverse DNS for an extension ID. For example, the ID of the
TVControllerChannel extension is
com.example.TVControllerExtension. Because all extensions share a single,
global namespace, using reverse DNS for the extension ID avoids name conflicts between extensions.
id element. (You create the extension
extensionID
9
The context type
The method createExtensionContext() takes a String parameter that is the context type for the new extension
context. This string specifies more information about what the new extension context is to do.
For example, suppose the extension com.example.TVControllerExtension can manipulate both channel and volume
settings. Passing
"channel" or "volume" in createExtensionContext() indicates which functionality the new
extension context will be used for. Another ActionScript class in the extension, such as TVVolumeController, could
createExtensionContext() with "volume" for the contextType value. The native implementation uses the
call
contextType value in its context initialization.
Typically, each possible context type value you define corresponds to a different set of methods in your native
implementation. The context type, therefore, corresponds to what is, in effect, a class in your native implementation.
If you call
createExtensionContext()multiple times with the same context type, typically your native
implementation creates multiple instances of a particular native class.
When the context types of multiple calls to createExtensionContext()are different, the native side typically
performs different initializations. Depending on the context type, the native side can create an instance of a different
native class and can provide a different set of native functions.
Note: A simple extension often has only one context type. That is, it has only one set of methods in the native
implementation. In this simple case, the context type String parameter can be
Null.
Call a native function
After the ActionScript extension class has called ExtensionContext.createExtensionContext(), it can call
methods in the native implementation. The TVChannelController example calls native methods
"setDeviceChannel" and "getDeviceChannel" as follows:
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the ActionScript side
package com.example {
public class TVChannelController extends EventDispatcher {
private var extContext:ExtensionContext;
private var channel:int;
channel = int (extContext.call("getDeviceChannel"));
return channel;
}
}
10
The call() method of ExtensionContext takes these parameters:
• functionName. This string represents a function in the native implementation. In the TVChannelController
example, these strings are different from the ActionScript method names. You can choose to make the names the
same. You can also choose whether a
represents. In your native implementation, you provide the association between this
native function. The association is in an output parameter of your
functionName string is the same as the name of the native function that it
functionName string and the
FREContextInitializer() method. See
“Extension context initialization” on page 17.
• An optional list of parameters. Each parameter is passed to the native function. A parameter can be a primitive type,
such as an int, or any ActionScript Object.
The return value of the call() method of ExtensionContext is a primitive type or any ActionScript Object. The
subclass of Object that it returns depends on what the native function returns. For example, the native function
"getDeviceChannel" returns an int.
Listen for events
The native implementation can dispatch events that the ActionScript extension code can listen for. This mechanism
allows the native implementation to perform tasks asynchronously, notifying the ActionScript side when the task is
complete.
The event target is the ExtensionContext instance. Therefore, use the addEventListener() method of the
ExtensionContext instance to subscribe to events from the native implementation.
The following example adds code to TVChannelController to receive an event from the native implementation. The
application using the extension calls the ActionScript extension class method
native function
"scanDeviceChannels".
scanChannels(), which in turn calls the
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the ActionScript side
This native function asynchronously scans for all available channels. When it has completed the scan, it dispatches an
event. The
of channels. The
onStatus() method handles the event by querying the native method "getDeviceChannels" for the list
onStatus() method stores the list in the scannedChannelList data member, and dispatches an
event to the application’s listening object. When the application object receives the event, it can call the ActionScript
extension class property accessor
package com.example {
public class TVChannelController extends EventDispatcher {
private var extContext:ExtensionContext;
private var channel:int;
private var scannedChannelList:Vector.<int>;
extContext.addEventListener(StatusEvent.STATUS, onStatus);
}
.
.
.
public function scanChannels():void {
extContext.call("scanDeviceChannels");
}
public function get availableChannels():Vector.<int> {
return scannedChannelList;
}
private function onStatus(event:StatusEvent):void {
if ((event.level == "status") && (event.code == "scanCompleted")) {
scannedChannelList = (Vector.<int>)(extContext.call("getDeviceChannels"));
dispatchEvent (new Event ("scanCompleted") );
}
}
}
}
availableChannels.
"com.example.TVControllerExtension", "channel");
11
The example illustrates the following points:
• The native implementation can dispatch only a StatusEvent object. Therefore, the addEventListener() method
listens for the event type
StatusEvent.STATUS.
• The native implementation sets the code and level properties of the StatusEvent object. You can define the strings
you want to use for these properties. In this example, the native implementation sets the
status" and the code property to "scanCompleted". Typically, the level property of a StatusEvent has the value
“
"status", "info", or "error".
level property to
• Because TVChannelController is a subclass of EventDispatcher, it can also dispatch an event. In this example, it
dispatches an Event object with the
type property "scanCompleted". Any ActionScript object interested in this
event can listen for it. For example, the following code shows a snippet from an AIR application that uses this
extension. The application creates a TVChannelController object. Then, it asks the TVChannelController object to
scan for channels. Then it waits for the scan to complete.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the ActionScript side
var channelController:TVChannelController = new TVChannelController();
channelController.addEventListener("scanCompleted", onChannelsScanned);
channelController.scanChannels();
var channelList:Vector.<int>;
private function onChannelsScanned(evt:Event):void {
The ActionScript extension class can dispose of the ExtensionContext instance by calling the ExtensionContext
method
example, the TVChannelController class can add a method for cleaning up:
public function dispose (): void {
}
dispose(). This method notifies the native implementation to clean up resources that the instance uses. For
extContext.dispose();
// Clean up other resources that the TVChannelController instance uses.
12
Your ActionScript extension class does not have to explicitly call the ExtensionContext instance’s dispose()method.
In this case, the runtime calls it when the runtime garbage collector disposes of the ExtensionContext instance. A best
practice, however, is to explicitly call
dispose(). An explicit call to dispose()typically cleans up resources much
sooner than waiting for the garbage collector.
Whether called explicitly or by the garbage collector, the ExtensionContext dispose() method results in a call to the
native implementation’s context finalizer. For more information, see
“Extension context finalization” on page 18.
Access the native extension’s directory
Sometimes extensions include additional files, such as images. An extension sometimes also wants to access the
information in the extension descriptor file, such as the extension version number.
To access these files for extensions on all devices except iOS devices, use the ExtensionContext class static method
getExtensionDirectory(). For example:
var extDir:File =
ExtensionContext.getExtensionDirectory("com.example.TVControllerExtension");
Pass the name of the extension to getExtensionDirectory(). This String value is the same name you use in:
• the extension descriptor file in the id element.
• the extension ID parameter you pass to ExtensionContext.createExtensionContext().
The returned File instance refers to the base extension directory. The extension directory has the following structure:
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the ActionScript side
extension base directory/
platform independent files
META-INF/
ANE/
extension.xml
platform name/
platform dependent files and directories
Regardless where the extension directory is on the device, the extension’s files are always in the same location relative
to the base extension directory. Therefore, use the returned File instance and File class methods to navigate to and
manipulate specific files included with the extension.
The extension directory location depends on whether the extension is available through application-bundling or
device-bundling as follows:
• With application-bundling, the extension directory is located within the application directory.
• With device-bundling, the extension directory location depends on the device.
An exception to using getExtensionDirectory() exists for ActionScript extensions for iOS devices. The resources
for these extensions are not located in the extension directory. Instead, they are located in the top-level application
directory. For more information, see
“Resources on iOS devices” on page 54.
13
More Help topics
“Extension availability at runtime” on page 5
Identify the calling application from a native extension
The ActionScript side of your extension can identify and evaluate the AIR application using the extension. For
example, use the ActionScript class
signature data. Then the ActionScript side can make runtime decisions based on this information.
Sometimes the native implementation has similar runtime decisions to make. In this case, the ActionScript side can
call() method of an ExtensionContext instance to report the application information to the native
use the
implementation.
NativeApplication to get information about the AIR application, such as its ID and
Native extension backward compatibility
Backward compatibility and the extension’s public interfaces
A best practice is to maintain backward compatibility in your extension’s ActionScript public interfaces. Continue to
support the extension’s classes, methods, properties, and events in all subsequent versions of the extension.
Device-bundled extensions have a more complex issue with regard to backward compatibility. Sometimes, the
behavior of an extension is different between versions of an extension. For example, a particular method returns a value
with a new meaning in a new version of the extension. When this behavior occurs for device-bundled extensions, an
application can stop working correctly. This problem can occur if the application was built with a version of the
extension that behaves differently than the version of the extension installed on the device. In this case, the application
expects one behavior, but the installed extension provides a different behavior.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the ActionScript side
In such cases, the extension installed on the device can determine how to proceed. The extension can do the following:
• Look up the extension version that the AIR application was built with as well as the version installed on the device.
• Determine whether the extension’s behavior is different in the two versions.
• If the AIR application was built with an older version of the extension, revert to the older version’s behavior.
Note: Typically an AIR application that was built with a newer version of an extension is not available on the device.
For more information, see
“Backward compatibility and the device’s application store” on page 14.
To look up the extension version number that the application was built with, do the following:
1 Get the application installation directory using File.applicationDirectory.
2
Use the File class APIs to access the extension.xml file of the extension that the application built against. The file is at:
3 Read the contents of the extension.xml file and find the value of the <versionNumber> element.
To look up the installed extension’s version number, do the following:
1 Use the static method ExtensionContext.getExtensionDirectory() to get the base directory for the
extension.
2 Use the File class APIs to access the extension.xml file of the extension installed on the device. The file is at:
<extension base directory>/META-INF/ANE/extension.xml
14
3 Read the contents of the extension.xml file and find the value of the <versionNumber> element.
Backward compatibility and the device’s application store
An AIR application that was built with a newer version of the extension than is installed on the device is typically not
available on the device. The application is not available because of how device manufacturers handle requests from the
device’s application store to a server to download such an application. Adobe recommends the following handling to
the device manufacturers:
• Consider the case when the server downloads an application that uses a newer version of the extension. The server
also downloads the newer version of the extension. The device’s application store installs both the application and
the newer version of the extension.
• Consider the case when the server cannot download a newer version of the extension. The server also does not
download the application that uses that version of the extension. The device’s application store handles the scenario
gracefully, informing the end user as needed.
• Consider the case when the server downloads an application that uses a newer version of the extension, but does
not download the newer version of the extension. The device’s application store does not allow the end user to run
the application. The application store handles the scenario gracefully, informing the end user as needed.
Last updated 1/27/2017
Chapter 3: Coding the native side with C
Some devices use the C programming language in their native implementations. If you are targeting your native
extension for such a device, use the native extensions C API to code the native side of your extension.
The C API is in the file FlashRuntimeExtensions.h. The file is available in the AIR SDK in the include directory. The
AIR SDK is available at
The AIR runtime connects the ActionScript side of an extension to the native side of the extension.
Using the C API, you do the following tasks:
• Initialize the extension.
• Initialize each extension context when it is created.
• Define functions that the ActionScript side can call.
• Dispatch events to the ActionScript side.
• Access data passed from the ActionScript side, and pass data back to the ActionScript side.
• Create and access context-specific native data and context-specific ActionScript data.
• Clean up extension resources when the extension’s work is done.
For details about each C API function, such as parameters and return values, see “Native C API Reference” on page 81.
http://www.adobe.com/products/air/sdk/.
15
For examples of native extensions that use the C API, see Native extensions for Adobe AIR.
Extension initialization
The runtime calls an extension initialization function on the native side. The runtime calls this initialization function
once each time the application that uses the extension runs. Specifically, the runtime calls the initialization function
the first time the extension calls
The function initializes data that all extension contexts can use. Define your extension initializer function with the
signature of
For example:
void MyExtensionInitializer
{
extDataToSet = NULL; // This example does not use any extension data.
*ctxInitializerToSet = &MyContextInitializer;
*ctxFinalizerToSet = &MyContextFinalizer;
}
The FREInitializer() method that you define returns the following data to the runtime:
• A pointer to the data that the runtime later passes to each new extension context. For example, if all extension contexts
use the same utility library, this data can include a pointer to the library. This data is called the extension data.
The extension data can be any data you choose. It can be a simple primitive data type, or a pointer to a structure
you define. In this example, the pointer is
ExtensionContext.createExtensionContext() for any context.
NULL because the extension does not have a use for this data.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
• A pointer to the context initialization function. Each time the ActionScript side calls
ExtensionContext.createExtensionContext(), the runtime calls an extension context initialization function
that you provide. See
“FREContextInitializer()” on page 88.
• A pointer to the context finalizer function. The runtime calls this function when the runtime disposes of the
extension context. This call occurs when the ActionScript side calls the ExtensionContext instance’s
method. If
dispose() is not called, the runtime garbage collects the ExtensionContext instance. See
dispose()
“FREContextFinalizer()” on page 87.
For application-bundled extensions, your implementation of FREInitializer()can have any name. Specify the
name of the initialization function in the extension descriptor file. See
“Native extension descriptor files” on page 72.
For device-bundled applications, how to specify the extension initializer function is device-dependent.
The following sequence diagram shows the AIR runtime calling the FREInitializer() function. It also shows context
initialization. For more information, see
“Extension context initialization” on page 17.
16
AIR
ActionScript extension classes
application
ActionScript extension
class API
Extension initialization sequence
for extension A
ExtensionContext.
createExtensionContext()
• extension ID
• context type
AIR
runtime
FREInitializer()
(called only on rst call
to this extension’s
createExtensionContext())
pointer to extension data
pointer to FREContextInitializer()
pointer to FREContextFinalizer()
FREContextInitializer()
• extension data
• context type
• FREContext value
FRESetContextNativeData()
• FREContext value
• native data
FREContextInitializer()
returns an array of pointers to
FRENamedFunction structures
Each structure contains:
• a pointer to a native function
• the name of the function as
called from ActionScript
• a pointer to function data
C native implementation
for extension A
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
Extension context initialization
To use the native C methods, the ActionScript side of your extension first calls the static method
ExtensionContext.createExtensionContext(). Calling createExtensionContext() causes the runtime to do
the following:
• Create an ExtensionContext instance.
• Create internal data it uses to track the extension context.
• Call the extension context initialization function.
The extension context initialization function initializes the native implementation for the new extension context.
Define your extension context initializer function with the signature of
For example, the Vibration example uses the following function:
A context initialization function receives the following input parameters:
• The extension data that the extension initialization function had created. See “Extension initialization” on page 15.
• The context type. The ActionScript method ExtensionContext.createExtensionContext()is passed a
parameter that specifies the context type. The runtime passes this string value to the context initialization function.
The function then uses the context type to choose the set of methods in the native implementation that the
ActionScript side can call. Each context type typically corresponds to a different set of methods. See
“The context
type” on page 9.
The value of the context type is any string agreed to between the ActionScript side and the native side.
If your extension has only one set of methods in the native implementation, pass null or an empty string in
ExtensionContext.createExtensionContext(). Then ignore the context type parameter in the extension
context initializer.
• A FREContext value. The runtime creates internal data when it creates an extension context. It associates the
internal data with the ExtensionContext class instance on the ActionScript side.
When your native implementation dispatches an event the ActionScript side, it specifies this FREContext value.
The runtime uses the FREContext value to dispatch the event to the corresponding ExtensionContext instance. See
“FREDispatchStatusEventAsync()” on page 95.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
Also, native functions can use this value to access and set the context-specific native data and context-specific
ActionScript data.
The extension context initialization function sets the following output parameters:
• An array of native functions. The ActionScript side can call each of these functions by using the ExtensionContext
instance’s
The type of each array element is FRENamedFunction. This structure includes a string which is the name the
ActionScript side uses to call the function. The structure also includes a pointer to the C function you write. The
runtime associates the name with the C function. Although the name string does not have to match the actual
function name, typically you use the same name.
call() method.
• The number of functions in the array of native functions.
A sequence diagram showing the AIR runtime calling the FREContextInitializer() function is in “Extension
initialization” on page 15.
More Help topics
Vibration native extension example
18
Context-specfic data
Context-specific data is specific to an extension context. (Recall that extension data is for all extension contexts in an
extension). The context initialization method, context finalization method, and native extension methods can create,
access, and modify the context-specific data.
The context-specific data can include the following:
• Native data. This data is any data you choose. It can be a simple primitive data type, or a structure you define. See
“FREGetContextNativeData()” on page 99 and “FRESetContextNativeData()” on page 114.
• ActionScript data. This data is an FREObject variable. Since an FREObject variable corresponds to an ActionScript
class object, this data allows you to save and later access an ActionScript object. See
“FREGetContextActionScriptData()” on page 98 and “FRESetContextActionScriptData()” on page 113. Also see
“The FREObject type” on page 22.
A sequence diagram showing the native implementation setting context-specific native data is in “Extension
initialization” on page 15. A sequence diagram showing the native implementation getting the context-specific data is
in “Extension functions” on page 20.
Extension context finalization
The ActionScript side of your extension can call the dispose() method of an ExtensionContext instance. Calling
dispose() causes the runtime to call the context finalization function of your extension. Define your extension
context finalization function with the signature of
FREContextFinalizer().
This method has one input parameter: the FREContext value. You can pass this FREContext value to
FREGetContextNativeData() and FREGetContextActionScriptData() to access the context-specific data. Clean
up any data and resources associated with this context.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
If the ActionScript side does not call dispose(), the runtime garbage collector disposes of the ExtensionContext
instance when no more references to it exist. At that time, the runtime calls your context finalization function.
The following sequence diagram shows the AIR runtime calling the FREContextFinalizer() function:
19
AIR
application
ActionScript extension
class API
Extension context finalization sequence
ActionScript extension classes
for extension A
ExtensionContext.dispose()
AIR
runtime
FREContextFinalizer()
• FREContext value
C native implementation
for extension A
Extension finalization
The C API provides an extension finalization function for the runtime to call when it unloads the extension. However,
the runtime does not always unload an extension. Therefore, the runtime does not always call the extension
finalization function.
Define your extension finalization function with the signature of FREFinalizer(). This method has one input
parameter: the extension data you created in your extension initialization function. Clean up any data and resources
associated with this extension.
For application-bundled extensions, your implementation of FREFinalizer()can have any name. Specify the name
of the finalization function in the extension descriptor file. See
For device-bundled applications, how to specify the extension finalization function is device-dependent.
Last updated 1/27/2017
“Native extension descriptor files” on page 72.
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
Extension functions
The ActionScript side of your extension calls C functions you implement by calling the ExtensionContext instance’s
call() method. The call() method takes these parameters:
• The name of the function. You provided this name in an output parameter of your context initialization function.
This name is an arbitrary string agreed to between the ActionScript side and the native side. Typically, it is the same
name as the actual name of the native C function. However, these names can be different because the runtime
associates the arbitrary name with the actual function.
• A list of arguments for the native function. These arguments can be any ActionScript objects: primitive types or
ActionScript class objects.
Define each of your native functions with the same function signature: FREFunction(). The runtime passes the
following parameters to each native function:
• The FREContext value. The native function can use this value to access and set the context-specific data. Also, the
native implementation uses the FREContext value to dispatch an asynchronous event back to the ActionScript side.
• A pointer to the data associated with the function. This data is any native data. When the runtime calls the native
function, it passes the function this data pointer.
• The number of function parameters.
• The function parameters. Each function parameter has the type FREObject. These parameters correspond to
ActionScript class objects or primitive data types.
A native function also has a return value with the type FREObject. The runtime returns the corresponding
ActionScript object as the return value for the ExtensionContext
call() method.
20
Note: Do not set a native function’s visibility to hidden. Use the default visibility.
The following sequence diagram shows an AIR application making a function call that results in calling a native C
function named
FREFunctionF(). In this example, the C function:
• Gets the context-specific native data.
• Gets the int32 value of an ActionScript object.
• Starts an asynchronous thread which later dispatches an event.
Note: The behavior of the C function FREFunctionF() is only a sample behavior to illustrate a call sequence.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
21
AIR
application
ActionScript extension classes
ActionScript extension
class API
for extension A
ExtensionContext.call()
• function name
• function arguments
AIR
runtime
FREFunctionF()
• FREContext value
• pointer to function data
• function arguments
FREGetContextNativeData()
• FREContext value
native data
FREGetObjectAsInt32()
• FREObject variable
int32 value
FREFunctionF returns
FREDispatchStatusEventAsync()
• FREContext value
• event code
• event level
FREDispatchStatusEventAsync() returns
C native implementation
for extension A
start asynchronous thread
• FREContext value
Asynchronous
native thread
StatusEvent
• event code
• event level
Native function sample call sequence
Dispatching asynchronous events
The native C code can dispatch asynchronous events back to the ActionScript side of your extension. For example, an
extension method can start another thread to perform some task. When the task in the other thread completes, that
thread calls
event is an ActionScript ExtensionContext instance.
The sequence diagram in “Extension functions” on page 20 shows a native C function starting an asynchronous thread,
which later dispatches an event.
More Help topics
“FREDispatchStatusEventAsync()” on page 95
FREDispatchStatusEventAsync() to inform the ActionScript side of the extension. The target of the
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
The FREObject type
A variable of type FREObject refers to an object that corresponds to an ActionScript class object or primitive type. You
use an FREObject variable in your native implementation to work with ActionScript data. A primary use of the
FREObject type is for native function parameters and return values.
When you write a native function, you decide on the order of the parameters. Since you also write the ActionScript
side, you use that parameter order in the ExtensionContext instance’s
native function parameter is an FREObject variable, you know its corresponding ActionScript type.
Similarly you decide on the ActionScript type of the return value, if any, of a native function. The call() method
returns an object of this type. Although the native function return value is always an FREObject variable, you know its
corresponding ActionScript type.
The extensions C API provides functions for using the object that an FREObject variable refers to. Because these
objects correspond to ActionScript data, these C API functions are how you access an ActionScript class object or
primitive data variable. The C APIs that you use depend on the type of the ActionScript object. The types are the
following:
• An ActionScript primitive data type
• An ActionScript class object
• An ActionScript String object
• An ActionScript Array or Vector class object
• An ActionScript ByteArray class object
• An ActionScript BitmapData class object
Note: You can call the extensions C APIs only from the same thread as the one in which the FREFunction function is
running. The one exception is the C API for dispatching an event to the ActionScript side. You can call that function,
FREDispatchStatusEventAsync(), from any thread.
call() method. Therefore, although every
22
Determining the type of an FREObject variable
Sometimes you don’t know the type of ActionScript Object that an FREObject variable corresponds to. To determine
the type, use the C API function
Once you know the type, use the appropriate C APIs to work with the value. For example if the type is
FRE_TYPE_VECTOR, use the C APIs in “Working with ActionScript Array and Vector objects” on page 27 to work with
the Vector object.
FREGetObjectType():
FREObject validity
If you attempt to use an invalid FREObject variable in a C API call, the C API returns an FRE_INVALID_OBJECT return
value.
Any FREObject variable is valid only until the first FREFunction function on the call stack returns. The first
FREFunction function on the call stack function is the one that the runtime calls due to the ActionScript side calling
the ExtensionContext instance’s
The following illustration illustrates this behavior:
call() method.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
FREFunctionC()
can use myobj
3
FREFunctionB()
creates FREObject myobj as a
global variable or allocated on the heap
2
FREFunctionA()
1
AIR runtime
FREObject validity on the call stack
calls indirectly
calls indirectly
calls
returns to
4
FREFunctionB()
which can
use myobj
5
returns to
FREFunctionA()
which can
use myobj
6
returns to
runtime
7
calls
FREFunctionA()
cannot use myobj
Note: An FREFunction function can indirectly call another FREFunction function. For example, FREFunctionA() can
call a method of an ActionScript object. That method then can call
FREFunctionB().
Therefore, when using an FREObject variable, consider the following:
23
• Any FREObject variable passed to an FREFunction function is valid only until the first FREFunction function on
the call stack returns.
• Any FREObject variable that any native function creates using the extensions C API is valid only until the first
FREFunction function on the call stack returns.
• You cannot use an FREObject variable in another thread. Only use the FREObject variable in the same thread as
the native function that received or created the variable.
• You cannot save an FREObject variable, for example in global data, between calls to FREFunction functions.
Because the variable becomes invalid when the first FREFunction function on the call stack returns, the saved
variable is useless. However, you can save the corresponding ActionScript object by using the method
FRESetContextActionScriptData().
• After an FREObject variable becomes invalid, the corresponding ActionScript object can still exist. For example, if
an FREObject variable is a return value of an FREFunction function, its corresponding ActionScript object is still
referenced. However, once the ActionScript side deletes its references, the runtime disposes of the ActionScript
object.
• You cannot share FREObject variables between extensions.
Note: You can share FREObject variables between extension contexts of the same extension. However, as in any case,
the FREObject variable becomes invalid when the first FREFunction function on the call stack returns to the runtime.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
Working with ActionScript primitive types and objects
Working with ActionScript primitive types
In your native functions, an input parameter can correspond to a primitive ActionScript type. All native function
parameters are of type FREObject. Therefore, to work with an ActionScript primitive type input parameter, you get
the ActionScript value of the FREObject parameter. You store the value in a corresponding primitive C data type
variable. Use the following C API functions:
If an output parameter or return value corresponds to a primitive ActionScript type, you create the ActionScript
primitive using a C API function. You provide a pointer to an FREObject variable and the value of the primitive in a
C data variable. The runtime creates the ActionScript primitive and sets the FREObject variable to correspond to it.
Use the following C API functions:
In your native functions, an input parameter can correspond to an ActionScript String class object. All native function
parameters are of type FREObject. Therefore, to work with an ActionScript String parameter, you get the ActionScript
String value of the FREObject parameter. You store the value in a corresponding C string variable. Use the C API
function
FREResult FREGetObjectAsUTF8(
);
FREGetObjectAsUTF8():
FREObject object,
uint32_t* length,
const uint8_t** value
After calling FREGetObjectAsUTF8(), the ActionScript String value is in the value parameter, and the length
parameter tells the length of the value string in bytes.
Last updated 1/27/2017
DEVELOPING NATIVE EXTENSIONS
Coding the native side with C
If an output parameter or return value corresponds to an ActionScript String class object, you create the ActionScript
String object using a C API. You provide a pointer to a FREObject variable and the string value and length in bytes in
C string variables. The runtime creates the ActionScript String object and sets the FREObject variable to correspond
to it. Use the C API function
FREResult FRENewObjectFromUTF8(
uint32_t length,
const uint8_t* value,
FREObject* object
);
FRENewObjectFromUTF8():
The value parameter strings must use UTF- 8 encoding and include the null terminator.
Note: All string parameters to any C API function use UTF-8 encoding and include the null terminator.
Working with ActionScript Class objects
In your native functions, an input parameter can correspond to an ActionScript class object. Since all native function
parameters are of type FREObject, the C APIs provide functions for manipulating class objects using an FREObject
variable.
Use the following C API functions to get and set a property of the ActionScript class object:
If an output parameter or return value corresponds to an ActionScript class object, you create the ActionScript object
using a C API. You provide a pointer to an FREObject variable plus FREObject variables to correspond to parameters
to the ActionScript class constructor. The runtime creates the ActionScript class object and sets the FREObject variable
to correspond to it. Use the following C API function:
Note: These general ActionScript object manipulation functions apply to all ActionScript class objects. However, the
ActionScript classes Array, Vector, ByteArray, and BitmapData are special cases because they each involve large amounts
of data. Therefore, the C API provides additional specific functions for manipulating objects of these special cases.
Working with ActionScript ByteArray objects
Use the ActionScript ByteArray class to efficiently pass many bytes between the ActionScript side and native side of
your extension. In your native functions, an input parameter, output parameter, or return value can correspond to an
ActionScript ByteArray class object.
As with other ActionScript class objects, an FREObject variable is the native side representation of an ActionScript
ByteArray object. The C APIs provide functions for manipulating a ByteArray class object using an FREObject
variable. Use
the ActionScript ByteArray object’s properties and to call its methods.
FRESetObjectProperty(), FREGetObjectProperty(), and FRECallObjectMethod()to get and set
26
However, to manipulate the bytes of the ByteArray object in the native code, use the C API function
FREAcquireByteArray(). This method accesses the bytes of a ByteArray object that was created on the ActionScript side:
FREResult FREAcquireByteArray(
FREObject object,
FREByteArray* byteArrayToSet
);
// The type FREByteArray is defined as:
typedef struct {
uint32_t length;
uint8_t* bytes;
} FREByteArray;
After you have manipulated the bytes, use the C API FREReleaseByteArray():
Note: Do not call any C API functions between the calls to FREAcquireByteArray() and FREReleaseByteArray().
This prohibition is because other calls could, as a side effect, execute code that invalidates the pointer to the byte array
contents.
Example
This example shows the ActionScript side of the extension creating a ByteArray object and initializing its bytes. Then
it calls a native function to manipulate the bytes.
Last updated 1/27/2017
Loading...
+ 111 hidden pages
You need points to download manuals.
1 point = 1 manual.
You can buy points or you can get point for every manual you upload.