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文件
- 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开发的同学有帮助。
- Ane的开发总结
- AIR的ane开发
- Flash开发ANE
- 生成Android证书(开发ane需要的证书)
- Adobe Air ANE之Admob开发需要的依赖库
- ane的那些屁事
- ANE总结(Android+iPhone)
- flashdevelop+ane 开发kinect索引
- 开发腾讯移动游戏平台SDK ios版Ane扩展 总结
- 开发腾讯移动游戏平台SDK Android版Ane扩展 总结
- 开发Flash ANE(Android版)
- 开发Flash ANE(Android版)
- ANE 在 Android 上的应用
- 如何导出ane所需的swc
- Air for ANE:打包注意的地方
- ANE 在 Android 上的应用
- Air for ANE:一星期的调试笔记
- Android开发者的Ane简单入门
- 自动安装分布式liberty版本openstack
- 策略设计模式
- 03、索引及高级数据操作
- C语言中的指针和地址的区别
- 历届试题 分糖果
- Ane的开发总结
- Unity项目的目录组织与Prefab的动态实例化
- 算法学习之显著性检测FT算法
- Share Extension调试
- 有1,2,3,4四个数,能组成多少个互不相同且无重复数字的三位数?都是多少?
- 从零开始打造一个Android 3D立体旋转容器
- 监听按钮点击事件
- 401. Binary Watch
- Redux中的Reducers