【问题标题】:how to get the message when receiving the "kCTMessageReceivedNotification" notification on IOS5IOS5收到“onMessageReceived Notification”通知时如何获取消息
【发布时间】:2012-05-27 18:16:22
【问题描述】:

使用 ios4.x 我可以在收到“kCTMessageReceivedNotification”通知时使用下面的代码来获取消息

CTTelephonyCenterAddObserver( ct, NULL, callback,NULL,NULL, CFNotificationSuspensionBehaviorHold); 

if ([notifyname isEqualToString:@"kCTMessageReceivedNotification"])//receive message
    {

        NSDictionary *info = (NSDictionary *)userInfo;
        CFNumberRef msgID = (CFNumberRef)[info objectForKey:@"kCTMessageIdKey"];
        int result;
        CFNumberGetValue((CFNumberRef)msgID, kCFNumberSInt32Type, &result);   
        Class CTMessageCenter = NSClassFromString(@"CTMessageCenter");
        id mc = [CTMessageCenter sharedMessageCenter];
        id incMsg = [mc incomingMessageWithId: result];}

但是使用 ios5 我不能这样做,因为 incMsg 是 nil,所以我该怎么做才能得到消息?

谢谢

【问题讨论】:

  • 是的,我看到此消息“未知 CommCenter [31] :删除收到的消息 2147483648”在我的通知处理程序开始运行之前弹出。就像(新的 iOS 5)通知中心收到消息后立即清除消息一样。我也试过打电话给[mc allIncomingMessages],它完全是空的。
  • 那你知道我怎样才能得到消息吗?我还没有解决它。谢谢。

标签: iphone ios5 sms jailbreak


【解决方案1】:
【解决方案2】:

这是我发现的……

仅查看转储的私有 API,ChatKit.framework 似乎可以提供帮助。看一眼 CKSMSService.h

CKMadridService.h 用于 iMessage 消息。

我确实很快尝试将我自己的方法混入,CKSMSService 中的几个方法:

- (void)_receivedMessage: (id)arg1 replace:(BOOL)arg2 replacedRecordIdentifier:(int)arg3 postInternalNotification:(BOOL)arg4;

- (void)_receivedMessage: (id)arg1 replace:(BOOL)arg2 postInternalNotification:(BOOL)arg3;

但在 iOS 5.0.1 上,我没有看到其中任何一个被调用(也许是我的错误?)。因此,我尝试直接从 sqlite SMS 数据库中获取消息。注意...我没有构建完整的应用程序来注册通知。我假设您获取kCTMessageReceivedNotification 的代码没问题……它只是不再给您短信内容。因此,如果您将以下代码放入通知处理程序中,您应该能够看到消息文本:

- (NSString *) mostRecentSMS  { 
    NSString *text = @"";

    sqlite3 *database;
    if(sqlite3_open([@"/private/var/mobile/Library/SMS/sms.db" UTF8String], &database) == SQLITE_OK) {
        sqlite3_stmt *statement;

        // iOS 4 and 5 may require different SQL, as the .db format may change
        const char *sql4 = "SELECT text from message ORDER BY rowid DESC";  // TODO: different for iOS 4.* ???
        const char *sql5 = "SELECT text from message ORDER BY rowid DESC";

        NSString *osVersion =[[UIDevice currentDevice] systemVersion];         
        if([osVersion hasPrefix:@"5"]) {
            // iOS 5.* -> tested
            sqlite3_prepare_v2(database, sql5, -1, &statement, NULL);
        } else {
            // iOS != 5.* -> untested!!!
            sqlite3_prepare_v2(database, sql4, -1, &statement, NULL);
        }

        // Use the while loop if you want more than just the most recent message
        //while (sqlite3_step(statement) == SQLITE_ROW) {
        if (sqlite3_step(statement) == SQLITE_ROW) {
            char *content = (char *)sqlite3_column_text(statement, 0);
            text = [NSString stringWithCString: content encoding: NSUTF8StringEncoding];
            sqlite3_finalize(statement);
        }

        sqlite3_close(database);
    }
    return text;
}    

现在,请确保此应用已安装在 /Applications/ 中。如果您只是构建此应用程序,并使用 Xcode 正常安装,由于应用程序沙盒,您将在打开 sqlite 数据库时收到权限被拒绝错误。

我的代码 sn-p 只是获取最新的文本内容。 Here's an example of doing a little more with the database。看QuerySMS方法。

另外,这是 sms.dblink on the database format。你可以在那里找到你需要的其他东西。或者,只需将 sms.db 复制到您的计算机,然后使用 Firefox SQLiteManager plugin 之类的内容进行浏览。祝你好运!

更新:来自question I posted on multi-process SQLite thread safety on iOS的一些信息

【讨论】:

  • 非常感谢。我会试一试的。
  • @dustdn,另外,由于我只构建了对你不起作用的应用程序的一半(获取短信内容),我不能 100% 确定如果你使用是否有任何时间问题收到通知后立即使用此代码。我仍然不是 100% 清楚 sqlite 在 iOS 上是否是线程安全的。我运行了代码int safe = sqlite3_threadsafe(); 并得到了一个非零结果(2),但我不确定这是否意味着它是线程安全的。无论如何,您可能需要使用一点延迟,或者观察 sqlite 调用的返回值以检查 SQLITE_MISUSE,我认为这表明存在线程安全问题。
  • 如果有帮助,我相信您可以使用 iOS equiv 触发该代码。 Mac OS X 的启动守护程序的“WatchPaths”选项,并且仅启动目录(即 SMS 目录)中的内容已更改。我还没有测试它(我使用了一个 cron 作业),但我找到了一些示例代码的链接:developer.apple.com/library/ios/#samplecode/DocInteraction/…
  • @Nate 很好的发现,虽然苹果警察会允许一个可以读取市场上用户文本的应用程序,假设这只是一个更大的应用程序的一部分,而不是整个应用程序?
  • @Dnaso,no,但这并不重要。这甚至无法在 App Store 应用程序中正常运行,因为应用程序商店应用程序是沙盒,安装在 /var/mobile/Applications 中。他们将无法读取 sms.db 文件。因此,这不仅仅是 Apple 的审查人员会允许什么的问题。限制是技术性的。
【解决方案3】:

我设法在未越狱的 iOS8 设备上收到最后一条消息:

  1. ChatKit 标头中获取CKDBMessage.h 并将文件添加到您的项目中。
  2. 通过CTTelephonyCenterAddObserver注册kCTMessageReceivedNotification
  3. 使用此函数获取最后收到的消息的信息:

    void SmsReceived()
    {
        NSLog(@"GOT SMS");
    
        //open IMDPersistence framework
        void *libHandle =     dlopen("/System/Library/PrivateFrameworks/IMDPersistence.framework/IMDPersistence", RTLD_NOW);
    
        //make/get symbol from framework + name
        IMDMessageRecordGetMessagesSequenceNumber = (int (*)())dlsym(libHandle, "IMDMessageRecordGetMessagesSequenceNumber");
    
        // get id of last SMS from symbol
        int lastID = IMDMessageRecordGetMessagesSequenceNumber();
        NSLog(@"%d", lastID);
    
        // close (release?) framework -> needed??
        dlclose(libHandle);
    
    
        // get message object
        dlopen("/System/Library/PrivateFrameworks/ChatKit.framework/ChatKit", RTLD_LAZY);
        Class CKDBMessageClass = NSClassFromString(@"CKDBMessage");// objc_getClass("CKDBMessage");
        CKDBMessage *msg = [[CKDBMessageClass alloc] initWithRecordID:lastID];
    
        NSString *text = msg.text;
        NSLog(@"text: %@", text);
    }
    

【讨论】:

  • 你能在 git hub 上分享项目吗?在哪里可以找到 CKDBMessage.h 以及如何注册“kCTMessageReceivedNotification”
  • 这仍然适用于 iOS 7,但我发现您在收到 kCTMessageReceivedNotification 通知后需要稍微延迟。否则你会错过刚刚收到的短信。我使用 0.1 秒的延迟,使用 [self performSelector .. afterDelay:0.1];
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多