Ane的开发总结

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{

@Override
public 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

@Override
public 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); // 监听生命周期方法
}

@Override
public void dispose() { // Context结束后的操作
    if(activityWrapper != null)
        activityWrapper.removeActivityResultListener(this);
        activityWrapper.removeActivityStateChangeListner(this);
}

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


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { // onActivityResult方法

}

@Override
public void onActivityStateChanged(ActivityState state) { // 生命周期变化

}

@Override
public 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开发的同学有帮助。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值