[轉載]使用 CTTeleyphonyCenter 截獲來去電及短信消息


轉自: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中會彈出一個空的短信提醒框,因此感受不是很完美。

相關文章
相關標籤/搜索