ChatKit.framework

From iPhone Development Wiki
Jump to: navigation, search
ChatKit.framework
Private Framework
Availabile 3.0 – present
Class Prefix CK

ChatKit is a framework designed for handling SMS, iMessage and MMS, and the views for these. iMessage was introduced in iOS 5 under the codename CKMadridService but has since been replaced and fully integrated into ChatKit.

Contents

Listener Capabilities

As of iOS 7, things a process can do with this framework is limited by imagent, the backend daemon that processes calls from ChatKit.framework. Imagent uses a property called listener capabilities to determine what each process can do.

Enum Declaration

enum FZListenerCapabilities {
    Status = 1 << 0,
    Notifications = 1 << 1,
    Chats = 1 << 2,
    VC = 1 << 3,
    AVChatInfo = 1 << 4,
    AuxInput = 1 << 5,
    VCInvitations = 1 << 6,
    Lega = 1 << 7,
    Transfers = 1 << 8,
    Accounts = 1 << 9,
    BuddyList = 1 << 10,
    ChatObserver = 1 << 11,
    SendMessages = 1 << 12,
    MessageHistory = 1 << 13,
    IDQueries = 1 << 14,
    ChatCounts = 1 << 15
};

Default Values for Some Common Processes

  • com.apple.springboard
    Status, Notifications, Accounts, Modify Read State, Chat Counts
  • com.apple.MobileSMS
    Status, Notifications, Chats, Transfers, Accounts, ID Queries

Reading a Message

First things first: When I speak about iMessage I include SMS as well.

ChatKit performs some actions when a message is read, but you as a Tweak developer can do even more.

When you read a message in the iMessage App, the notification CKConversationMessageReadNotification is posted.

We can simply listen to this notification using

[[NSNotificationCenter defaultCenter] addObserver:myTarget selector:@selector(readAwesomeMessage:) name:@"CKConversationMessageReadNotification" object:nil];

So whenever the notification is posted, we can control it in the -(void)readAwesomeMessage:(NSNotification *)notification; method.

By looking at the NSNotification documentation we can see that every NSNotification object has an -(NSDictionary *)userInfo method that returns information which was sent with the notification. This method can return NULL if there is no information available.

From my findings I can say that the userInfo dictionary contains a CKIMMessage object for the key CKMessageKey so basically

-(void)readAwesomeMessage:(NSNotification *)notif {
 
CKIMMessage *msg = notif.userInfo[@"CKMessageKey"]; 
//CKIMMessage *msg = [[notif userInfo] objectForKey:@"CKMessageKey"]; -->long way that does the same as the line above
 
//...
}

Now you have a CKIMMessage object to use. You should of course verify the object is not NULL before you try to access properties of it. You can have a quick look at CKIMMessage.h and you directly see that it contains a lot of information to use:

@property (nonatomic,retain) IMMessage * IMMessage; //another message object
@property (nonatomic,readonly) NSString * guid; //message id
@property (nonatomic,readonly) NSString * address; //email address to which the message was sent
@property (nonatomic,readonly) NSAttributedString * subject; //subject of the conversation
@property (assign,nonatomic) CKConversation * conversation; //get the conversation in which the message was read. contains a lot of information as well
@property (nonatomic,readonly) NSArray * parts; //a message contains of different parts (CKMessagePart objects)
@property (nonatomic,readonly) NSArray * recipients; //who are in the conversation?
@property (nonatomic,readonly) NSDate * date; //date of reading
@property (nonatomic,readonly) NSDate * timeRead; //time exactly of reading
@property (nonatomic,readonly) CKEntity * sender; //who sent the message? it contains a lot of information as well
@property (nonatomic,readonly) BOOL isiMessage; //which type of message?
@property (nonatomic,readonly) BOOL isSMS; //which type of message?
@property (nonatomic,readonly) BOOL isOutgoing; //are you sending it?
@property (nonatomic,readonly) BOOL isFromMe; //same
@property (nonatomic,readonly) BOOL hasAttachments; //does it contain images or videos?
@property (nonatomic,readonly) BOOL isToEmailAddress; 
...

We will focus on the message parts a little bit more. It allows you to go through the entire message and filter out different types of parts (Text, Images, Videos).

-(void)readAwesomeMessage:(NSNotification *)notif {
 
CKIMMessage *msg = notif.userInfo[@"CKMessageKey"]; 
 
if (msg) { //avoid to have an EXC_BAD_ACCESS exception - we avoid trying to access a NULL object
 
for (CKMessagePart *part in [msg parts]) { //look through all parts of the message - we can safely do that because no one writes messages with thousands of parts.
 
//have a look at http://developer.limneos.net/?framework=ChatKit.framework&header=CKMessagePart.h
//write your code here what you do with each message part.
 
} 
 
} 
 
}

As you can see, it is very easy to implement your own code when the user reads a message. If you want to find out more about the notification's userInfo, you can log it easily:

-(void)readAwesomeMessage:(NSNotification *)notif {
 
for (NSString *key in [notification.userInfo allKeys]) {
    id value = [notif.userInfo objectForKey:key];
    NSLog(@"Class: %@ - Value : %@",[value class],value);
}
 
}

This should pretty much print all what is in the userInfo dictionary to the syslog.

Sending a Message in iOS 7

As of iOS 7, you can use something like the following code to send a message programatically. It will automatically decide whether to send as an SMS or iMessage:

//Get the shared conversation list
CKConversationList* conversationList = [CKConversationList sharedConversationList];
//Get the conversation for an address
CKConversation* conversation = [conversationList conversationForExistingChatWithAddresses:[NSArray arrayWithObjects:@"11111111", nil]];
//Make a new composition
NSAttributedString* text = [[NSAttributedString alloc] initWithString:message[@"reply"]];
CKComposition* composition = [[CKComposition alloc] initWithText:text subject:nil];
//A new message from the composition
CKMessage* smsMessage = [conversation newMessageWithComposition:composition addToConversation:YES];
//And finally, send the message in the conversation
[conversation sendMessage:smsMessage newComposition:YES];

Note that this will only work from the MobileSMS process, as [CKConversationList sharedConversationList] is null in other processes.

Useful Links