# Developing native extensions for Adobe AIR

This tutorial introduces you to creating your own native extensions for Adobe AIR using simple code. In addition to showing you code and skills that are common across all native extensions (AIR, ActionScript 3, and Flash Builder), this tutorial covers the compilation of native code on the Android platform. Although you may be interested in targeting Objective-C, C#, C++, C, or some other language, the Java code should give you a solid understanding of native interaction with native extensions.

Before you begin

To make the most of this tutorial, be sure you have the following software installed:

• Adobe AIR 3 (included in Flash Builder) for mobile devices (AIR 2.5 or higher for Adobe AIR for TV-based extensions)
• Adobe Flex 4.6 (included in Flash Builder)
• Java API for AS extensions (included in the AIR 3 SDK, under lib/android/FlashRuntimeExtensions.jar)
You also need the following:
• An Android device for on-device testing. You may choose to use another platform, but the steps in the native-code portion of this guide will require that you maintain your own native build environment.
• A properly installed JDK and the Android SDK.

• Android SDK
• Installing the Android SDK
• Developing ActionScript Extensions for Adobe AIR

1、FlashBuilder4.6
3、一个Android设备用来测试

What are native extensions?

Adobe AIR has allowed application developers to extend the features of the runtime with a set of tools known as Native Extensions for Adobe AIR. This feature was enabled for AIR for TV starting with version 2.5, but it's now been expanded to work on mobile and desktop platforms. By using native extensions, your applications can access all of the features of your target platform, even if the runtime itself doesn't have built-in support.

To illustrate this point, imagine you're creating an application on an Android device, and want to vibrate the phone when your application completes a download. Without native extension support, you'd either have to code the entire program in Java, or use AIR and accept that this task would be impossible. With native extensions, however, you can create a bridge that spans between native code and your own application logic, allowing you to pass instructions back and forth, making it possible for your app to control the vibration motor. You could then leverage the multiplatform support of AIR to deploy this same app to iOS, and expand your native extension by including Objective-C code. You could even change the native code to be platform-aware, allowing you to change the vibration duration and pattern whether the app is running on Android or iOS.

Native extensions allow you to harness unique and platform-specific capabilities of your devices; they also allow you to use native code in ActionScript apps; reuse existing platform code; perform operations in threads to increase your apps' processing power; and give you access to native platform libraries. Native extensions are packaged and distributed like all other ActionScript libraries: you can distribute your own libraries, as well as use native extensions published by other developers, allowing you to plug in functionality to your own applications.

Adobe also provides several fully documented native extension examples that will help developers get started with the above features.

Getting started

This tutorial will get you started creating a native extension of your own. It'll walk you through the steps requried to create native Java code for Android, ActionScript 3 code and a native extension file; you'll also learn how to create a Flex mobile application that works with your native extension, and finally you'll test it on your device. Even though this is a "Hello, World!" tutorial, we'll eschew printing the usual message via native code, and instead opt to control the vibration motor of an Android smartphone. If you're feeling adventerous (or wish to target a different platform) you may choose to adapt the native code section of this guide to to fit a non-Android platform.

Here are the high-level steps that you'll undertake in the following pages:

Creating native code

1. Set up an Android development environment in Flash Builder 4.6.
2. Connect and test your Android device                                              .
3. Create a native Android project.
4. Create Java code to create an Extension Context.
5. Create Java code to connect back to ActionScript 3.

1.  在FB4.6中建立Android开发环境
2.  连接Android设备
3.  创建native Android工程
4.  用Java创建Extension Context
5.  用Java关联AS3
6.  编译

Creating ActionScript 3 code

1. Set up an ActionScript 3 library project in Flash Builder 4.6.
2. Code the bridge to your Java code.
3. Set up a Flex mobile project for your Android phone.

1.在FB4.6中创建AS3的library工程
2.桥接Java代码
3.创建Flex Mobile工程

Creating the .ANE file, tying native and ActionScript 3 together

1. Handle certificates.
3. Modifying your Flex app to use the new .ANE file.

创建ANE，把native和AS3整合在一起
1.证书问题
3.在Flex程序中使用ANE

1. Prove that your native extension works!

Creating native code

At the heart of a native extension is the native code, which will act as the first layer between your application and the feature you want to control. In this example, the native code will control the vibration motor and send and receive information with ActionScript 3. You'll write the functions to control the vibration motor yourself, and you'll use the Java APIs provided by Adobe AIR to send data back and forth to ActionScript 3.

Before you can start coding and using libraries, however, you have to set up your build environment.

#### Setting up an Android development environment using Flash Builder 4.6

Since you'll be writing native Android code, you need a development environment that can operate with the Android SDK. If you haven't already, install and configure the Android SDK by following the links included at the beginning of this guide. Once this is complete, you'll modify Flash Builder to create and compile Android projects:

1. Open Flash Builder and go to Help > Install New Software (Flash Builder > Window > Install New Software on OS X). (If necessary, close and relaunch Flash Builder with administrative privileges.)
打开FB，Help>Install New Software
3. Flash Builder will download a list of available software. Install all developer tools, including Android DDMS, Android Development Tools, Android History Viewer, and Android Traceview. Click Next
twice, review the EULAs and decide if you agree, and wait for the packages to install. Some of the Android packages contain unsigned content, but you should continue the installation regardless.
FB将下载一个可用软件的列表，包括Android DDMS，Android Development Tools，Android History Viewer和Android Traceview。点击Next，处理许可，等待package下载。有些Android的packages含有usigned的content，但是你应该无视它们，继续安装。
4. Restart Flash Builder when prompted.
重启动FB。
5. You need to point Flash Builder to the location of your Android SDK. Go to Window > Preferences (Flash Builder > Preferences on OS X) and click Android. Click Browse and select the root location of your Android SDK (for example, C:\Users\dan\Programs\android-sdk). If you're missing any components of the Android SDK, you'll receive an instruction to run the Android SDK manager and install them. Select the most recent version of the SDK and click OK.
在FB中指定Android SDK的位置。Windows > Preferences，点击Android。设定Android SDK的路径
6. Click Window > Android SDK and AVD Manager.
打开SDK and AVD Manager
7. Go to Available Packages and choose the latest Google Inc. packages, to make sure that you have the latest Android SDK and API packages. You may also want to install the USB Driver, depending on your device.
下载最新的SDK和API，视需要下载USB Driver。
8. Close this window. You should now be able to click File > New Project and see and entry for Android Project. If so, Flash Builder is properly configured.
关闭这个对话框，如果能在File > New 后，从Wizard看到Android工程，则说明配置成功

#### Connecting and testing your Android device

Though it's tempting to jump into the specifics of writing code, it'll save hassle later if you now verify that your phone can connect, and is recognized by the Android SDK.

连接Android设备
2. On the device, verify that development mode is enabled by going to Settings > Applications > Development, and making sure there's a check in the "USB Debugging" check box.
3. If necessary, click through the dialogs on your computer that allow you to install the drivers. On Windows, you may want to select the driver located in the android_sdk\usb_driver folder.
4. Open a command prompt or terminal, and run "adb devices".
5. You should see your device ID listed. If not, follow guides online for getting adb working with your phone. If that command produces "command not found" or a similar error, add the location of the android_sdk\tools folder to your system PATH variable, and try again.

#### Creating a new Android project

We now have to create a new Android project in Flash Builder, and instruct the linker to look for the Java API JAR file provided with the AIR SDK.

1. In Flash Builder, go to File > New > Project.
2. Select Android Project and click Next.
3. Name the project HelloANENative.
4. Note the project location (you can also change the location if you want).
5. Be sure to select a recent Android SDK for your build target. If you don't see your desired target, return to the previous steps to install the Android SDK inside of Eclipse, or update the SDK to include the APIs and target you want. The rest of the tutorial will be completed with the assumption that you selected Android 2.3.3 or later—but this should not affect any of the following instructions.
本例要求Android在2.3.3之上
6. Enter the package name, com.<yourdomain>.example.android.helloANE. For example, com.yourDomain.example.android.helloANE.
7. Click Finish.
8. Flash Builder will have created a HelloANENativeActivity.java file for you. Open it using the Package Explorer.
FB会创建一个java文件。
9. Right-click the HelloANENative project in the package explorer, and click Properties.
10. Click Java Build Path, and then Libraries.
11. You'll now have to add the Java APIs that allow you to interface with ActionScript 3. Click Add External JARs.
需要添加Java API，允许你与AS3交互（能否理解为：为Android开发增加一个操作AS3的库）
12. Browse to and select the FlashRuntimeExtensions.jar file (the path to the file is similar to the following:C:\...\Adobe Flash Builder 4.5\sdks\4.5.2\lib\android\
13. Click OK to dismiss the project propeties dialog box.

You have one more project configuration task: set the application to have permission to use the vibration controls of the device.

1. Open the AndroidManifest.xml file. You should see the Android Manifest Permissions screen.
打开AndroidManifest.xml。
2. Click Add and select UAndroidManifest.xmlses Permission, and then click OK.

3. Under Attributes for Uses Permission select android.permission.VIBRATE.
4. Save the HelloANENative Manifest file.

You've performed this step so that your native code will have the requisite permission to run should you decide to create native test cases. Although this tutorial doesn't cover it, testing your native code before moving on to ActionScript 3 can be helpful—especially for more advanced native extensions.

#### What is an extension context?

Now that your Android project is properly configured, you have to start adding in the structures that establish a bridge between ActionScript and your native Java code. The first of these structures is an extension context. An extension context is responsible for containing up to three native extension-related items (see also Oliver Goldman's article, Extending Adobe AIR):

1. A mapping of native functions to names that ActionScript can reference. This allows ActionScript code to call specific, native functions, and is the heart of a native extension.
native函数的map。AS将通过它调用特定的native function
2. A reference to an ActionScript object, which is shared between native code and your AIR app.
AS对象的引用，将在native code和AIR程序中共享。
3. A reference to a native code structure, which can only be accessed from native code.
native的代码结构，只在native code中引用

Note that your native extension may have multiple Extension Contexts, and you should separate them based on function. In this example, you only need one, which will provide a map to access the Android vibration feature.

#### Creating a vibration Extension Context

Next you'll create a new VibrationExtensionContext class.

1. In the Package Explorer, right-click the src.com.yourDomain.example.android.helloANE package and select New > Class.
选择刚才创建的包，创建一个新的类，New > Class
2. Set the package to com.yourDomain.example.android.helloANE.extensions.
设置所属于哪个package
3. Set the name to VibrationExtensionContext.
设置类名
4. Set the superclass to com.adobe.fre.FREContext. You can use the Browse button to select this class. This is the AIR Java API that Adobe provides to make the native extension bridge work.
设置superclass
5. Click Finish to create the new class.

You'll see that two functions have been created for you: public void dispose() and public Map<String, FREFunction> getFunctions() . As you may have guessed, getFunctions() must return a key-value pair mapping between Strings (which are referenced in your ActionScript 3 code), and any FREFunction classes, which you'll define next. The APIs provided by Adobe give you classes and functions that begin with the abbreviation FRE, which stands for Flash Runtime Extension.

#### Creating a mapping of functions

The first step to defining the functions in your native extension is to create a new Map to return. In the getFunctions() class, add:

@Override
public Map<String,FREFunction> getFunctions()
{
Map<String, FREFunction> functionMap = new HashMap<String, FREFunction>();

return functionMap;
}

This creates an empty HashMap, but it clearly isn't very useful if it's empty. You're going to map three key value pairs, each of which will define a class that implements the FREFunction interface:

• isSupported to a VibrationSupportedFunction. This will run some logic and pass an FREObject to ActionScript 3 containing either true or false , depending on whether the platform supports vibration.
isSupported对应VibrationSupported函数。

Note: It's best practice to always allow the ActionScript 3 code to do a compatibility check before using other features of your native extension.
最好的办法是始终允许AS3代码在使用native extensiong前进行兼容性检查

• vibrateMe to a VibrationVibrateFunction. This FREFunction accepts a parameter from ActionScript 3 controlling the duration of the vibration, and then performs the actual vibration on your device.
vibrateMe对应VibrationVibrate函数。这个函数接收一个来自AS3的参数，控制vibration的duration，接下来在你的设备上执行实际的vibration。
• initMe to a VibrationInitFunction. This function allows the native code to perform and initialization tasks before the other functions are ready to be used. In this example, you'll create a reference to Android's VIBRATOR_SERVICE , which will be used in the VibrationVibrateFunction (AKA "vibrateMe" in ActionScript 3).
initMe对应VibrationInitFunction。这个函数是在其他函数被使用前进行初始化。在本例中，你将要创建一个针对Android VIBRATOR_SERVICE的引用。
• Inside of the getFunctions() Class, call the put() function on your functionMap object. The first parameter will be a String representing the above function names, and the second parameter a new instance of the (not yet created) function:
在类getFunctions中，在functionMap上调用put函数。第一个参数是函数名称，第二个参数是函数的实例
functionMap.put("initMe", new VibrationInitFunction());
functionMap.put("isSupported", new VibrationSupportedFunction());
functionMap.put("vibrateMe", new VibrationVibrateFunction());

#### The first of three functions: VibrationInitFunction

You've defined three functions. Next, you'll write them as classes that implement the FREFunction interface. You'll start with the VibrationInitFunction, which, when called, will set a class in your VibrationExtensionContext that will later be used to vibrate the device.

1. Right-click a package in the Package Explorer and choose New > Class.
添加一个新类
2. Make the package com.yourDomain.example.android.helloANE.extensions and set the name to VibrationInitFunction.
确认所在的包和类名
3. Leave the Superclass as just a java.lang.Object, and add a new entry to the Interfaces box: com.adobe.fre.FREFunction.
确定Superclass，添加新的接口
4. Click Finish.

As you'll see, a function inside of your VibrationInitFunction has already been defined for you: call(), which takes two arguments: an FREContext, and an FREObject[] array. By default, these are defined as arg0 and arg1, but you can give them more descriptive names. Change the call() function definition to look like this:

public FREObject call(FREContext context, FREObject[] passedArgs)

When this function is called, the first argument will be a reference to your VibrationExtensionContext, and the second argument will be an array of all arguments (if any) passed down by the ActionScript 3 code. This will be important for your VibrationVibrateFunction, which will set the duration based on the first argument in that array.

For now, your init function is going to use the passed-in FREContext object to get the VibrationExtensionContext, and then the Android Activity it belongs to. Using this activity reference, it will then be able to retrieve the global Android system service known as the Context.VIBRATOR_SERVICE, which will allow you to control the vibrator motor. You'll store this system service in a new variable contained in your VibrationExtensionContext, which you'll create shortly:

1.In the call() function of VibrationInitFunction , add the following line to grab the VibrationExtensionContext from the FREContext that was passed in:
VibrationExtensionContext vbc = (VibrationExtensionContext)context;

2.You can now grab the Activity using the VibrationExtensionContext getActivity() function. The inclusion of this function in the FREContext class is designed to support common tasks, such as your need to grab the context's Activity, and thus have a path to the SystemService that we require.
Activity a = vbc.getActivity();

3.You can now call a.getSystemService(), and pass in a reference to the global Context.VIBRATOR_SERVICE . This will return an object of type Vibrator. You need a place to store this that is available to the entire Extension Context, so put it in a new variable, vb, placed inside the VibrationExtensionContext:
vbc.vb = (Vibrator)a.getSystemService(Context.VIBRATOR_SERVICE);

4.You should now open the VibrationExtensionContext class, and add a public variable called vb to the class:
public Vibrator vb = null;

Thus, you've created a reference to a native code structure, the vb Vibrator class, which is accessible to any class that can reference your VibrationExtensionContext.

Your completed VibrationInitFunction should look like this:

public class VibrationInitFunction implements FREFunction
{
@Override
public FREObject call(FREContext context, FREObject[] passedArgs)
{
VibrationExtensionContext vbc = (VibrationExtensionContext)context;
Activity a = vbc.getActivity();
vbc.vb = (Vibrator)a.getSystemService(Context.VIBRATOR_SERVICE);
return null;
}
}

You've learned how to: create a class that implements FREFunction; understand the arguments passed in from ActionSscript 3; access your Extension Context via the FREContext argument; and you've seen a common initialization task for extensions.

1、创建实现自FREFunction的类
2、理解从AS3传入的参数
3、通过FREContext参数访问Extension Context
4、一般性的初始化

Next you have to implement the other two FREFunctions that you defined in the Map<String, FREFunction> getFunctions() function.

#### The second of three functions: VibrationSupportedFunction

The second function that you defined earlier is the VibrationSupportedFunction. As you indicated in the HashMap returned by getFunctions(), this function can be called using the ActionScript 3 String isSupported. The creation of this function is quite similar to the VibrationInitFunction—however, it will show you how to return a Boolean inside of a FREObject.

1. Right-click a package in the package explorer and click New > Class.
2. Select com.yourDomain.example.android.helloANE.extensions as the package, and name this classVibrationSupportedFunction, as expected by the value provided in the earlier HashMap.
3. Choose FREFunction as an Interface that this class will implement.
4. Click Finish to create the class.
以上四步创建一个新类，方法同前一个类
5. Change the arguments in this class from arg0 and arg1 to context and passedArgs, respectively.
参数改名，更易读
6.  You'll want to return a FREObject as a result in the call() function; create and return that now. You'll also want a reference to your VibrationExtensionContext, so create that by casting the context parameter:
FREObject result = null;
VibrationExtensionContext vbc = (VibrationExtensionContext)context;
// ...
return result;

7. The logic of this function will be as follows:

• VibrationInitFunction has already been called, and thus vbc.vc should be set.
• Is vbc.vc non-null? If so, result should be true.
• If vbc.vc is null, we can reasonably conclude that initialization failed, and that this platform doesn't support Vibration.result should be set to false.

Create the following if statement:
if (vbc.vb == null)
{
result = FREObject.newObject(false);
}
else
{
result = FREObject.newObject(true);
}

8. There is one additional task: calling newObject() on FREObject can result in an FREWrongThreadException exception being thrown. You'll surround your if statement in a try catch block, to handle this eventuality.
这里要额外做一件事：调用newObject可能会产生异常，你需要增加异常处理。

Your completed call() function should now look like this:

@Override
public FREObject call(FREContext context, FREObject[] passedArgs)
{
FREObject result = null;
VibrationExtensionContext vbc = (VibrationExtensionContext)context;

try
{
if (vbc.vb == null)
{
// Not supported
result = FREObject.newObject(false);
}
else
{
// Supported
result = FREObject.newObject(true);
}
}
{
fwte.printStackTrace();
}

return result;
}

You now have the second of your three native extension functions: VibrationSupportedFunction. When called by the ActionScript 3 String isSupported , this function will check to see if the variable vb in the VibrationExtensionContext "context" is non-null. It'll return a FREObject that's either true or false based on this condition, and will catch a FREWrongThreadException that's potentially thrown by the static newObject()function of FREObject.

#### The Third of three functions: VibrationVibrateFunction

The last native extension function you have to implement performs the core duty of your native extension: it allows the AIR application to vibrate the device's motor for a specified duration.

1. In the Package Explorer, right-click a package and choose New > Class.
2. Choose com.yourDomain.example.android.helloANE.extensions as the package, and name the classVibrationVibrateFunction.
3. Make the class implement com.adobe.fre.FREFunction.
4. Click Finish to create the class.
5. In the function definition, rename arg0 to context and arg1 to passedArgs.
以上几步创建类，修改参数变量名
6. Create a null FREObject called result.
创建返回值
7.  Cast the context variable to a VibrationExtensionContext variable called vbc. You'll use this to access vbc.vb, the Vibrator object.

We're now ready to access the first passed argument as a FREObject, and try to set it as an integer. If the data is malformed, an exception may be thrown, which you'll catch. Your call() function should currently look like this:

@Override
public FREObject call(FREContext context, FREObject[] passedArgs)
{
FREObject result = null;

VibrationExtensionContext vbc = (VibrationExtensionContext)context;

try
{
// Vibrate the device
}
catch (Exception e)
{
e.printStackTrace();
}

return result;
}
8.  Inside of the try { // ... } block, we're going to try and grab the first element in the passedArgs array as a FREObject:
FREObject fro = passedArgs[0];
参数中获得第一个元素

9. We can now create an int by calling getAsInt(); on this FREObject:

int duration = fro.getAsInt();
根据刚刚获得的fro获得int
10. Finally, call the Android native vibrate function on our vb Vibrator variable, passing in the duration:
vbc.vb.vibrate(duration);

最终，调Android的native vibrate函数

You've now successfully created three native functions, mapped them to strings in the HashMap provided bygetFunctions(), and created the native logic necessary to perform all the actions that are required of your native extension. This completes the creation of the VibrationExtensionContext, which is the only extension context that your native extension requires.

#### Creating the main extension class

You've created the one and only extension context that your native extension requires, but you still haven't created the main class of our extension. Fortunately, adding this class is simple; all we have to do is create a class called VibrationExtension which implements the FREExtension interface.

The FREExtesion interface defines the initializedispose, and createContext functions, which allow hooks into the lifecycle of a native extension. Despite providing us with three functions, we only have to customize one: the createContext function. This function has to return a FREContext. Fortunately, you've already created your own VibrationExtensionContext, and you can simply return an instance of this class.

1. Right-click a package, and select New > Class.
2. Choose com.yourDomain.example.android.helloANE.extensions as the package name.
3. Name the class VibrationExtension.
4. Make the class implement com.adobe.fre.FREExtension by using the Add button next to the interfaces box.
5. Click Finish to create the class.
创建一个新类，实现FREExtension接口
6.  By default, the string argument defined in the createContext() function will read arg0 . This argument is actually an ID defining the type of context to create (which is only useful if you have multiple context types). Change arg0 to contextType.

7.  To complete the createContext() function, we only need to return a new instance of our VibrationExtensionContext. Replace the return null; code with the following:

return new VibrationExtensionContext();
This will cause the initialization and creation of your Extension Context, and allow you to use the native code you put in your native extension.

#### Exporting your native code as a JAR file

In the following sections of this tutorial, we'll see how to code the ActionScript 3 side of our native extension, as well as package and test the completed native extension file and sample application. These steps will involve referencing your native code as a JAR file. Creating a JAR file in Flash Builder is simple:

1. With your HelloANENative project selected in the Package Explorer, go to File > Export.
2. Select Java > JAR file and click Next.
3. Select HelloANENative as the resource to export.
4. Make sure "Export generated class files and resources" is selected.
5. Select a destination for the JAR file, name it HelloANENative.JAR and click Finish. You'll use this JAR file both when you create the extension.xml file in your Flex library project, and when you run the packaging command to create your native extension file.

### Creating ActionScript 3 Code

You've done the majority of the coding necessary in creating a native extension, having created Java code that you can extend with additional functions, logic, and (if necessary) even additional extension contexts to expand the scope of your native extension.

In contrast, creating the ActionScript 3 code necessary to complete this platform bridge is simple. Your tasks include:

• Creating and configuring a Flex Library project.
创建配置Flex库工程
• Creating an extension.xml file to describe your extension.
创建描述extension的extension.xml
Your ActionScript 3 library code will consist of one class, which will import the flash.external.ExtensionContext API, and provide the following functions:

• A constructor, which will create a new Extension Context of the proper ID, and which will call your initMe native function.
构造函数，它将会创建一个新的Extension Context。它会调用你的InitMe native函数。
• A function called isSupported, which will call our isSupported native function, and which will return trueor false depending on the response from our native code.
函数isSupported，调用isSupported native函数，该函数会根据native code的处理返回true或flase。
• A function called vibrate, which will accept a Number duration, and call your native vibrateMe function with this number as a parameter.
函数vibrate，接收一个数值duration。它会以这个值为参数调用native的vibrateMe函数。
• After completing this code, your ActionScript 3 library function will be complete, and you can move on to packaging and using your native extension. Note that the library function defines the ActionScript 3 code necessary to use your native extension, but it isn't a sample application. In order to use your native extension, you'll have to reference this library application from a Flex mobile application, which you'll create in a later section of this guide.
做完这些之后，AS3库的工作告一段落，你可以使用native extension来打包。需要注意的是，虽然这些库函数可以用你的native extension，但它不是一个范例程序。为了使用native extension，你需要创建一个Flex mobile 程序。
Creating a Flex library project
Your ActionScript 3 code will exist inside of a Flex Library project:
• In Flash Builder, open the Flash perspective by selecting it in the top right of the screen.
• Click File > New > Flex Library Project.
• Name the project HelloANELibrary.
• Make sure the Generic library radio button is selected.
• Make sure that "Include Adobe AIR libraries" is checked. The native extension libraries your project will depend on are included with the AIR APIs.
• Click Finish to create the project.
创建一个新的Flex Library工程。
• Open the HelloANELibrary project in your Package Explorer, right-click the src folder, and select New > ActionScript Class.
• Name the package com.<yourDomain>.nativeExtensions.Vibrate. For example,
• Name the class Vibrate.
• Set the superclass to flash.events.EventDispatcher. This will allow this class to dispatch events, which will be useful when you integrate native extensions into real applications.
• Click Finish to create the Vibrate class.
在该库中创建一个类Vibrate。
Coding the ActionScript 3 bridge to your native code
You now have to create the connection to our Extension Context, which will allow you to access the initMe, isSupported, and vibrateMe functions you created in Java.

1.In the Vibrate class, add a private, static reference to an Extension Context:

private static var extContext:ExtensionContext = null;

2.In the constructor, you're going to verify whether this extContext variable has been initialized. If not, you'll call the static function ExtensionContext.createExtensionContext(), and pass in two identifiers. The first is an ID you'll set in an extension.xml file shortly. The second is a parameter that's passed to the createContext() function of VibrationExtension. You'll recall that it allows you to create different Extension Contexts; since you only have one, you ignored this parameter in your native code. If you have multiple extension contexts, you should make your native code parse the value you pass in with an if or switch statement, and create the appropriate values based on the available shared String values. Write the following:

if ( !extContext )
{
extContext = ExtensionContext.createExtensionContext("com.yourDomain.Vibrate","vibrate");
extContext.call("initMe");
}
3.Note that you called initMe via extContext.call(), passing in no additional parameters. This will map up with the VibrationInitFunction that you coded in Java, and will initialize the internal data structures necessary for you to vibrate the device.

The Extension Context will now be created and initialized as soon as the Vibrate() constructor is called by any application that uses your new ActionScript 3 library. You still have two functions to implement, however. First create the isSupported() function, which will connect to the native isSupported function, and inspect the Boolean value that is returned by your application logic.

1.Create a static getter called isSupported, which returns a Boolean:

public static function get isSupported():Boolean
{
var supported:Boolean = false;

// ...

return false;
}
2.Between the two statements, add a call to extContext.call(), passing in isSupported as a String parameter, and which sets your supported variable to the returned Boolean value:

supported = extContext.call("isSupported") as Boolean;
Repeat this process to create the vibrateMe function, which takes in a single Number as the duration. Creation of this function is straightforward:

public function vibrate(duration:Number):void
{
extContext.call("vibrateMe",duration);
}
Note that Flash Builder will automatically compile your library into a SWC file, located in the bin folder of the project. The SWC file is an archive that contains library.swf. You have to manually reference both the SWC and SWF whenever you package an ANE file with ADT. Thus, you should now open the SWC file in an archive management tool, extract library.swf, and place it in the bin/ directory of HelloANELibrary:
1. Navigate to HelloANELibrary/bin/.
2. Unzip the HelloANELibrary.swc file, or open it in an archive management tool (e.g., 7-Zip).
3. You'll see a catalog.xml and a library.swf file inside of the SWC archive.
The library.swf file needs to be placed inside of the native code directory for every platform you target. For example, you'd place this file inside iOS/, android/, x86/, etc., depending on your project's targets. (For more advanced ANEs, you can specify different library.swf files, if you require that your AS3 library is different for different platforms. This goes against the best practice of defining a common interface, however, and it's recommended that you stick with a single version of library.swf.)
从SWC文件中会看到catalog.xml和library.swf。library.swf需要被放置在每个目标平台的native code所在目录。比如，你需要把这个文件放入iOS、android、x86等。（可能有不同的library.swf的情况。。。）
4. When complete, your HelloANELibrary folder should contain both HelloANELibrary.swc, and HelloANENative should contain library.swf.
操作完成时，文件夹HelloANELibrary应该包含HelloANELibrary.swc，HelloANENative应该包含library.swf。（此话可能翻译不准确）
By extracting library.swf, you now have all the files you need to create a native extension. Note that you have to repeat steps 1 through 4 whenever you change your library code, otherwise library.swf will be out of date.

At this point, you've written all of the library code you need to use your native extension.

Describing your native extension in an extension.xml file

You've created the requisite code, but you've yet to link everything together into an ANE file. First, create an extension.xml file inside of your Flex library project. For each native target, this file points to the native code (your JAR file) and describes the package location of the initializer function (and, optionally, a finalizer function, which you don't need in this example). You'll hand this file to the packager when you create your ANE file (which you'll then use in a sample application).

Create the extension.xml file inside of your Flex library project:

1. Right-click the src folder in your HelloANELibrary project. Click New > File.
2. Name the file extension.xml.
3. Re-open this file by right-clicking it and selecting Text Editor, rather than the default XML editor.
建议用文本编辑器来打开
4. The following XML describes the AIR namespace to use (2.5), the ID of the extension, and the single platform we wish to target (note that "iPhone-ARM" is another common target platform):
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
<id>com.yourDomain.Vibrate</id>
<versionNumber>1</versionNumber>

<platforms>
<platform name="Android-ARM">

<!-- ... -->

</platform>
</platforms>
</extension>
Inside of the <platform> tags, you'll now set the location of the JAR file in a <nativeLibrary> tag, and set the location of the initializer to the location we set in the native code (recall that you created the initialize() function in your VibrationExtension class):

<applicationDeployment>
<nativeLibrary>HelloANENative.jar</nativeLibrary>
<initializer>com.yourDomain.example.android.helloANE.extensions.VibrationExtension </initializer>
</applicationDeployment> 
You've now successfully created your extension.xml file, and have all the components you need to create your ANE file.

Packaging a native extension

Currently, packaging a native extension requires using the command line tool adt, and passing it a number of parameters. I recommend creating a batch script in Windows (.bat file), or a bash script in OS X (typically a .sh file); the script you'll create will allow you to set your own variables in the top part of the script, allowing it to be easily adapted to your other native extension projects.

There are a number of pieces of information you need to plug into the script. I'll list the information, and show you the values I use on my own system:

• Programming root directory: C:\Users\dan\Programs

• ActionScript 3 library directory: %root_directory%\HelloANELibrary
AS3库的目录
• Android native directory: %root_directory%\HelloANENative
Android native的目录
• Signing options: -storetype pkcs12 -keystore "c:\Users\dan\Programs\ cert.p12"
签名选项
• Destination ANE file: HelloANE.ane
目标ANE文件名
• Location of extension.xml: %library_directory%\src\extension.xml
extension.xml的位置
• Location of compiled ActionScript 3 library SWC: %library_directory%\bin\HelloANELibrary.swc
编译好的SWC的位置
You should create a similar list of values for your own system. You can then plug them in by referencing the variables with the following ADT command:

"%adt_directory%"\adt -package %signing_options% -target ane "%dest_ANE%" "%extension_XML%" -swc "%library_SWC%" -platform Android-ARM bin/library.swf -C "%native_directory%" .


This command may look complicated, but it's simply running adt and passing in signing options, specifying ane as the target, providing the extension.xml file, specifying the HelloANELibrary.swc file, targeting Android-ARM as the platform, and telling ADT where to look for the native library files.

A compile_ane.bat file on Windows may look like this:
Windows平台上的批处理可能如下
set adt_directory=C:\Program Files\Adobe Flash Builder 4.5\sdks\4.5.2\bin
set root_directory=C:\Users\dan\Programs
set library_directory=%root_directory%\HelloANELibrary
set native_directory=%root_directory%\HelloANENative
set signing_options=-storetype pkcs12 -keystore "c:\Users\dan\Programs\cert.p12"
set dest_ANE=HelloANE.ane
set extension_XML=%library_directory%\src\extension.xml
set library_SWC=%library_directory%\bin\HelloANELibrary.swc
"%adt_directory%"/adt -package %signing_options% -target ane "%dest_ANE%" "%extension_XML%" -swc "%library_SWC%" -platform Android-ARM -C "%native_directory%" .
On Mac OS X, the script might look like this:
#!/bin/bash

root_directory=/Users/dan/Programs
library_directory=${root_directory}/HelloANELibrary native_directory=${root_directory}/HelloANENative
signing_options="-storetype pkcs12 -keystore /Users/dan/Programs/cert.p12"
dest_ANE=HelloANE.ane
extension_XML=${library_directory}/src/extension.xml library_SWC=${library_directory}/bin/HelloANELibrary.swc

"${adt_directory}"/adt -package${signing_options} -target ane "${dest_ANE}" "${extension_XML}" -swc "${library_SWC}" -platform Android-ARM -C "${native_directory}" .

Note that I use a p12 file as my signing certificate. You can substitute the file you normally use for signing AIR files. If you need to create one, the easiest way to do so is to open a Flex or AIR project in Flash Builder, and go to Project > Export Release Build. During the second step you'll have the option to create a certificate using the GUI.

Run your script from the command line, enter your cert's password, and the %dest_ANE% file should be created, and ready to use in a sample application!

Using the native extension in a Flex sample application

You're now going to create a Flex mobile application that uses your native extension! The process of setting up a project and deploying it to Android is simple:
1. In Flash Builder 4.5.2, click File > New > Flex Mobile Project.
创建一个Flex Mobile工程
2. Name the project HelloANESample.
3. Make sure you're using the 4.5.2 SDK or newer, and click Next.
确保使用4.5.2 SDK或者更新版本
4. Make sure that only Google Android is selected as a target platform.
5. Choose a View-Based application and click Next.
6. Click Next, as you don't need any server settings.
7. Click the NativeExtensions tab, which allows you to target any ANE files that your application needs.
迁移至Native Extensions页
8. Click Add and browse to the ANE file you packaged in the previous step. It should be in the HelloANELibrary folder, named HelloANE.ane.
加入前面所打包的ANE文件
9. Click OK. You should see a green check mark next to the ANE file's entry. If you expand this entry, you should see the following warning: "Launching on win32(Windows-x86) is not supported" (or a similar message for OS X). This is because we didn't target our desktop environment when we coded the native portion of our native extension, nor did we configure it when we wrote the extension.xml or ran ADT.
10. Click Finish.
11. We'll now double check that the native extension is included in packaging, and not just in the build paths. Although it should be correctly configured, you may have to perform these steps should you modify the native extension. Right-click your project in the Package Explorer and select Properties.

12. Expand Flex Build Packaging and select Google Android.

13. Click the Native Extensions tab.
14. You should see a green check mark next to your native extension, as well as a checkmark in the Package column for that native extension. If not, select the check box.
15. Click OK to close the project properties.
Configuring permissions
To finish setting up your project, you need to specify that your application requires the use of the Android vibration controls. Pay particular attention to this aspect when you're taking advantage of additional features of a device—it's easy to overlook that some features require additional permissions. The AIR application descriptor won't make these entries available in the commented sections either, as you're going above and beyond the features of the runtime. Should you forget to specify the proper permissions, the native code will fail to work, and will likely throw a permissions-related exception. (On Android, this output is easily visible by using logcat in the adb shell.)

To add permission to the AIR application descriptor:
1. Right-click the HelloANESample-app.xml application descriptor, and choose to open it with the text editor.
2. Scroll down to this section:
<android>
<manifest android:installLocation="auto">
3.   Add permission to use the Vibration controls:
<uses-permission android:name="android.permission.VIBRATE"/>

Now that the project is configured, you can add a vibrate button to the home view:
1. Between the s:View tags (in the main body of the class), add a new s:Button . Give it a label of Vibrate using ANE, and create a new click handler. Flash Builder should automatically create an fx:Script tag and click handler ActionScript 3 function for you.
2. Create a new Vibrate class inside of your click handler, which will expose your native extension via an ActionScript 3 object:
var v:Vibrate = new Vibrate();
3.  Trace the value of v.isSupported , and then call your main vibrate function, passing in a hard-coded value of 100 for the number of milliseconds the motor should run:
trace("Is this ANE supported on this platform? " + Vibrate.isSupported);
v.vibrate(100);
4. Click the debug button in the main toolbar.
5. Select Google Android as the target platform, and choose to launch on the device, with debugging via USB.
6. Click Debug.

The Flex application should now launch on the device, and provide a button labelled Vibrate using ANE. Tapping this button should produce a 100ms long vibration from the motor in your Android device! You'll also notice the following output in the Console view in Flash Builder:
[SWF] com.yourDomain.Vibrate - 2,916 bytes after decompression
[SWF] HelloANESample.swf - 2,702,220 bytes after decompression
Is this ANE supported on this platform? True
You can add a TextInput or form of numeric input if you wish to control the duration of the vibration. Simply replace the 100 argument that we hard-coded with a locally scoped variable, and set this variable using a control. At this point, coding the ActionScript 3 side of your application is no different than other Flex application development.

Where to go from here

In this guide you learned that AIR native extensions allow you to expand the capabilties of Adobe AIR, giving your applications access to device and hardware capabilities that would otherwise be inaccessible via the runtime APIs alone. You learned how to create native extensions for Android, and can use these skills to target other platforms. In this example, you focused on the simple task of making the vibration motor of an Android device activate for a specified duration; this illustrated how to create and initialize an native extension, as well as pass data back and forth between your native code and your AIR application.

To achieve this, you:
1. Coded in native Java to interface with the native extension APIs that Adobe AIR provides (FREObject, FREFunction, etc.).
2. Coded a Flex library comprised of ActionScript 3 APIs. These hooked into your native APIs.
3. Wrote an extension.xml describing our extension.
4. Scripted a batch/bash file to package our native extension with the command line utility ADT.
5. Created a mobile Flex project that uses our native extension.
• Although you focused on Android, native extensions work on iOS, Mac OS X, Windows, and Adobe AIR for TV. You can create a single native extension that targets multiple platforms, and your application logic can determine (at runtime or compile-time) if specific features are supported on a platform-by-platform basis.
• You now have the knowledge and skills necessary to create your own native extensions. Your applications can access additional hardware features, take advantage of native-optimized code or third party libraries, and even spawn multiple threads to handle time-consuming computations without blocking your AIR app.
Including Assets in native extensions
Our example didn't require any assets beyond compiled code—however, you may wish for your native extension to access images, files, database or configuration stores, etc. This is quite possible, and requires a few considerations on mobile:
• On Android, include your assets "res" folder of your Android project path. These files will be merged into the resources directory of your main application, so you need to choose unique names that won't conflict with your other assets. You can access them using FREContext.getResourceId(), by passing in the desired resource ID (see also Oliver Goldman's article, Extending Adobe AIR).
• On iOS, resources are accessed via the NSBundle APIs; note that the namespaces are flattened when the project is compiled, and the names you choose for your resources (even if used only in native code) should be guaranteed not to conflict with other resources in your project. For example, don't use two resources anywhere in your project that are both named Localizable.strings (see also Oliver Goldman's article, Extending Adobe AIR).
Dispatching status events
You'll likely find that your native extension must perform asynchronous tasks in native code, and you'll require a way to pass notifications to your AIR application when the task completes. This is accomodated by the function dispatchStatusEventAsync(String code, String level); in the FREContext Class. As an example, the following Java code instructs a hypothetical native extension library that there has been a Status Event with a code of "DATA_CHANGED":
context.dispatchStatusEventAsync("DATA_CHANGED", stringData);
This Status Event will be dispatched asynchronously, and (provided your AIR application isn't busy), will immediately be available in the corresponding native extension ActionScript 3 event listener. Since the context is capable of dispatching these events, you'll have to instruct your native extension library to listen for them:
context.addEventListener(StatusEvent.STATUS, onStatus);
...
private function onStatus(e:StatusEvent):void
{
if (e.code == "DATA_CHANGED")
{
var stringData:String = e.level;
// ...
}
}
Status Events provide a convenient way of updating your native extension library (and thus your resulting AIR and Flex applications) on the status of a native code task.

Learning More
You can continue learning about native extensions by referring to the "additional resources" section at the beginning of this guide. These resources include a link to the native extensions that Adobe has already created and distributed, allowing you to expand AIR's capabilities simply by dropping native extension files into your Flex and ActionScript 3 applications.

Also be sure to check out the in the Adobe AIR Developer Center.

#### Using native extensions for Adobe AIR

2012-08-10 14:39:57

#### Android studio 3.0 引起的 outputFile sync failed：not vaild

2017-05-28 18:06:15

#### 揭秘Android Studio项目目录结构

2014-08-14 11:13:32

#### xxx cannot be resolved or is not a field

2014-06-27 15:34:10

#### 解决android项目65k方法数的限制，让你的应用不在爆棚。

2016-04-02 18:00:30

2010-04-12 15:57:00

2012-10-28 22:38:42

#### Developing AIR Applications with Adobe Flex.pdf

2008年12月27日 2.03MB 下载

#### AIR NativeProcess 调用bat

2014-08-19 13:08:13