How AIR Native Extension for iOS Access Third Party sdk Implements AppDelegate Life Cycle

Keywords: iOS xcode Unity Android

Author: Panda Fang

Source: http://www.cnblogs.com/lonkiss/p/6492385.html

Original articles, reprinted please indicate the author and origin, without permission can not be used for commercial profit-making activities

 

Last year to this year, I did several AIR Native Extension (ANE) on iOS, which was very painful. The way of ANE development has long been wasted by the predecessors' Tucao, which is much inefficient and seriously depressed kpi. After experiencing Unity's plug-in development, it's really much more refreshing and efficient.

To put it right, one of the pains is that it is difficult to achieve the life cycle of AppDelegate. As far as life cycle implementation is concerned, the ane on Android is also difficult. Write it next time. If it's convenient to make a standard iOS App on xcode to write AppDelegate, just fill in the function. But these APIs are not exposed on ANE for you to implement. Air itself is an app running on ios, and adobe implements it using delegate but not exposed to us. We use adobe air sdk as a framework relying on adobe. We can't help cursing Adobe while doing it. Now that adobe air is used, we can rely on hook s. The following article is worth reading.

Get through Android, IOS, ANE production processes - know why - Blog Channel - CSDN.NET 

Then I will quote this article for explanation.

 

Create a new objective-c file named HookUtil in xcode. xocde will generate a HookUtil.m file to delete the code in the file and copy and paste the code below. But the following code can not solve the problem, really want to know why it is still to insist on seeing how I finally solve.

  1 //
  2 //  HookUtils.m
  3 //  ResearchMethodSwizzl
  4 //
  5 //  Created by Xue Yuan on 15/4/27.
  6 //  Copyright (c) 2015 Xue Xue. 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     //Add the method to the original 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 /*Specific code to go*/
 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 /*Alipay's corresponding method*/
 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 default
 92 /*default The default does not need to be changed*/
 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

Here are some explanations about this HookUtils:
HookUtils is the implementation of the Hook mechanism of IOS, so it is suitable for all IOS development. Here we only do some processing for the Air application.  
Hook mechanism needs to get the class name of the application's implementation life cycle, so that Hook can handle it. If you are the code developed by Xcode engineering, you can easily find the class name. This applies to IOS native, Unity and so on. Cocos engine Because they all use Xcode development tools. However, Air development is based on Flash Builder, not directly related to the Xcode project. The class name CTAppDelegate of Air is found by printing the life cycle class of Air application through code. Then the code is set to be modified by other engines. Of course, you can also get it through the configuration file (Info.plist), so that the code does not need to be modified.

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

(3) You need to implement your specific code in the hooked ** method, and finally call the header file definition method (void) hookMehod:(SEL) oldSEL and Def:(SEL) defaultSEL and New:(SEL) newSEL in the +(void)load() method to achieve the purpose of Hook;

I quoted that blog above, and when I added the code, I wondered where to call it. Ask an experienced iOS developer to understand that it is not necessary to call the function in HookUtil in other functions. This class method load is the entry, as long as it is declared as a class method and named load, it will be automatically called by the system. After making ane and testing it in demo, demo that could have run flickered back after adding HookUtil to it. By observing log, hookMethod was executed. As a matter of fact, the system automatically calls these codes. The ane has not triggered instantiation through buttons in demo yet.

So I added the log to 34 lines of assert (old method); this line was hung up, the old method was null, but I didn't see what was wrong for a long time, then I suspected that 25 lines of oldClass would also be null, so I added the log NSLog (@ "old class%@), oldClass); if it was null, I would like to review that blog, maybe not CTApp Delegate. What's the name? The blog said that the class name CTAppDelegate for Air was found by printing the life cycle class of the Air application in code. So print it in hookMethod.

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

But it's still null, and then I wonder if it's too early. It is then placed in an api method of ane and triggered by a button in the application layer 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 }

Sure enough, it's no longer null, and the printed name is not CTAppDelegate, but CTAppController. My airsdk is 21, and adobe has changed its name. After changing CTAppDelegate from 25 lines of code to CTAppController, the function in delegate is called correctly and the life cycle delegate is solved.

Posted by stuartbaggs on Sun, 16 Dec 2018 20:48:04 -0800