这很棘手。苹果在这方面做出了重大改变。在 iOS 5 上这很容易,但在 iOS 6 上我还没有找到简单的方法来做到这一点。
首先,您需要使用 CTTelephonyCenter 观察 __kIMChatItemsDidChangeNotification 通知。我是在 SpringBoard 中注入的 dylib 中进行的。不确定,但这可能很重要。
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, Callback, NULL, NULL, CFNotificationSuspensionBehaviourHold);
void Callback(CFNotificationCenterRef, void*, NSString* notification, const void*, NSDictionary* userInfo)
{
if (![notification isEqualToString:@"__kIMChatItemsDidChangeNotification"])
{
return;
}
for (IMChatItem* chatItem in userInfo[@"__kIMChatItemsKey"])
{
IMMessage* msg = [chatItem message];//Incoming message object
NSString* text = [[msg text] string];//message text
NSString* sender = [[msg sender] ID];//message sender
[[IMDMessageStore sharedInstance] performBlock:^{
IMDChatRecordDeleteChatForGUID([NSString stringWithFormat:@"SMS;-;%@", sender]);
}];
}
}
最后一点非常重要。您不能只删除消息。您需要在特定的内部线程上执行此操作,否则会出现错误。这就是我使用IMDMessageStore 的原因。这是performBlock: 方法在这个特殊线程上执行块。
IMDChatRecordDeleteChatForGUID 函数可以在 IMDPersistence.framework 中找到。它会删除具有特定 GUID 的整个消息树(聊天/对话)。我找不到检索此 GUID 的方法,因此我使用 SMS sqlite 数据库中的 GUID 作为示例手动构建它。
要删除一条消息,您可以使用IMDMessageRecordDeleteMessagesForGUIDs([NSArray arrayWithObject:[msg guid]]);
IMChatItem 和IMMessage 可以在IMCore.framework 中找到。 IMDMessageStore 在 IMDaemonCore.framework 中。
这是简单的部分。现在,当您收到消息并以这种方式阻止它时,您会看到它仍然显示在 MobileSMS 应用程序中,您仍然可能会收到公告通知,您仍然会收到徽章告诉您有未读消息。但是如果您打开 SMS sqlite 数据库,您会看到该消息确实已被删除。阻止这些并不是那么容易。
- 公告。在 SpringBoard 中,您需要挂钩
BBServer 方法 publishBulletin:destinations:alwaysOnLockScreen:。第一个参数是 BBBulletin 对象。如果它是传入消息公告,则它的section 属性等于com.apple.MobileSMS。要阻止公告,只需从此方法返回,不要调用原始实现。
- MobileSMS 应用程序徽章。当有传入的 SMS 时,SpringBoard 中会加载 ChatKit.serviceBundle。您需要在
MessagesBadgeController - _madridChatRegistered: 和_madridUnreadCountChanged: 中挂钩两个方法。他们的第一个参数是NSNotification 对象,其中object 属性包含IMChat 对象。同样,只需从这些方法返回即可防止徽章更改。
- 手机短信应用。为了阻止它显示已删除的消息,我
hook了很多方法。我只给你一个清单:
SMSApplication _receivedMessage:、CKTranscriptController
_messageReceived:、CKConversationList _handleRegistryDidRegisterChatNotification:, _handleRegistryDidLoadChatNotification:, hasActiveConversations, unreadCount。 CKConversationController
_chatParticipantsChangedNotification:, updateConversationList, CKMessagesController showConversation:animate:forceToTranscript:
关于 ChatKit.serviceBundle。要挂钩它的类,您需要等待 SpringBoard 实际加载它。这是在SBPluginManager loadPluginBundle: 中完成的。捆绑标识符应等于com.apple.SMSPlugin。只有这样你才能挂钩方法。
就是这样。相当多的工作,但它工作完美 - 没有收到消息的迹象,即使消息到达时您在 MobileSMS 应用程序中也是如此。
我确信有更简单的方法可以做到这一点。有 com.apple.imagent 守护进程向各种 iOS 组件发送通知。它在 iOS 6 消息系统中非常重要。开始的好地方。