AIR Native Extension for iOS 接入第三方sdk 如何实现 AppDelegate 生命周期

作者:Panda Fang

出处:http://www.cnblogs.com/lonkiss/p/6492385.html

原创文章,转载请注明作者和出处,未经允许不可用于商业营利活动

去年到今年做了几个 iOS上的 AIR Native Extension (简称 ANE), 痛苦不堪。  ANE 的开发方式早已被前辈吐槽多多 效率低下 浪费生命 严重压低kpi 。体验过Unity的插件开发, 相比之下真的是爽快多了,效率飙升。

言归正传, 痛苦之一就是难以实现AppDelegate 生命周期。关于生命周期实现,其实Android上的 ane 也难搞。下次再写。如果在 xcode上做一个标准的 iOS App 写 AppDelegate 很方便, 填函数就行了。 但是在ANE上 没有暴露这些api给你实现。air 本身是运行在ios上的app ,adobe 实现它的时候自己使用了 delegate 但是却不暴露给我们使用。 我们使用adobe air sdk做依赖adobe 的框架, 束手束脚, 真的忍不住一边做一边骂adobe 。既然adobe air用了 那么我们就能靠hook了, 下面这篇文章非常值得看

打通Android、IOS、ANE制作流程 - 知其然知其所以然 - 博客频道 - CSDN.NET

接着我将引用这篇文章进行讲解

在xcode 中 新建一个 objective-c 文件 取名为 HookUtil  , xocde 将生成一个HookUtil.m文件 将文件里的代码删干净, 复制下面的代码粘贴进去。但下面的代码并不能解决问题,真正要知其所以然还是要坚持看完我最后是怎么解决的。

  1 //
  2 //  HookUtils.m
  3 //  ResearchMethodSwizzl
  4 //
  5 //  Created by 薛旻 on 15/4/27.
  6 //  Copyright (c) 2015年 薛旻. All rights reserved.
  7 //
  8
  9 #import <Foundation/Foundation.h>
 10 #import <UIKit/UIKit.h>
 11 #import <objc/runtime.h>
 12
 13
 14 @interface HookUtils : NSObject
 15
 16 + (void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL;
 17
 18 @end
 19
 20 @implementation HookUtils
 21
 22 + (void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL {
 23     NSLog(@"hookMehod");
 24
 25     Class oldClass = objc_getClass([@"CTAppDelegate" UTF8String]);
 26
 27     Class newClass = [HookUtils class];
 28
 29     //把方法加给原Class
 30     class_addMethod(oldClass, newSEL, class_getMethodImplementation(newClass, newSEL), nil);
 31     class_addMethod(oldClass, oldSEL, class_getMethodImplementation(newClass, defaultSEL),nil);
 32
 33     Method oldMethod = class_getInstanceMethod(oldClass, oldSEL);
 34     assert(oldMethod);
 35     Method newMethod = class_getInstanceMethod(oldClass, newSEL);
 36     assert(newMethod);
 37     method_exchangeImplementations(oldMethod, newMethod);
 38
 39 }
 40
 41 + (void)load {
 42     NSLog(@"load");
 43     [self hookMehod:@selector(application:didFinishLaunchingWithOptions:) andDef:@selector(defaultApplication:didFinishLaunchingWithOptions:) andNew:@selector(hookedApplication:didFinishLaunchingWithOptions:)];
 44
 45     [self hookMehod:@selector(applicationWillEnterForeground:) andDef:@selector(defaultApplicationWillEnterForeground:) andNew:@selector(hookedApplicationWillEnterForeground:)];
 46 }
 47
 48
 49 /*具体要走的代码*/
 50 -(BOOL)hookedApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic
 51 {
 52     NSLog(@"applicationDidFinishLaunching");
 53     [self hookedApplication:application didFinishLaunchingWithOptions:dic];
 54     return YES;
 55 }
 56
 57 - (void)hookedApplicationWillResignActive:(UIApplication *)application {
 58     [self hookedApplicationWillResignActive:application];
 59 }
 60
 61 - (void)hookedApplicationDidEnterBackground:(UIApplication *)application {
 62     [self hookedApplicationDidEnterBackground:application];
 63 }
 64
 65 - (void)hookedApplicationWillEnterForeground:(UIApplication *)application {
 66     [self hookedApplicationWillEnterForeground:application];
 67 }
 68
 69 - (void)hookedApplicationDidBecomeActive:(UIApplication *)application {
 70     [self hookedApplicationDidBecomeActive:application];
 71 }
 72
 73 - (void)hookedApplicationWillTerminate:(UIApplication *)application {
 74     [self hookedApplicationWillTerminate:application];
 75 }
 76
 77 /*支付宝对应的方法*/
 78 - (BOOL)hookedApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
 79     [self hookedApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation];
 80     return YES;
 81 }
 82
 83
 84
 85 -(BOOL)hookedApplication:(UIApplication*)application handleOpenURL:(NSURL*)url {
 86     [self hookedApplication:application handleOpenURL:url];
 87     return YES;
 88 }
 89
 90
 91 #pragma 默认
 92 /*default 默认不需要改动*/
 93 - (BOOL)defaultApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic { return YES;
 94 }
 95
 96 - (void)defaultApplicationWillResignActive:(UIApplication *)application {}
 97
 98 - (void)defaultApplicationDidEnterBackground:(UIApplication *)application {}
 99
100 - (void)defaultApplicationWillEnterForeground:(UIApplication *)application {}
101
102 - (void)defaultApplicationDidBecomeActive:(UIApplication *)application {}
103
104 - (void)defaultApplicationWillTerminate:(UIApplication *)application {}
105
106 - (BOOL)defaultApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
107     return YES;
108 }
109
110 - (BOOL)defaultApplication:(UIApplication *)application handleOpenURL:(NSURL *)url {
111     return YES;
112 }
113 @end

关于这个HookUtils做几点说明: 
① HookUtils是IOS的Hook机制的实现,所以适用于所有IOS的开发,这里只是针对Air应用做了一些处理。 
① Hook机制中需要获取应用的实现了生命周期的类名,这样才能Hook处理,如果你是Xcode工程开发的代码那你会很方便的找到这个类名,这适用于IOS原生,Unity以及Cocos引擎,因为它们都会使用Xcode开发工具。但是,Air开发是在Flash Builder上,并不直接涉及到Xcode工程,通过代码打印Air应用的生命周期类,找到了Air的类名CTAppDelegate,于是代码中设置为,其他引擎自行修改,当然,你也可以通过配置文件(Info.plist)获取,这样代码就不需要修改了

 Class oldClass = objc_getClass([@"CTAppDelegate" UTF8String]);

③ 你需要在hooked**方法中实现你的具体代码,最后在+ (void)load()方法中调用头文件定义的方法(void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL;来达到Hook的目的

上面是引用那篇博客的,我加好代码后就疑问了, 那哪里来调用它呢。 问了有经验的iOS开发者才明白 其实并不用在别的函数里面来调用这个HookUtil里的函数, 这个类方法 load就是入口, 只要声明为类方法并起名load会被系统自动调用。 制作好ane 后在demo中测试,原本可以跑起来的demo自从加了HookUtil反而启动就闪退了,通过观察log发现 hookMethod执行了,果然是系统自动调用这些代码, ane 还没在demo中通过按钮触发实例化呢

于是增加log 最后定位到在34行  assert(oldMethod);  这行挂掉,原来 oldMethod是null ,但是看半天没看出来哪里错了, 后来怀疑25行  oldClass   会不会也是null 呢, 于是加了日志  NSLog(@"oldclass %@", oldClass);  果然 也是null , 这时候回顾那篇博客,也许不是CTAppDelegate 这个名字呢? 那篇博客说通过代码打印Air应用的生命周期类,找到了Air的类名CTAppDelegate。 于是在 hookMethod里面打印

1    id delegate = [UIApplication sharedApplication].delegate;
2     NSLog(@"delegate %@", delegate);

然而还是null ,然后又想啊, 会不会是时机太早啊。 于是放在了 ane的一个api方法里面在 应用层demo中通过按钮触发,

1 FREObject initSDK(FREContext ctx, void *data, uint32_t argc, FREObject argv[])
2 {
3     id delegate = [UIApplication sharedApplication].delegate;
4     NSLog(@"------------delegate %@", delegate);
5 }

果然不再是null 了, 打印出来的名字也不是CTAppDelegate,而是 CTAppController 我的 airsdk 是21 ,adobe adobe 又改名字了。  把25行代码中的CTAppDelegate 改成 CTAppController 之后测试, delegate中的函数得到正确调用, 实现生命周期delegate就此解决

时间: 2024-10-24 17:23:19

AIR Native Extension for iOS 接入第三方sdk 如何实现 AppDelegate 生命周期的相关文章

接入第三方sdk出现了一些问题总结

最近cocos2d-x 3.3工程接入第三方sdk时,出现支付的时候应用重启的问题. 结果排查发现,cocos2d-x 3.3经过特殊方法处理(处理方法:http://www.cnblogs.com/Colored-Mr/p/4239888.html),so文件复制在lib/armeabi文件下,但是会出现so文件复制不全的问题(可以比对大小)... 目前只能经过打包后解压apk文件,然后进入apk把so文件重新复制进去,重新签名后包就可以运行了!!!

iOS系列 基础篇 03 探究应用生命周期

iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本篇主要探讨的是iOS应用中各种状态的跃迁过程,建议大家通过修改AppDelegate.swift,在每个过程中添加日志输出代码,从而观察其变化. 作为应用程序的委托对象,AppDelegate类在应用程序生命周期的不同阶段会回调不同的方法. 首先,咱们先来了解一下iOS应用的不同状态和他们之间的关系

iOS程序执行顺序和UIViewController 的生命周期(整理)

说明:此文是自己的总结笔记,主要参考: iOS程序的启动执行顺序 AppDelegate 及 UIViewController 的生命周期 UIView的生命周期 言叶之庭.jpeg 一. iOS程序的启动执行顺序 程序启动顺序图 iOS启动原理图.png 具体执行流程 程序入口进入main函数,设置AppDelegate称为函数的代理 程序完成加载[AppDelegate application:didFinishLaunchingWithOptions:] 创建window窗口 程序被激活[

iOS开发之旅之App的生命周期

在iOS App中,入口函数并不在根目录下,而是在"Supporting Files"目录的main.m文件的main函数中.这很容易理解,C/C++都是以main为入口. int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } 这个函数比较简单,只是调用了UI

iOS 平台 Cocos2d-x 项目 接入第三方SDK 的坑(就是静态库接入的问题)

解决方法是: -force_load path/to/your/libWeiboSDK.a 而不是 他提供的-ObjC.-all_load,下面是一些详细说明 我的开发环境 Mac OS X 10.10.1Xcode 6.1.1 (6A2008a)Cocos2d-x 3.2新浪微博 SDK for iOS 2015 年 1 月 5 日从 github clone 的版本 遇到的问题 根据新浪微博 SDK 附带的文档接入项目后,在模拟器运行项目,在调用注册方法时发生崩溃.注册方法代码: 1 [We

Xamarin.ios引用第三方SDK

引言 诚然,Xamarin是个优秀的跨平台解决方案,但毕竟还是不能将Native中所有的方法都直接实现.诸如各种第三方库,也都只有java/oc原生版本的SDK,无法直接拿过来直接使用.但,不能直接拿过来用,就没办法扩展APP功能,不能使用已经造好的轮子吗?答案是否定的!Xamarin中可以通过引用java中的Jar包,oc中的A档,实现这一切! 什么是a档? a档就是iOS中的class library,我是这么理解为啥叫a档的,因为a档生成的文件扩展名是.a.举个栗子: 如何建立a档 1.在

iOS 基于第三方QQ授权登录

基于iOS实现APP的第三方QQ登陆,接入第三方SDK时的一个基本的步骤: 1,找到相关的开放平台,QQ互联平台,http://connect.qq.com/: 2,注册成功后创建自己的APP,填写一堆基本信号后获得一个App_Key,就是你APP的唯一识别码: 3,下载对应的SDK,并且阅读其中的开发文档或demo,通常看开发文档比较直观,如果看demo,有些SDK的demo简直不忍直视: 4,嵌入SDK中对应功能,测试成功后提交第三方平台审核,等审核通过后就可以正式接入第三方SDK的功能了:

React Native之生命周期

React Native生命周期主要分为三大阶段:实例化阶段(图中上框部分),存在阶段(图中左框部分),销毁阶段(图中右框部分). 如图: 下面简单讲解一下三大阶段中各自的函数: 实例化阶段: 在日常开发中,最为常用的就是实例化阶段,因为该阶段是组件的构建,展示阶段. getDefaultProps: 该函数用于初始化一些默认的属性,开发中,通常将一些固定不变的值放在该函数内进行初始化,比如url.可以利用this.props.XXX 来获取该属性值.由于被初始化后,以后就不会再调用getDef

IOS视图控制器导航及生命周期研究Demo

1.背景: 2014年4月份第一次接触IOS端开发,为某银行开发一款金融app.在开发的最后阶段,加入了需要从任意一个页面直接返回主页的功能.悲催的是,当时没有使用UINavigationController进行导航管理,而是使用了IOS中的模态跳转方式(presentViewController/dismissViewControllerAnimated). 因此需要找的一种方法进行,实现如下方式的导航跳转: 已知: 页面a→页面b→页面c 求解: 页面c直接跳回到页面a,并且要求不能有内存泄