轉自:http://www.cnblogs.com/OtionSky/archive/2011/11/10/iPhone_TelephoneCenter.html html
無庸置疑,如下的全部操做必須創建在已越獄的iPhone手機上。 sql
首先,在創建工程以後咱們要引入一個名爲CoreTelephony.framework的框架,他是一個是一個有關電話、短信和郵件通信的框架。 數據庫
注:使用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去獲得那些有關的類。 app
接着,咱們要引入一些沒有在文檔中出現,但又確實存在的函數,因爲咱們的實現文件爲.mm文件因此引入時最好使用extern "C"方式: 框架
extern "C" CFNotificationCenterRef CTTelephonyCenterGetDefault(void); // 得到 TelephonyCenter (電話消息中心) 的引用
extern "C" void CTTelephonyCenterAddObserver(CFNotificationCenterRef center, const void *observer, CFNotificationCallback callBack, CFStringRef name, const void *object, CFNotificationSuspensionBehavior suspensionBehavior);
extern "C" void CTTelephonyCenterRemoveObserver(CFNotificationCenterRef center, const void *observer, CFStringRef name, const void *object);
extern "C" NSString *CTCallCopyAddress(void *, CTCall *call); //得到來電號碼
extern "C" void CTCallDisconnect(CTCall *call); // 掛斷電話
extern "C" void CTCallAnswer(CTCall *call); // 接電話
extern "C" void CTCallAddressBlocked(CTCall *call);
extern "C" int CTCallGetStatus(CTCall *call); // 得到電話狀態 撥出電話時爲3,有呼入電話時爲4,掛斷電話時爲5
extern "C" int CTCallGetGetRowIDOfLastInsert(void); // 得到最近一條電話記錄在電話記錄數據庫中的位置 函數
以上這些方法都在CoreTelephony這個庫中實現,這也是爲何咱們要一開始就引入這個框架了。 測試
第三步:咱們就要是要在SpringBaord啓動以後就將咱們的回調函數註冊到CTTelephonyCenter這個消息中心,註冊咱們就放在Hook到SpringBoard的applicationDidFinishLaunching:的那個函數中去: spa
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, &callBack, CFSTR("kCTCallStatusChangeNotification"), NULL, CFNotificationSuspensionBehaviorHold);
這裏用到的CTTelephonyCenterAddObsever這個函數基本上與文檔中給出的CFNotificationCenterAddObserver這個函數同樣,因此咱們能夠參照後者對前者進行使用(經我測試用法基本相同)。 orm
最後,就是對回調函數的實現: server
static void callBack(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
if ([(NSString *)name isEqualToString:@"kCTCallStatusChangeNotification"]) {
CTCall *call = (CTCall *)[(NSDictionary *)userInfo objectForKey:@"kCTCall"];
NSString *caller = CTCallCopyAddress(NULL, call); // caller 即是來電號碼
CTCallDisconnect(call); // 掛斷電話
CTCallAnswer(call); // 接電話
CTCallGetStatus(CTCall *call); // 得到電話狀態 撥出電話時爲3,有呼入電話時爲4,掛斷電話時爲5
CTCallGetGetRowIDOfLastInsert(void); // 得到最近一條電話記錄在電話記錄數據庫(call_history.db)中的位置(ROWID)
}
}
以上代碼經測試能夠使用:
測試機型:iPhone 3GS
系統版本:iOS 4.3.3
手機狀態:已越獄
測試結果:Perfect!
下面咱們講一下如何捕獲和攔截短信:
首先咱們須要一個名爲ChatKit的基礎框架,它是一個私有的基礎框架。從這個框架中咱們能夠得到以下消息和鍵值:
CKServiceMessageReceivedNotification
CKServiceMessageSentNotification
CKMessageKey
與上面的電話消息同樣,咱們在SpringBoard啓動後在CTTelephonyCenter中註冊以上的消息:
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, callBack, CKServiceMessageReceivedNotification, NULL, CFNotificationSuspensionBehaviorDrop);
而後就是回調函數的實現:
static void callBack(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
// 經過以上提到的那個鍵值CKMessageKey咱們能夠得到一個類型爲CKSMSMessage的 // message, 這個CKSMSMessage也定義在ChatKit這個框架中。message 將爲咱們提 // 供一個短信的全部屬性和內容,而後咱們就能夠對該短信進行操做了。
CKSMSMessage *message = [(NSDictionary *)userInfo objectForKey:CKMessageKey];
// 在各類操做中刪除操做是最複雜的,由於它涉及到了系統短信數據庫的操做,且各個iOS版本也有不一樣。下面咱們說一下iOS4和iOS5中的短信刪除。
NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
if ([systemVersion hasPrefix:@"4."]) {
[[objc_getClass("SBSMSManager") sharedSMSManager] deleteMessage:message deleteConversationIfEmpty:YES];
} else if ([systemVersion hasPrefix:@"5."]) {
NSString *address = [message address];
CKConversation *conversation = [message conversation];
CKSMSService *service = (CKSMSService *)[conversation service];
[service deleteMessage:message fromConversation:conversation];
NSUInteger count = 0;
sqlite3 *database = NULL;
if (sqlite3_open(SMSDATABASE, &database) == SQLITE_OK) {
char *sql = sqlite3_mprintf("SELECT COUNT(*) FROM message WHERE address = \'%s\'", [address UTF8String]);
sqlite3_stmt *statement = NULL;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
count = (NSUInteger)sqlite3_column_int(statement, 0);
}
sqlite3_finalize(statement);
}
sqlite3_free(sql);
if (!count) {
sql = sqlite3_mprintf("DELETE FROM group_member WHERE address = \'%s\'", [address UTF8String]);
sqlite3_exec(database, sql, NULL, NULL, NULL);
sqlite3_free(sql);
}
sqlite3_close(database);
}
}
}
以上代碼經測試有效,且能夠在每一個會話中沒有內容的時候刪除該空會話,可是iOS4中會彈出一個空的短信提醒框,因此感受不是很完美。