守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 1377|回复: 0

[IOS] IOS ANE的坑爹之路——url回调、事件传递、原生控件、调试

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51788
    钢镚
    1422

    开源英雄守望者

    发表于 2015-1-15 11:47:41 | 显示全部楼层 |阅读模式

    上回说到了坑爹的微信ANE,这回继续~

    上文解决的问题是比较简单的,只是从我们的app中发消息到微信中,跑通了整个ANE的流程。但是实际应用中还会遇到如下的一些问题:

    • 发送完消息后,能够回到应用中
    • 接收回调完成的消息,进行处理
    • objc端与air端事件传递、消息同步
    • objc端调试不方便
    • 使用原生控件

    下面就一一的解决一下吧~


    1、通过URL调用应用

    原生的iOS应用要解决这个问题很简单,在Xcode中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”即可。

    实际上,Xcode是在info.plist里面添加了一段XML:

    1. <key>CFBundleURLTypes</key>
    2. <array>
    3.   <dict>
    4.     <key>CFBundleURLName</key>
    5.     <string>weixin</string>
    6.     <key>CFBundleURLSchemes</key>
    7.     <array>
    8.       <string>wxappid</string>
    9.     </array>
    10.   </dict>
    11. </array>
    复制代码
    上面的示例注册了一个名为wxappid的 URI 方案,从而允许应用程序由wxappid://形式的 URL 进行调用。而air的程序是用flash builder创建的,打包后的info.plist由flash builder生成。在项目中的app.xml里面有个<iphone>的标签,可在此配置info.plist的内容,因此只需将上面的xml复制到app.xml的<iphone>标签中即可。更多的配置选项可以参考这里~通过自定义 URI 调用应用程序时,air的NativeApplication 对象会调一个 invoke 事件,链接的 URL(包括查询参数)放在 InvokeEvent 对象的 arguments 数组中,我们可以在applicationCompleteHandler如下调用:
    1. NativeApplication.nativeApplication
    2.     .addEventListener(InvokeEvent.INVOKE,
    3.         function invokeHandler(event:InvokeEvent):void{
    4.             if(event.arguments.length>0){
    5.                 doSomething(event.arguments[0]);
    6.             }
    7.         });
    复制代码
    2、处理微信的URL回调微信的URL回调有两种:在微信中向应用请求消息、在应用发消息给微信后返回应用。原生应用要触发这两个回调是在 applicationpenURL:sourceApplication:annotation: 方法中中调用WXApi handleOpenURL:delegate:,触发delegate的onReq或onResp方法。
    然而air开发的应用无法调用此方法,因此可以利用上面的invoke事件通过ANE进行调用。

    3、Objc与Air进行事件同步delegate的onReq或onResp被触发后,往往是要让应用进行某些处理,因此还需要objc和air端进行消息同步,可调用air提供了的C语言接口FREDispatchStatusEventAsync进行处理:
    1. //收到一个来自微信的请求,处理完后调用sendResp
    2. -(void) onReq:(BaseReq*)req {
    3.   NSString * code = @"onWXReq";
    4.   NSString * level = @"someReqData";

    5.   FREDispatchStatusEventAsync(g_ctx,
    6.         (constuint8_t *)[code UTF8String],
    7.         (constuint8_t *)[level UTF8String]);
    8. }

    9. //发送一个sendReq后,收到微信的回应
    10. -(void) onResp:(BaseResp*)resp {
    11.   NSString * code = @"onWXResp";
    12.   NSString * level = @"someRespData";

    13.   FREDispatchStatusEventAsync(g_ctx,
    14.         (constuint8_t *)[code UTF8String],
    15.         (constuint8_t *)[level UTF8String]);
    16. }
    复制代码
    上面两个方法是向air端发出事件,因此air端需要对事件进行监听,我们需要对之前的actionScript接口进行修改:创建一个Weixin事件对象
    1. public class WeixinApiEvent extends Event {
    2.   public static const onReq:String = "onWXReq";
    3.   public static const onResp:String = "onQXResp";

    4.   public var data:String = null;

    5.   public function WeixinApiEvent(type:String,
    6.                 data:String,
    7.                 bubbles:Boolean=false,
    8.                 cancelable:Boolean=false) {
    9.     super(type, bubbles, cancelable);
    10.     this.data = data;
    11.   }
    12. }
    复制代码
    继承EventDispatcher,并监听StatusEvent
    1. import flash.events.EventDispatcher;
    2. import flash.events.StatusEvent;

    3. public class WeixinApi extends EventDispatcher {
    4.   ...
    5.   public function WeixinApi(appIdStr:String) {
    6.     super();
    7.     this.registerApp(appIdStr);
    8.     if(isRegistered){
    9.       //监听StatusEvent
    10.       extContext.addEventListener(StatusEvent.STATUS,onStatus);
    11.     }
    12.   }
    13.   ...
    14.   public function onStatus(e:StatusEvent):void {
    15.     //将事件封装并转发给应用
    16.     dispatchEvent(new WeixinApiEvent(e.code,e.level));
    17.   }
    18. }
    复制代码
    重新打包ANE后,即可在应用中对微信的回调事件进行监听了,如:
    1. function applicationCompleteHandler(event:FlexEvent):void {
    2.   ...
    3.   wxApi = new WeixinApi("weixinApi");
    4.   wxApi.addEventListener(WeixinApiEvent.onReq,dosomething);
    5.   wxApi.addEventListener(WeixinApiEvent.onResp,dosomething);
    6.   ...
    7. }
    复制代码
    4、原生控件调用及辅助调试ANE的调试一直是很纠结的,代码分布在3个地方,并且air端不支持alert,安装到iOS设备上也看不到trace信息,出错了也不知错在哪,纠结~~~~ air端可以通过try/catch捕获错误信息,将debug信息输出到一个textField里面,但对于objc端就无能为力了。好在可以通过ANE调用objc的原生控件,这样就可以将objc端的调试信息展示出来了。AIR应用是在一个标准的window对象里运行的,你可以通过下面的方法获得这个window对象:
    1. [UIApplication sharedApplication].keyWindow
    复制代码
    得到window对象后你可以给它添加subviews来显示原生的view对象。
    1. UILabel* nativeLogLabel;
    2. NSString * logInfo = @"-- start loging --";

    3. //air无法alert,那就直接调用原生的alert吧~
    4. void nativeAlert(NSString * title, NSString * message) {
    5. UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:title
    6.   message:message
    7.   delegate:nil
    8.   cancelButtonTitle:@"OK"
    9.   otherButtonTitles:nil, nil];
    10.   [alert show];
    11.   [alert release];
    12. }
    13. //在界面中显示logArea
    14. void showLogArea(float x, float y, float width, float height) {
    15.   if (!nativeLogLabel){
    16.     nativeLogLabel = [[UILabelalloc] initWithFrame:CGRectMake(x, y, width, height)];
    17.     nativeLogLabel.font = [UIFontsystemFontOfSize:11];
    18.     nativeLogLabel.lineBreakMode = UILineBreakModeWordWrap;
    19.     nativeLogLabel.numberOfLines = 0;
    20.   }
    21.   nativeLogLabel.frame = CGRectMake(x, y, width, height);
    22.   nativeLogLabel.text = logInfo;
    23.   [[[UIApplicationsharedApplication] keyWindow] addSubview:nativeLogLabel];
    24. }
    25. //添加log信息
    26. void addLogContent(NSString * log){
    27.   logInfo = [NSStringstringWithFormat:@"%@\n%@",log,logInfo];
    28.   if (nativeLogLabel){
    29.     nativeLogLabel.text = logInfo;
    30.   }
    31. }
    复制代码
    通过定义ANE_FUNCTION的方式将这三个方法暴露出去后,即可在air和objc端调用统一的调试信息输出接口,找bug总算容易多了~


    5、其他经验个人总结的一些经验:
    • ANE的相关资料比较少,最好的办法就是多看Adobe提供的文档~ ;
    • 使用(一)中提到的xcode模板,它帮你写好了各种方法定义、宏、配置、批处理文件,不然你的开发会成倍的复杂;
    • 将FlashRuntimeExtensions.h中常用的方法进行封装,诸如从FREObject里面获取数据等;
    • 用一个objc对象封装所有的业务逻辑,而不是将所有逻辑都写在ANE_FUNCTION里面;

    比较常见的错误:
    • air端try/catch捕获异常 argument error #3500 -- objc忘了将方法添加到functionsToSet 中;
    • 调用ANE方法直接闪退 -- objc中有错误的内存引用,好好研究下什么retain、release的吧;
    • 发布AIR应用的时候,指明需要引用的iOS SDK地址,不然有些时候会出错。在Flash Builder里,在“构建打包>本机扩展”面板中可以进行设置;

    另外推荐一篇文章:《20条开发AIR Native Extension的建议
    Blog: http://rolfzhang.com/
    本文作者:Rolf_Zhang


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2019-11-18 16:26 , Processed in 0.046003 second(s), 34 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表