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文件 将文件里的代码删干净, 复制下面的代码粘贴进去。但下面的代码并不能解决问题,真正要知其所以然还是要坚持看完我最后是怎么解决的。
//
// HookUtils.m
// ResearchMethodSwizzl
//
// Created by 薛旻 on 15/4/27.
// Copyright (c) 2015年 薛旻. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <objc/runtime.h> @interface HookUtils : NSObject + (void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL; @end @implementation HookUtils + (void)hookMehod:(SEL)oldSEL andDef:(SEL)defaultSEL andNew:(SEL)newSEL {
NSLog(@"hookMehod"); Class oldClass = objc_getClass([@"CTAppDelegate" UTF8String]); Class newClass = [HookUtils class]; //把方法加给原Class
class_addMethod(oldClass, newSEL, class_getMethodImplementation(newClass, newSEL), nil);
class_addMethod(oldClass, oldSEL, class_getMethodImplementation(newClass, defaultSEL),nil); Method oldMethod = class_getInstanceMethod(oldClass, oldSEL);
assert(oldMethod);
Method newMethod = class_getInstanceMethod(oldClass, newSEL);
assert(newMethod);
method_exchangeImplementations(oldMethod, newMethod); } + (void)load {
NSLog(@"load");
[self hookMehod:@selector(application:didFinishLaunchingWithOptions:) andDef:@selector(defaultApplication:didFinishLaunchingWithOptions:) andNew:@selector(hookedApplication:didFinishLaunchingWithOptions:)]; [self hookMehod:@selector(applicationWillEnterForeground:) andDef:@selector(defaultApplicationWillEnterForeground:) andNew:@selector(hookedApplicationWillEnterForeground:)];
} /*具体要走的代码*/
-(BOOL)hookedApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic
{
NSLog(@"applicationDidFinishLaunching");
[self hookedApplication:application didFinishLaunchingWithOptions:dic];
return YES;
} - (void)hookedApplicationWillResignActive:(UIApplication *)application {
[self hookedApplicationWillResignActive:application];
} - (void)hookedApplicationDidEnterBackground:(UIApplication *)application {
[self hookedApplicationDidEnterBackground:application];
} - (void)hookedApplicationWillEnterForeground:(UIApplication *)application {
[self hookedApplicationWillEnterForeground:application];
} - (void)hookedApplicationDidBecomeActive:(UIApplication *)application {
[self hookedApplicationDidBecomeActive:application];
} - (void)hookedApplicationWillTerminate:(UIApplication *)application {
[self hookedApplicationWillTerminate:application];
} /*支付宝对应的方法*/
- (BOOL)hookedApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[self hookedApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation];
return YES;
} -(BOOL)hookedApplication:(UIApplication*)application handleOpenURL:(NSURL*)url {
[self hookedApplication:application handleOpenURL:url];
return YES;
} #pragma 默认
/*default 默认不需要改动*/
- (BOOL)defaultApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic { return YES;
} - (void)defaultApplicationWillResignActive:(UIApplication *)application {} - (void)defaultApplicationDidEnterBackground:(UIApplication *)application {} - (void)defaultApplicationWillEnterForeground:(UIApplication *)application {} - (void)defaultApplicationDidBecomeActive:(UIApplication *)application {} - (void)defaultApplicationWillTerminate:(UIApplication *)application {} - (BOOL)defaultApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return YES;
} - (BOOL)defaultApplication:(UIApplication *)application handleOpenURL:(NSURL *)url {
return YES;
}
@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里面打印
id delegate = [UIApplication sharedApplication].delegate;
NSLog(@"delegate %@", delegate);
然而还是null ,然后又想啊, 会不会是时机太早啊。 于是放在了 ane的一个api方法里面在 应用层demo中通过按钮触发,
FREObject initSDK(FREContext ctx, void *data, uint32_t argc, FREObject argv[])
{
id delegate = [UIApplication sharedApplication].delegate;
NSLog(@"------------delegate %@", delegate);
}
果然不再是null 了, 打印出来的名字也不是CTAppDelegate,而是 CTAppController 我的 airsdk 是21 ,adobe adobe 又改名字了。 把25行代码中的CTAppDelegate 改成 CTAppController 之后测试, delegate中的函数得到正确调用, 实现生命周期delegate就此解决
AIR Native Extension for iOS 接入第三方sdk 如何实现 AppDelegate 生命周期的更多相关文章
- iOS系列 基础篇 03 探究应用生命周期
iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本 ...
- iOS系列 基础篇 04 探究视图生命周期
iOS系列 基础篇 04 探究视图生命周期 视图是应用的一个重要的组成部份,功能的实现与其息息相关,而视图控制器控制着视图,其重要性在整个应用中不言而喻. 以视图的四种状态为基础,我们来系统了解一下视 ...
- QF——iOS程序运行原理(APP的生命周期)
iOS程序的运行原理: main.m: 1. main.m 主函数是所有程序的入口函数. 2. 在main函数里是UIApplicationMain函数,开启了一个无限循环,以监听该应用. 该UIAp ...
- iOS程序执行顺序和UIViewController 的生命周期(整理)
说明:此文是自己的总结笔记,主要参考: iOS程序的启动执行顺序 AppDelegate 及 UIViewController 的生命周期 UIView的生命周期 言叶之庭.jpeg 一. iOS程序 ...
- Xamarin.ios引用第三方SDK
引言 诚然,Xamarin是个优秀的跨平台解决方案,但毕竟还是不能将Native中所有的方法都直接实现.诸如各种第三方库,也都只有java/oc原生版本的SDK,无法直接拿过来直接使用.但,不能直接拿 ...
- IOS第12天(3,UIViewController的生命周期)
#import "HMViewController.h" @interface HMViewController () @property(nonatomic,strong)NSA ...
- iOS viewController 和 view 的创建消失生命周期总结
控制器创建的生命周期 1. 如果从stroryBoard 中产生一个controller,那么会先调用initWithCoder:, awakeFromNib, loadView,viewDidLoa ...
- ios --也是在B页面的生命周期设置如下代码。方法一是直接关闭和激活侧滑手势,方法二则是B遵循协议UIGestureRecognizerDelegate,设置侧滑交互代理,重写手势方法。
@property (weak, nonatomic) id<UIGestureRecognizerDelegate> restoreInteractivePopGestureDelega ...
- IOS storyboard(控件器的 生命周期)
@interface NJTwoViewController () @end @implementation NJTwoViewController // 当控制器的view加载完毕就调用 - (vo ...
随机推荐
- SP2713 GSS4 - Can you answer these queries IV
题目大意 \(n\) 个数,和在\(10^{18}\)范围内. 也就是\(\sum~a_i~\leq~10^{18}\) 现在有两种操作 0 x y 把区间[x,y]内的每个数开方,下取整 1 x y ...
- 我的web安全工程师学习之路——规划篇
据网上收集的web安全工程师需要掌握哪些技能,职位要求以及如何入门,加上学习网易推出的web安全工程师微专业课程,为了进一步学习,所以给自己做了一些小小规划,也希望给同样想成为web安全工程师的同仁们 ...
- mpvue 小程序应用拖动排序
<template> <div> <div style="width:90%;height:40px;line-height:40px;margin:auto; ...
- SQL-Error-1
错误描述:String or binary data would be truncated. 原因:字段长度不够
- 江西财经大学第一届程序设计竞赛 C
链接:https://www.nowcoder.com/acm/contest/115/C来源:牛客网 题目描述 决赛圈还剩下两个人,“伏地魔”XDD和跑毒进圈的FZL,XDD拿着狙击枪AWM瞄准并准 ...
- 1040 有几个PAT (25 分
字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位(P),第 4 位(A),第 6 位(T):第二个 PAT 是第 3 位(P),第 4 位(A),第 6 位(T). 现 ...
- SQL注入工具sqlmap的注入过程记录
1.sqlmap的get注入 假设目标是 https://www.baidu.com/news.php?id=1&data=2 sqlmap语句 列库 sqlmap.py -u "h ...
- Spring Cloud 没移动完 到Ribbon
一 Spring Cloud各组件简要介绍 1. Eureka 注册中心. 帮助我们做服务的注册.服务的发现以及接口的调用 2. Ribbo 请求负载均衡 3. Zuul 网关.做合法性的校验. ...
- sublime快捷键:快速查找函数和快速匹配括号
1. 快速查找函数 Ctrl+R 2. 快速匹配括号 光标置于括号中,Ctrl+Shift+M 快速匹配括号内容,再按下 Ctrl+Shift+[ 折叠代码, Ctrl+Shift+] 展开代码. 3 ...
- .net core项目中引用.net framework封装的dll库
https://blog.csdn.net/sharphou/article/details/80746551 A----------如何安装IIS [Server Hosting]------- ...