你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 利用ios的hook機制實現adobe air ios ane下appdelegate的動態替換

利用ios的hook機制實現adobe air ios ane下appdelegate的動態替換

編輯:IOS開發綜合

開發背景

利用adobe air開發完游戲後,需要針對ios或者android平台進行支付、推送的sdk接入,本文可以用來徹底解決ios平台下delegate生命周期幾個回調函數的調用,實現原生的推送、支付功能的接入


hook知識背景

(objc裡的Method Swizzling,本節內容轉自http://blog.csdn.net/yiyaaixuexi)


在Objective-C中調用一個方法,其實是向一個對象發送消息,查找消息的唯一依據是selector的名字。利用Objective-C的動態特性,可以實現在運行時偷換selector對應的方法實現,達到給方法掛鉤的目的。
每個類都有一個方法列表,存放著selector的名字和方法實現的映射關系。IMP有點類似函數指針,指向具體的Method實現。

\


我們可以利用 method_exchangeImplementations 來交換2個方法中的IMP,
我們可以利用 class_replaceMethod 來修改類,
我們可以利用 method_setImplementation 來直接設置某個方法的IMP,
……
歸根結底,都是偷換了selectZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcrXESU1Qo6zI58/CzbzL+cq+o7o8YnI+CjwvcD4KPHA+PGltZyBzcmM9"/uploadfile/Collfiles/20141111/2014111108225471.png" alt="\">


實現思路

1、在MDChangeDelegateHelper類加載階段就對adboe air的appdelegate類進行方法hook,確保在adobe air的appdelegate在創建前替換成我們新實現的類

2、需要3個SEL,

一個AppDelegate原SEL:oldSEL,

一個MDChangeDelegateHelper的默認SEL:defaultSEL,用於為原appdelegate添加默認的原oldSEL

一個MDChangeDelegateHelper的目標SEL:newSEL

方法替換思路:

\

3、替換後對應的sel關系為

oldSEL -- newMethod

newSEL -- oldMethod

所以當對應的appdelegate方法被調用時,

oldSEL找到了newMethod的實現,newMethod的實現在MDChangeDelegateHelper.m內的hookedxxx方法

在newMethold中調用了newSEL,newSEL指向oldMethod,實現了原流程的兼容


代碼實現

//
//  MDChangeDelegateHelper.m
//  ChangeDelegateDemo
//
//  Created by ashqal on 14-10-31.
//  Copyright (c) 2014年 moredoo. All rights reserved.
//

#import "MDChangeDelegateHelper.h"
#import 

#import 

void hookMethod(SEL oldSEL,SEL defaultSEL, SEL newSEL)
{
    //CTAppController
    Class aClass = objc_getClass("CTAppController");
    if ( aClass == 0 )
    {
        NSLog(@"!!!!!!!!!!!!!did not find adobe class!");
        return;
    }
    Class bClass = [MDChangeDelegateHelper class];
    //把方法加給aClass
    class_addMethod(aClass, newSEL, class_getMethodImplementation(bClass, newSEL),nil);
    class_addMethod(aClass, oldSEL, class_getMethodImplementation(bClass, defaultSEL),nil);
    
    Method oldMethod = class_getInstanceMethod(aClass, oldSEL);
    assert(oldMethod);
    Method newMethod = class_getInstanceMethod(aClass, newSEL);
    assert(newMethod);
    method_exchangeImplementations(oldMethod, newMethod);
  
}




@implementation MDChangeDelegateHelper




+ (void)load
{
    NSLog(@"MDChangeDelegateHelper load");
    //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(createStarterNotificationChecker:)
                                                 //name:@"UIApplicationWillFinishLaunchingNotification" object:nil];
    //[self changeDelegate];
    
    
    hookMethod( @selector(application:didFinishLaunchingWithOptions:)
               ,@selector(defaultApplication:didFinishLaunchingWithOptions:)
               ,@selector(hookedApplication:didFinishLaunchingWithOptions:)
               );
    hookMethod( @selector(application:handleOpenURL:)
               , @selector(defaultApplication:handleOpenURL:)
               , @selector(hookedApplication:handleOpenURL:)
               );
    hookMethod(@selector(application:openURL:sourceApplication:annotation:)
               , @selector(defaultApplication:openURL:sourceApplication:annotation:)
               , @selector(hookedApplication:openURL:sourceApplication:annotation:));
    
    hookMethod(@selector(application:supportedInterfaceOrientationsForWindow:)
               , @selector(defaultApplication:supportedInterfaceOrientationsForWindow:)
               , @selector(hookedApplication:supportedInterfaceOrientationsForWindow:)
               );
    hookMethod(@selector(applicationDidBecomeActive:)
               , @selector(defaultApplicationDidBecomeActive:)
               , @selector(hookedApplicationDidBecomeActive:)
               );
    
    hookMethod(@selector(init)
               , @selector(init)
               , @selector(hookedInit)
               );
}


-(BOOL)hookedApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic
{
    
    NSLog(@"hooked didFinishLaunchingWithOptions");
    [self hookedApplication:application didFinishLaunchingWithOptions:dic];
    return YES;
}

-(id)hookedInit
{
    NSLog(@"hooked init!!!");
    return [self hookedInit];
}




- (BOOL)hookedApplication:(UIApplication *)application handleOpenURL:(NSURL *)url {
    
    NSLog(@"hooked handleOpenURL");
    [self hookedApplication:application handleOpenURL:url];
    return YES;
}

- (BOOL)hookedApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    NSLog(@"hooked openURL sourceApplication annotation");
    [self hookedApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation];
    return YES;
}

- (NSUInteger) hookedApplication:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    NSLog(@"hooked supportedInterfaceOrientationsForWindow");
    [self hookedApplication:application supportedInterfaceOrientationsForWindow:window ];
    return 0;
}

- (void)hookedApplicationDidBecomeActive:(UIApplication *)application
{
    [self hookedApplicationDidBecomeActive:application];
    NSLog(@"hooked applicationDidBecomeActive");
}


- (BOOL)defaultApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)dic{ return YES;}
- (BOOL)defaultApplication:(UIApplication *)application handleOpenURL:(NSURL *)url{return YES;}
- (BOOL)defaultApplication:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{return YES;}
- (NSUInteger) defaultApplication:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{return 0;}
- (void)defaultApplicationDidBecomeActive:(UIApplication *)application{}
- (id)init
{
    self = [super init];
    if (self) {
        
    }
    return self;
}

@end


注意點

a) 在運行時nslog出adobe air的appdelegate名字為CTAppController,所以將此類作為替換對象

b) 在對init函數進行替換時發現CTAppController沒有實現init函數,所以將默認的init函數做了基礎實現,不然無法創建實例了


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved