Adobe AIR Native Extension,Adobe AIR的本地扩展,简称ANE。本来已经是过时的技术了,但是由于项目需求,需要使用 flash ane,在一番挣扎之后总算是成功编写了 ane 并且实现了需要的功能,这里记录下来,以免这种古老的技术流失。
由于工作保密性,这里只以一个简单例子来呈现flash ane的编写和使用。
首先是开发工具,我们需要用到的工具是 Flash Builder 和 Eclipse 。
这里推荐使用Eclipse来创建Android工程,因为使用Android Studio创建工程,最后在导出jar包等地方会有问题。至于Eclipse怎么配置Android开发环境,请自行百度,教程很多。不过在配置Android开发环境时,会因为网上Android SDK的版本不够老(因为新的SDK已经不支持Eclipse了,google很任性~),导致环境配置失败。如需老的SDK,可以在下方留言。
我们先在Eclipse中创建一个名为 HelloAne 的Android工程,并且不创建Activity和launcher icon:
接下来导入FlashRuntimeExtensions.jar。该jar包可以在Flash Builder的安装路径下找到:..\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0\lib\android 。找到后,将jar包拷贝到新建的Android工程的 ..\HelloAne\libs 路径下。操作完的文件目录结构如下:
接下来实现 FREExtension (Implements)、FREContext (extends)和 FREFunction (Implements)。
我们创建一个 ToastFunction 的类,并且指定包名是:com.helloapp.ane.function。然后编写如下代码:
package com.helloapp.ane.function;
import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREInvalidObjectException;
import com.adobe.fre.FREObject;
import com.adobe.fre.FRETypeMismatchException;
import com.adobe.fre.FREWrongThreadException;
import android.widget.Toast;
public class ToastFunction implements FREFunction {
@Override
public FREObject call(FREContext context, FREObject[] objectAry) {
// TODO Auto-generated method stub
FREObject result = null;
try {
String msg = objectAry[0].getAsString();
Toast.makeText(context.getActivity(), msg, Toast.LENGTH_SHORT).show();
// 返回值
result = FREObject.newObject(msg);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FRETypeMismatchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FREInvalidObjectException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FREWrongThreadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
call方法是最终调用到Android native的地方,第一个参数context是Android native的接口类对象,第二个参数objectAry是从Flex手机项目(AS3)传过来的参数数组。例子中接收了一个String类型的msg参数,并显示在手机上。如果需要返回值,可以通过
result = FREObject.newObject(msg);
设置返回值并返回给Flex项目。
我们在包路径:com.helloapp.ane.context;下创建一个名为 HelloAppContext的java 类,目的是返回一个存放本地方法的Map。具体代码如下:
package com.helloapp.ane.context;
import java.util.HashMap;
import java.util.Map;
import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.helloapp.ane.function.ToastFunction;
public class HelloAppContext extends FREContext {
private static final String TOAST_FUNC_KEY = "toast";
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public Map getFunctions() {
// TODO Auto-generated method stub
Map functions = new HashMap();
functions.put(TOAST_FUNC_KEY, new ToastFunction());
return functions;
}
}
在包路径:com.helloapp.ane.extension;下创建名为 HelloAppExtension 的java类,该类负责与AS3 交互。具体代码如下:
package com.helloapp.ane.extension;
import com.adobe.fre.FREContext;
import com.adobe.fre.FREExtension;
import com.helloapp.ane.context.HelloAppContext;
public class HelloAppExtension implements FREExtension {
@Override
public FREContext createContext(String arg0) {
// TODO Auto-generated method stub
return new HelloAppContext();
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public void initialize() {
// TODO Auto-generated method stub
}
}
这样,我们的Android Native Lib就完成了。
鼠标选中src文件夹,右键——>Export——>Java——>JAR file——>Next:
设置jar包导出的路径和名称,然后点击Finish即可导出jar包。
打开FlashBuilder,文件——>新建——>Flex 项目
src目录,右键——>新建——>ActionScript类
通过ExtensionContext与Native交互。
com.example.myextension是一会新建extension.xml中要定义的一个ID,代表了android native extension,通过这个id得到extension的Context,之后调用call方法调用到Native层的Function,根据function_key找到对应的Function。
例如“toast”对应我们之前在android工程里定义的ToastFunction。
package com.example.helloane
{
import flash.external.ExtensionContext;
public class AndroidToast
{
public var extCtx:ExtensionContext=null;
public function AndroidToast()
{
extCtx = ExtensionContext.createExtensionContext("com.example.myextension","");
}
public function showToast(msg:String):void{
if(extCtx){
extCtx.call("toast",msg);
}
}
}
}
在HelloAneFlex工程根目录下创建一个名为extension.xml的文件
并编辑如下:
com.example.myextension
1
helloappane.jar
com.helloapp.ane.extension.HelloAppExtension
com.example.helloane.AndroidToast
编辑id:com.example.myextension 和AS类里面使用的id一样,实际上,是AS类使用的ID必须和这里一样
编辑nativeLibrary:最早导出的jar包:helloappane.jar
编辑initializer:在Android代码中实现的Extension类的全称:com.helloapp.ane.extension.HelloAppExtension
编辑finalizer:在Flex库工程中实现的接口类的全称:com.example.helloane.AndroidToast
创建一个文件夹makeane,把HelloAneFlex工程下的extension.xml文件和bin目录下的HelloAneFlex.swc拷贝进去。再在makeane文件夹下新建一个名为Android-ARM的文件夹,首先把之前打好的helloappane.jar拷贝到Android-ARM文件夹下,再把HelloAneFlex.swc拷贝出一个副本并重命名为zip压缩文件(或者其他压缩文件),解压之后,将里面的所有文件拷贝到Android-ARM文件夹下。这样我们就准备好了打包的所有文件:
进入到makeane文件夹下,shift+右键,选择“在此处打开命令窗口”进入到cmd界面。然后输入以下命令:
"E:\软件\AdobeFlashBuilder\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0\bin\adt" -package -target ane helloappane.ane extension.xml -swc *.swc -platform Android-ARM -C Android-ARM .
其中双引号里是Flash Builder下的adt的路径,注意改成自己的adt的路径!
命令执行完,我们就能在当前文件夹下找到新生成的ANE:helloappane.ane
有文档说要设置Action Script库编译器参数如下,所以最好设置一下: