Ane的开发总结

来源:互联网 发布:.手机 域名骗局 编辑:程序博客网 时间:2024/04/30 01:46

1.flashBuilder开发

创建名为MyNativeLib的项目再创建一个名为EntryPoint的ActionScript类,我们以这个作为扩展的入口,

包名com.booyue.myane,OK,工程创建结束。

代码有以下三点:

① 继承EventDispatcher

public class EntryPoint extends EventDispatcher

EventDispatcher是可调度事件的所有类的基类,事件模型的重要组成部分)暂时不懂没关系

② 创造一个ExtensionContext

ExtensionContext.createExtensionContext(EXTENSION_ID, “”);

通过ExtensionContext来访问本地代码可以通过它的call()方法来调用本地方法EXTENSION_ID:是我们创建的扩展的唯一标识

③ 给ExtensionContext添加事件监听

extensionContext.addEventListener(StatusEvent.STATUS, onStatus);

异步的本地代码结果会传递到该监听中

具体代码如下:

package com.booyue.myane{    import flash.events.Event;    import flash.events.EventDispatcher;    import flash.events.StatusEvent;    import flash.external.ExtensionContext;    public class EntryPoint extends EventDispatcher{        private static var instance:EntryPoint;         private static var extensionContext:ExtensionContext;        // 我们编写的ane的唯一标识        public static const EXTENSION_ID:String = "com.booyue.myane";         public function EntryPoint(){            // 创建一个与本地代码调用的ExtensionContext            extensionContext = ExtensionContext.createExtensionContext(EXTENSION_ID, "");            extensionContext.addEventListener(StatusEvent.STATUS, onStatus); // 添加回调事件返回监听        }        public static function getInstance():EntryPoint { //类单例方式实现            if(instance == null)                instance = new EntryPoint();            return instance;        }       //本地代码的回调会返回到该方法        protected function onStatus(event:StatusEvent):void{        //event.level回调内容 event.code区分回调的类别//dispatchEvent(new KeyValueEvent(KeyValueEvent.ASR_RESULT,event.level+"=="+event.type+"=="+event.code,false,false));            if(event.code == "notifyKeyValueChange"){            dispatchEvent(new KeyValueEvent(KeyValueEvent.RESULT,event.level,false,false));//向flash分发事件            }else if(event.code == "notifyAsrCallback"){            dispatchEvent(newKeyValueEvent(KeyValueEvent.ASR_RESULT,event.level,false,false));            }        }        }    }}

下面叙述了通过ExtensionContext来访问本地代码,通过它的call()方法来调用本地方法,具体代码如下:

public static function getNativeData():String {            var params1:int = 3;            var params2:String = "paramsString";            if(extensionContext != null)                return extensionContext.call("getNativeData",params1,params2) as String;            else                return null;        }

2.本地代码的实现

由于这套规范必然是Adobe的工程师们设计的,所以我们得通过他们提供的入口和规范来实现我们想要的功

能,因此我们需要Adobe提供的java库了,路径在/AirSDK根目录/lib/android/FlashRuntimeExtensions.jar

将FlashRuntimeExtensions.jar添加到你的安卓工程中

air_sdk下载链接

① 实现FREExtension接口

FREExtension是扩展的入口,需要返回一个FREContext的对象,通过接口定义的createContext可以获得本地代码的连接器(上下文)
public class NativeExtension implements FREExtension{    private static final String TAG = "NativeExtension";    public static FREContext extensionContext;    public static Context appContext;    public static void notifyKeyValueChange(String str) {        LogManager.d("notifyKeyValueChange");        if(extensionContext != null){            extensionContext.dispatchStatusEventAsync("notifyKeyValueChange", str);            Log.d(TAG, "dispatchStatusEventAsync");        }    }    public static void notifyAsrCallback(String str) {        LogManager.d("notifyAsrCallback");        if(extensionContext != null){            extensionContext.dispatchStatusEventAsync("notifyAsrCallback", str);            Log.d(TAG, "dispatchStatusEventAsync");        }    }    /**     * 需要返回一个FREContext对象     */    @Override    public FREContext createContext(String s){        Log.d(TAG, "createcontext begin");        return new NativeContext();    }    /***     * Extension结束后的操作     */    @Override    public void dispose() {        appContext = null;        extensionContext = null;        Log.d(TAG, "dispose begin");    }    /**     * Extension初始化的操作     */    @Override    public void initialize() {        Log.d(TAG, "Extension initialized");    }}

② 实现FREContext对象。

该对象就是本地代码的连接器(上下文),通过该对象的getFunctions()返回给ActionScript能够调用到的方法集合,该方法集合都是FREFunction的子类
public class NativeContext extends FREContext{    private static final String TAG = "NativeContext";    /**     * 返回一个包含FREFunction的map集合     *     * @return     */    @Override    public Map<String, FREFunction> getFunctions() {        Log.d(TAG, "getFunctions begin");        Map<String, FREFunction> map = new HashMap<String, FREFunction>();        map.put("init", new InitFunction());//注册滑块监听        map.put("writePassInfo", new InitFunction());//写入过关信息        map.put("record", new InitFunction());//开始录音        map.put("play", new InitFunction());// 播放录音        Log.d(TAG, "createcontext success");        return map;    }    @Override    public void dispose() {        // TODO Auto-generated method stub        Log.d(TAG,"Context disposed");    }}

把FREContext传递给Extension

@Override
public FREContext createContext(String arg0) { //需要返回一个FREContext对象
NativeContext context = new NativeContext();
return context;
}

③ 实现FREFunction接口

该接口定义了一个方法,叫做call,是不是很熟悉,对,这个call方法与ActionScript中的ExtensionContext的call方法是对应的,这也是它们沟通的最后一步

public class GetNativeDataFunction implements FREFunction{

@Overridepublic FREObject call(FREContext arg0, FREObject[] arg1) {    return null;}

}

注意几点:① 参数一arg0,也就是FREContext对象。它有一些实用的方法,如获取Activity,Activity在Android中是一个很重要的组件,它负责与用户交互,可以加载UI并且根据不同情况有对应的生命周期方法。Activity activity = arg0.getActivity();

FREFunction的代码如下:

public class GetNativeDataFunction implements FREFunction{    @Override    public FREObject call(FREContext arg0, FREObject[] arg1) {        Activity activity = arg0.getActivity();         Log.i("ANE", activity.getPackageName()); // 使用安卓的日志方法打印出应用的包名        int params1 = 0;        String params2 = null;        try {            params1 = arg1[0].getAsInt();    // 获取第一个参数            params2 = arg1[1].getAsString(); // 获取第二个参数        } catch (IllegalStateException e) {            e.printStackTrace();        } catch (FRETypeMismatchException e) {            e.printStackTrace();        } catch (FREInvalidObjectException e) {            e.printStackTrace();        } catch (FREWrongThreadException e) {            e.printStackTrace();        }        FREObject freObject = null;        try {            String nativeData = params1 + params2; //将参数1与参数2拼接            freObject = FREObject.newObject(nativeData);        } catch (FREWrongThreadException e) {            e.printStackTrace();        }        return freObject; //返回结果    }}

将FreFunction添加到FreContext

@Overridepublic Map<String, FREFunction> getFunctions() { // 需要返回一个包含FREFunction的Map集合        Map<String, FREFunction> map = new HashMap<String, FREFunction>();        map.put("getNativeData", new GetNativeDataFunction());        return map;}

② 关于安卓的生命周期的处理
了解点安卓的同学应该知道,常常会用到Activity的生命周期的方法,那在本地代码中如何处理?Adobe工程师设计了一个Activity的包装类AndroidActivityWrapper,通过给包装类注册监听来监听安卓Activity的变化。

你会发现在扩展的jar包并没有这个类,那是因为扩展还是上面一层,而安卓的Activity涉及到了设备代码,所以它自然而然处在了Air的Runtime中,所以你还需要一个runtime的jar包。在路径/Air_SDK根目录/lib/android/lib/runtimeClasses.jar

导入runtimeClasses.jar,OK,可以找到AndroidActivityWrapper类了
同样我们监听还需要在runtime中的StateChangeCallback接口和ActivityResultCallback接口

注意一点:反编译runtimeClasses.jar看AndroidActivityWrapper类中StateChangeCallback接口和ActivityResultCallback接口时,发现这两个接口时protected的,也就是说,如果要实现这两个接口就需要与AndroidActivityWrapper在同一个包下,即在com.adobe.air包下。static abstract interface ActivityResultCallback{    public abstract void onActivityResult(int paramInt1, int paramInt2, Intent paramIntent);}static abstract interface StateChangeCallback {    public abstract void onActivityStateChanged(AndroidActivityWrapper.ActivityState paramActivityState);    public abstract void onConfigurationChanged(Configuration paramConfiguration);}所以,按照以下实现思路操作:在com.adobe.air包路径下创建新接口继承ActivityResultCallback和StateChangeCallback,但是把权限放大到public

于是在com.adobe.air下先创建抽象接口,继承ActivityResultCallback和StateChangeCallback,代码如下:

package com.adobe.air;

import com.adobe.air.AndroidActivityWrapper.ActivityResultCallback;
import com.adobe.air.AndroidActivityWrapper.StateChangeCallback;

public abstract interface LifeCycle extends ActivityResultCallback, StateChangeCallback{}

通过上面的方法,在我们自己的代码中就可以处理生命周期了
于是再改造一下NativeContext类,实现我们自己的LifeCycle接口
在构造函数中添加监听,在dispose方法中移除监听

public class NativeContext extends FREContext implements LifeCycle{

private AndroidActivityWrapper activityWrapper;public NativeContext() {    activityWrapper = AndroidActivityWrapper.GetAndroidActivityWrapper(); //ActivityWrapper    activityWrapper.addActivityResultListener(this); // 监听onActivityResult方法    activityWrapper.addActivityStateChangeListner(this); // 监听生命周期方法}@Overridepublic void dispose() { // Context结束后的操作    if(activityWrapper != null)        activityWrapper.removeActivityResultListener(this);        activityWrapper.removeActivityStateChangeListner(this);}@Overridepublic Map<String, FREFunction> getFunctions() { // 需要返回一个包含FREFunction的Map集合    Map<String, FREFunction> map = new HashMap<String, FREFunction>();    map.put("getNativeData", new GetNativeDataFunction());    return map;}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { // onActivityResult方法}@Overridepublic void onActivityStateChanged(ActivityState state) { // 生命周期变化}@Overridepublic void onConfigurationChanged(Configuration config) {}

}

其中生命周期的对应关系如下:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { // onActivityResult方法
Log.i(“ANE”, “onActivityResult”);
}

@Override
public void onActivityStateChanged(ActivityState state) { // 生命周期变化
switch (state) {
case RESUMED: // 生命周期onResume
Log.i(“ANE”, “onResume”);
break;
case STARTED: // 生命周期onStart
Log.i(“ANE”, “onStart”);
break;
case RESTARTED: // 生命周期onRestart
Log.i(“ANE”, “onRestart”);
break;
case PAUSED: // 生命周期onPause
Log.i(“ANE”, “onPause”);
break;
case STOPPED: // 生命周期onStop
Log.i(“ANE”, “onStop”);
break;
case DESTROYED: // 生命周期onDestory
Log.i(“ANE”, “onDestory”);
break;
}
}

以上就是安卓本地代码的处理了,总结一下
① 核心类FREExtension,FREContext,FREFunction
② 通过FREContext连通,call方法调用
③ 异步回调可以通过FREContext的dispatchStatusEventAsync处理
④ 生命周期的实现需要点技巧

3.制作ANE

进过上面操作代码逻辑层面已经处理完了,废话不说,通过上面的东西,制作可用的ANE
2.2.1 准备资源

以下是一个ANE打包的资源清单,只需要Android或者IOS的同学可自由组合,后面分别介绍它们

Android本地代码库——jar包(Android需要)IOS本地代码库——IOS静态库文件(IOS需要)ActionScript库——SWC文件(必须)library.swf(必须)extension.xml(必须,Android与IOS配置不同)platformoptions.xml (IOS可能需要)第三方库文件 (IOS可能需要)

1 Android本地代码库——jar包

先将android本地代码导出jar包,右键Eclipse工程,Export

2 ActionScript库——SWC文件(必须)
swc文件将改为rar文件,在解压就生成swf和catelog.xml文件

  1. library.swf(必须)

4.extension.xml文件

<extension xmlns="http://ns.adobe.com/air/extension/3.5">    <id>com.booyue.myane</id>    <versionNumber>1</versionNumber>    <platforms>        <platform name="default">            <applicationDeployment>            </applicationDeployment>        </platform>        <platform name="Android-ARM">            <applicationDeployment>                <nativeLibrary>MyNativeLib.jar</nativeLibrary>                <initializer>com.xuemin.mynativelib.NativeExtension</initializer>            </applicationDeployment>        </platform>        <platform name="iPhone-ARM">            <applicationDeployment>                <nativeLibrary>libMyNativeLib.a</nativeLibrary>                <initializer>ExtensionInitializer</initializer>                <finalizer>ExtensionFinalizer</finalizer>            </applicationDeployment>        </platform>    </platforms></extension>

4.Ane打包

通过adb命令
adt -package -target ane L1FlashAndroidLib.ane extension.xml -swc L1FlashLib.swc -platform Android-ARM L1NativeLib1.jar library.swf -platform default library.swf

备注:希望对于想学习ane开发的同学有帮助。

0 0
原创粉丝点击