庸置疑,以下的所有操作必须建立在已越狱的iPhone手机上。
02
首先,在建立工程之后我们要引入一个名为CoreTelephony.framework的框架,他是一个是一个有关电话、短信和邮件通讯的框架。
03
注:使用4.x的SDK的开发者可以清楚的看到这个框架中有关电话和运营商的各种类(/Developer/Platforms /iPhoneOS.platform/Developer/SDKs/iPhoneOS4.x.sdk/System/Library /Frameworks/CoreTelephony.framework),而其在3.x的SDK中是一个私有框架(/Developer /Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.x.sdk/System /Library/PrivateFrameworks/CoreTelephony.framework),我们可以使用
class
-dump(目前最 新版本为3.3.4)去dump去得到那些有关的类。
04
接着,我们要引入一些没有在文档中出现,但又确实存在的函数,由于我们的实现文件为.mm文件所以引入时最好使用
extern
"C"
方式:
05
extern
"C"
CFNotificationCenterRef CTTelephonyCenterGetDefault(
void
);
06
extern
"C"
void
CTTelephonyCenterAddObserver(CFNotificationCenterRef center,
const
void
*observer, CFNotificationCallback callBack, CFStringRef name,
const
void
*object, CFNotificationSuspensionBehavior suspensionBehavior);
07
extern
"C"
void
CTTelephonyCenterRemoveObserver(CFNotificationCenterRef center,
const
void
*observer, CFStringRef name,
const
void
*object);
08
extern
"C"
NSString *CTCallCopyAddress(
void
*, CTCall *call);
09
extern
"C"
void
CTCallDisconnect(CTCall *call);
10
extern
"C"
void
CTCallAnswer(CTCall *call);
11
extern
"C"
void
CTCallAddressBlocked(CTCall *call);
12
extern
"C"
int
CTCallGetStatus(CTCall *call);
13
extern
"C"
int
CTCallGetGetRowIDOfLastInsert(
void
);
14
以上这些方法都在CoreTelephony这个库中实现,这也是为什么我们要一开始就引入这个框架了。
15
第三步:我们就要是要在SpringBaord启动之后就将我们的回调函数注册到CTTelephonyCenter这个消息中心,注册我们就放在Hook到SpringBoard的applicationDidFinishLaunching:的那个函数中去:
16
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, &callBack, CFSTR(
"kCTCallStatusChangeNotification"
), NULL, CFNotificationSuspensionBehaviorHold);
17
18
这里用到的CTTelephonyCenterAddObsever这个函数基本上与文档中给出的CFNotificationCenterAddObserver这个函数一样,所以我们可以参照后者对前者进行使用(经我测试用法基本相同)。
19
最后,就是对回调函数的实现:
20
static
void
callBack(CFNotificationCenterRef center,
void
*observer, CFStringRef name,
const
void
*object, CFDictionaryRef userInfo) {
21
if
([(NSString *)name isEqualToString:@
"kCTCallStatusChangeNotification"
]) {
22
CTCall *call = (CTCall *)[(NSDictionary *)userInfo objectForKey:@
"kCTCall"
];
23
NSString *caller = CTCallCopyAddress(NULL, call);
24
CTCallDisconnect(call);
25
CTCallAnswer(call);
26
CTCallGetStatus(CTCall *call);
27
CTCallGetGetRowIDOfLastInsert(
void
);
28
}
29
}
30
以上代码经测试可以使用:
31
测试机型:iPhone 3GS
32
系统版本:iOS 4.3.3
33
手机状态:已越狱
34
测试结果:Perfect!
35
36
下面我们讲一下如何捕获和拦截短信:
37
首先我们需要一个名为ChatKit的基础框架,它是一个私有的基础框架。从这个框架中我们可以获得如下消息和键值:
38
CKServiceMessageReceivedNotification
39
CKServiceMessageSentNotification
40
CKMessageKey
41
与上面的电话消息一样,我们在SpringBoard启动后在CTTelephonyCenter中注册以上的消息:
42
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, callBack, CKServiceMessageReceivedNotification, NULL, CFNotificationSuspensionBehaviorDrop);
43
然后就是回调函数的实现:
44
static
void
callBack(CFNotificationCenterRef center,
void
*observer, CFStringRef name,
const
void
*object, CFDictionaryRef userInfo) {
45
46
CKSMSMessage *message = [(NSDictionary *)userInfo objectForKey:CKMessageKey];
47
48
NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
49
if
([systemVersion hasPrefix:@
"4."
]) {
50
[[objc_getClass(
"SBSMSManager"
) sharedSMSManager] deleteMessage:message deleteConversationIfEmpty:YES];
51
}
else
if
([systemVersion hasPrefix:@
"5."
]) {
52
NSString *address = [message address];
53
CKConversation *conversation = [message conversation];
54
CKSMSService *service = (CKSMSService *)[conversation service];
55
[service deleteMessage:message fromConversation:conversation];
56
NSUInteger count = 0;
57
sqlite3 *database = NULL;
58
if
(sqlite3_open(SMSDATABASE, &database) == SQLITE_OK) {
59
char
*sql = sqlite3_mprintf(
"SELECT COUNT(*) FROM message WHERE address = \'%s\'"
, [address UTF8String]);
60
sqlite3_stmt *statement = NULL;
61
if
(sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
62
while
(sqlite3_step(statement) == SQLITE_ROW) {
63
count = (NSUInteger)sqlite3_column_int(statement, 0);
64
}
65
sqlite3_finalize(statement);
66
}
67
sqlite3_free(sql);
68
if
(!count) {
69
sql = sqlite3_mprintf(
"DELETE FROM group_member WHERE address = \'%s\'"
, [address UTF8String]);
70
sqlite3_exec(database, sql, NULL, NULL, NULL);
71
sqlite3_free(sql);
72
}
73
74
sqlite3_close(database);
75
}
76
}
77
}
78
以上代码经测试有效,且可以在每个会话中没有内容的时候删除该空会话,但是iOS4中会弹出一个空的短信提醒框,所以感觉不是很完美。