分析iphone-background源码的感悟

Posted yohunl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析iphone-background源码的感悟相关的知识,希望对你有一定的参考价值。

在2009.1.25日作者增加了 added the package structure,之前的版本都没有package文件夹的,日志号是111

还有以前版本得时候的mobilesubstrate的用法也不一样了
以前的版本:
MSHookMessage的第四个参数是必须使用的
MSHookMessage($SpringBoard, @selector(applicationDidFinishLaunching:), (IMP)&$SpringBoard$applicationDidFinishLaunching$, "bg_");

@interface SpringBoard (Backgrounder_RenamedMethods)
- (void)bg_applicationDidFinishLaunching:(id)application;
- (void)bg_dealloc;
- (void)bg_menuButtonDown:(GSEvent *)event;
- (void)bg_menuButtonUp:(GSEvent *)event;
- (void)bg__handleMenuButtonEvent;
- (void)bg_handleMenuDoubleTap;
@end

static void $SpringBoard$applicationDidFinishLaunching$(SpringBoard *self, SEL sel, id application)

...................

现在的版本改为了以下的用法模式,省去了自定义bg_applicationDidFinishLaunching的麻烦,方便了很多
HOOK(SpringBoard, applicationDidFinishLaunching$, void, id application)

...................

MSHookMessage($SpringBoard, @selector(applicationDidFinishLaunching:), &$SpringBoard$applicationDidFinishLaunching$);



图片放在才“E:/project/background/package/System/Library/CoreServices/SpringBoard.app/Default_Backgrounder.png,FSO_Backgrounder.png
HOOK(UIApplication, applicationDidResume, void)

#if 0
NSString *name = [NSString stringWithFormat:@"Backgrounder"];
if ([self respondsToSelector:@selector(addStatusBarImageNamed:removeOnExit:)])
[self addStatusBarImageNamed:name removeOnExit:YES];
else
[self addStatusBarImageNamed:name removeOnAbnormalExit:YES];
#endif
if (!backgroundingEnabled)
CALL_ORIG(UIApplication, applicationDidResume);


_UIApplication$applicationDidResume =
MSHookMessage($UIApplication, @selector(applicationDidResume), &$UIApplication$applicationDidResume);



在267版本中,使用新的mobilesubstrate提供的宏LOAG_HOOK
Class $SpringBoard = objc_getClass("SpringBoard");
LOAD_HOOK($SpringBoard, @selector(applicationDidFinishLaunching:), SpringBoard$applicationDidFinishLaunching$);
以此取代下面的
Class $SpringBoard(objc_getClass("SpringBoard"));
_SpringBoard$applicationDidFinishLaunching$ =
MSHookMessage($SpringBoard, @selector(applicationDidFinishLaunching:), &$SpringBoard$applicationDidFinishLaunching$);

在289版本中
有一个变化是Revision: 289
Author: gaizin@gmail.com
Date: 21:19:07, 2009年9月23日
Message:
Moved badge image to root of Backgrounder.app, and removed other unused images.
----
Added : /trunk/package/Applications/Backgrounder.app/badge.png (Copy from path: /trunk/package/Applications/Backgrounder.app/images/badge.png, Revision, 288)
Modified : /trunk/package/System/Library/CoreServices/SpringBoard.app/Backgrounder_Badge.png
Deleted : /trunk/package/Applications/Backgrounder.app/images/badge.png
Deleted : /trunk/package/Applications/Backgrounder.app/images/invoke_dbltap.png
Deleted : /trunk/package/Applications/Backgrounder.app/images/invoke_hold.png
Deleted : /trunk/package/Applications/Backgrounder.app/images/mode_simple.png
Deleted : /trunk/package/Applications/Backgrounder.app/images/mode_tasklist.png


NSString *identifier = [self displayIdentifier];
SBApplicationIcon *icon = [[objc_getClass("SBIconModel") sharedInstance] iconForDisplayIdentifier:identifier];
UIImageView *badgeView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Backgrounder_Badge.png"]];
[badgeView setOrigin:CGPointMake(-12.0f, 39.0f)];
[badgeView setTag:1000];
[icon addSubview:badgeView];
[badgeView release];

306日志
将hook的代码从class文件夹移到了extension文件夹, Ported to Dustin Howetts's theos build system

309日志开始
Revision: 309
Author: gaizin
Date: 13:23:23, 2010年2月16日
Message:
Converted to use Logos preprocessor.
----
Added : /trunk/Extension/ApplicationHooks.xm (Copy from path: /trunk/Extension/ApplicationHooks.mm, Revision, 308)
Added : /trunk/Extension/SpringBoardHooks.xm (Copy from path: /trunk/Extension/SpringBoardHooks.mm, Revision, 308)
Modified : /trunk/Extension/main.mm
Deleted : /trunk/Extension/ApplicationHooks.mm
Deleted : /trunk/Extension/SpringBoardHooks.mm

从这次的对比中可以看出来
在新的预处理中
%init;
%init(GHomeHold);
我理解是他们需要结合%hook,%end,%group 来用
在代码中出现的
%init应该是预处理直接扫面代码,将原来的在初始化函数中写
Class $SpringBoard = objc_getClass("SpringBoard");
LOAD_HOOK($SpringBoard, @selector(applicationDidFinishLaunching:), SpringBoard$applicationDidFinishLaunching$);
LOAD_HOOK($SpringBoard, @selector(dealloc), SpringBoard$dealloc);
..........
给简化了
现在只要写个%init,预处理会对整个文件进行扫描,根据%hook来生成
Class $SpringBoard = objc_getClass("SpringBoard");
LOAD_HOOK($SpringBoard, @selector(applicationDidFinishLaunching:), SpringBoard$applicationDidFinishLaunching$);
LOAD_HOOK($SpringBoard, @selector(dealloc), SpringBoard$dealloc);
..........
这样的话,以下的
%init(GLockHold);也好理解了
不带参数的默认只扫描不在%group GHomeHold(可以为别的名称) 中出现的%hook,%end
//==============================================================================

%group GHomeHold
// NOTE: Only hooked when invocationMethod == BGInvocationMethodMenuShortHold

%hook SpringBoard

- (void)menuButtonDown:(GSEventRef)event

invocationTimerDidFire = NO;

if ([SBWActiveDisplayStack topApplication] != nil)
// Not SpringBoard, start hold timer
startInvocationTimer();

%orig;


- (void)menuButtonUp:(GSEventRef)event

if (invocationTimerDidFire)
// Backgrounder popup is visible; hide it
[self dismissBackgrounderFeedback];
else
cancelInvocationTimer();

%orig;


%end

%end // GHomeHold


还有%new(v@:)只能在%hook下,否则没法加上诸如$SpringBoard$之类的前缀了
%new(v@:)
- (void)invokeBackgrounder

.......

相当于之前的
static void $SpringBoard$invokeBackgrounder(SpringBoard *self, SEL sel)

............


%orig;只能用在%hook中的函数中,否则预处理不知道如何加诸如CALL_ORIG(SpringBoard之类的前缀了
HOOK(SpringBoard, dealloc, void)

[bgEnabledApps release];
[activeApps release];
[displayStacks release];
CALL_ORIG(SpringBoard, dealloc);

变为了
- (void)dealloc

[bgEnabledApps release];
[activeApps release];
[displayStacks release];
%orig;




对于HOOK的使用有一点要注意
好似最多只能hook一个参数的函数
对于没有参数的函数的hook例子
LOAD_HOOK($SBApplication, @selector(exitedCommon), SBApplication$exitedCommon);
实现是HOOK(SBApplication, exitedCommon, void)

对于有一个参数的(注意有一个 :)
LOAD_HOOK($SBApplication, @selector(launchSucceeded:), SBApplication$launchSucceeded$);
实现的参数
HOOK(SBApplication, launchSucceeded$, void, BOOL unknownFlag)

对于有两个参数的
Class _$NSURL = [NSURL class];
MSHookMessageEx(_$NSURL,@selector(initWithString:),(IMP)replaced_NSURL_initWithString_,(IMP *)&original_NSURL_initWithString_);
MSHookMessageEx(_$NSURL,@selector(initWithString:relativeToURL:),(IMP)replaced_NSURL_initWithString_relativeToURL_, (IMP *)

&original_NSURL_initWithString_relativeToURL_);
MSHookMessageEx(_$NSURL,@selector(absoluteString),(IMP)replaced_NSURL_absoluteString_,(IMP *)&original_NSURL_absoluteString_);

id replaced_NSURL_initWithString_relativeToURL_(NSURL *self, SEL _cmd, NSString *URLString, NSURL* baseURL)
..........

id replaced_NSURL_initWithString_(NSURL *self, SEL _cmd, NSString *URLString)
.........

id replaced_NSURL_absoluteString_(NSURL *self, SEL _cmd)
............

 

 

background使用的编译系统是一个叫TheOS的,

https://github.com/DHowett/theos/tree/master/extras

在另外一个人的git上,提供了一个基于theos的更好用的一个编译环境

https://github.com/rpetrich/theos

使用theos,那么就可以使用上面的,并且它上面有简单的使用说明!!!

%Hook,%new。。。。。。。

 

 

https://github.com/rpetrich这个人的网站上有很多非常有用的iphone源码!!!!

以上是关于分析iphone-background源码的感悟的主要内容,如果未能解决你的问题,请参考以下文章

跟大家聊聊我们为什么要学习源码?学习源码对我们有用吗?(源码感悟)

mysql社区版可以在公司用吗,工作感悟

妙味课堂jquery源码分析视频教程 jquery源码逐行分析分析

UCOSIII空闲任务的作用及源码分析

String源码学习感悟

对于学习Spring源码的感悟