SimpleSample-chat users-ios

Ask tech team
From QuickBlox Developers (API docs, code samples, SDK)
Jump to: navigation, search

Contents

Sources

Project homepage on GIT — https://github.com/QuickBlox/quickblox-ios-sdk/tree/master/sample-chat

Download ZIP - https://github.com/QuickBlox/quickblox-ios-sdk/archive/master.zip


Overview

This sample demonstrates how to work with QuickBlox Chat API.
It allows you to organise group Chat & 1 to 1 chat

It gives examples of how to:

  1. Organise chat between 2 users
  2. Organise group chat


Guide: Getting Started with Chat API

Get a QuickBlox account

http://admin.quickblox.com/register

Create applications in the Admin panel

http://admin.quickblox.com/apps/new

In addition, there is this helpful 5 minute guide.

Connect QuickBlox to your application

To get the information on how to connect to the QuickBlox.framework, please, refer to the IOS-how-to-connect-Quickblox-framework page.

Add Chat to your application

Login to Chat

Note: In order to login to the chat please read the information about Chat login/password formation.

In order to use QuickBlox Chat APIs you must:

  • Create session & Sign In to QuickBlox OR just create session with user
  • Sign In to QuickBlox Chat

Please follow the lines below:

Create session with User & Sign In to QuickBlox Chat

// Create session with user
QBASessionCreationRequest *extendedAuthRequest = [QBASessionCreationRequest request];
extendedAuthRequest.userLogin = @"garry";
extendedAuthRequest.userPassword = @"garrySant88";
 
[QBAuth createSessionWithExtendedRequest:extendedAuthRequest delegate:self]; 
 
#pragma mark -
#pragma mark QBActionStatusDelegate
 
// QuickBlox queries delegate
- (void)completedWithResult:(Result *)result{
 
    // Create session result
    if(result.success && [result isKindOfClass:QBAAuthSessionCreationResult.class]){
       // You have successfully created the session
       QBAAuthSessionCreationResult *res = (QBAAuthSessionCreationResult *)result;
 
       // Sign In to QuickBlox Chat
       QBUUser *currentUser = [QBUUser user];
       currentUser.ID = res.session.userID; // your current user's ID
       currentUser.password = @"garrySant88"; // your current user's password   
 
       // set Chat delegate
       [QBChat instance].delegate = self;
 
       // login to Chat
       [[QBChat instance] loginWithUser:currentUser];
 
    }
}
 
#pragma mark -
#pragma mark QBChatDelegate
 
// Chat delegate
-(void) chatDidLogin{
    // You have successfully signed in to QuickBlox Chat
}
 
- (void)chatDidNotLogin{
 
}

Keep in mind that the QuickBlox Chat is a standard XMPP chat and you need to send presence periodically to remain available. Just create a timer that will send presence each 60 seconds:

[NSTimer scheduledTimerWithTimeInterval:60 target:[QBChat instance] selector:@selector(sendPresence) userInfo:nil repeats:YES];

Chat in background mode

As iOS doesn't provide 'true' background mode, we can't have a persistent Chat connection while iOS application is in background. The better way to handle correctly chat offline messages is to do 'Chat logout' when app goes to background and does 'Chat login' when app goes to foreground:

@implementation AppDelegate
 
// this is our AppDelegate class
 
- (void)applicationWillTerminate:(UIApplication *)application
{
    [[QBChat instance] logout];
}
 
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[QBChat instance] logout];
}
 
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // check here if a user was logged in to Chat and login him if YES
    // ...
    [[QBChat instance] loginWithUser:user];
}

1 to 1 Chat

Text chat

1 to 1 Chat is very easy to set up. Just send a message to the opponent & receive messages from them in return:

// send message
QBChatMessage *message = [QBChatMessage message];
message.recipientID = 546; // opponent's id
message.text = @"Hi mate!";
 
// You also can set custom parameters for your message
[message setCustomParameters:@{@"playSound": @YES}];
 
[[QBChat instance] sendMessage:message];
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatDidReceiveMessage:(QBChatMessage *)message{
    NSLog(@"New message: %@", message);
}

Custom parameters

You can use custom parameters for the messages you send in the chat, for example to send some additional info or to send control messages:

// send message
QBChatMessage *message = [QBChatMessage message];
message.recipientID = 546; // opponent's id
[message setCustomParameters:@{@"delivered": @YES}];
 
[[QBChat instance] sendMessage:message];


Chat State Notifications

Many instant messaging systems include notifications about the state of one's conversation partner in a one-to-one chat (or, sometimes, in a many-to-many chat). In essence, chat state notifications can be thought of as a form of chat-specific presence.

This section describes how to integrate chat states notifications into your application.

Here is a list of common Chat State Notifications:

  1. composing: The user is composing a message. The user is actively interacting with a message input interface specific to this chat session (e.g., by typing in the input area of a chat window)
  2. paused: The user had been composing but now has stopped. The user was composing but has not interacted with the message input interface for a short period of time (e.g., 30 seconds)
  3. inactive: The user has not been actively participating in the chat session. The user has not interacted with the chat session interface for an intermediate period of time (e.g., 2 minutes)

With QuickBlox you can use any of these chat status notifications and integrate any others as well. It's purely dependent on the developer's imagination.

Here is an example of how to implement the composing (typing) notification.

To produce this notification we should implement a UITextFieldDelegate delegate in the application:

@interface ChatViewController : UIViewController <UITextFieldDelegate>
 
@property (nonatomic, assign) IBOutlet UITextField *textField;
 
...
 
@implementation ChatViewController
 
#pragma mark
#pragma mark UITextFieldDelegate
 
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
 
    // send 'composing' notification to opponent
    QBChatMessage *message = [QBChatMessage message];
    message.recipientID = 546; // opponent's id
    [message setText:@"composing"];
    [message setCustomParameters:@{@"isComposing": @YES}];
    [[QBChat instance] sendMessage:message];
 
    return YES;
}
 
- (void)textFieldDidEndEditing:(UITextField *)textField{
    // finish composing
    QBChatMessage *message = [QBChatMessage message];
    message.recipientID = 546; // opponent's id
    [message setText:@"composing"];
    [message setCustomParameters:@{@"isComposing": @NO}];
    [[QBChat instance] sendMessage:message];
}

On the opponent's side we can track this notification and update the UI:

@interface ChatViewController : UIViewController <QBChatDelegate>
 
...
 
@implementation ChatViewController
 
#pragma mark
#pragma mark QBChatDelegate
 
-(void)chatDidReceiveMessage:(QBChatMessage *)message{
    NSDictionary *customParameters = message.customParameters;
    NSNumber *isComposingNotification = customParameters[@"isComposing"];
    if(isComposingNotification != nil){
        BOOL isComposingState = [isComposingNotification boolValue];
        if(isComposingState){
            // opponent is composing - update UI
        }else{
            // opponent has stopped compose - update UI
        }
    }
}


Send files

To send file you should perform the following steps:

  1. Upload new file to Content module:
    // Upload new avatar to Content module
    NSData *image = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"myAvatar" ofType:@"png"]];
    //
    [QBContent TUploadFile:image fileName:@"MyAvatar" contentType:@"image/png" isPublic:NO delegate:self];
     
    #pragma mark -
    #pragma mark QBActionStatusDelegate
     
    - (void)completedWithResult:(Result *)result{
     
        // success result
        if(result.success){
            // Upload file result
            if([result isKindOfClass:QBCFileUploadTaskResult.class]){
     
                // get uploaded file ID
                QBCFileUploadTaskResult *res = (QBCFileUploadTaskResult *)result;
                NSUInteger uploadedFileID = res.uploadedBlob.ID;
            }
        }else{
            NSLog(@"Errors=%@", result.errors);
        }
    }
  2. To send a link to a file through chat messages:
    // send message
    QBChatMessage *message = [QBChatMessage message];
    message.recipientID = 546; // opponent's id
    [message setCustomParameters:@{@"fileID": @(uploadedFileID)}];
     
    [[QBChat instance] sendMessage:message];
  3. Receive message and download file:
    #pragma mark -
    #pragma mark QBChatDelegate
     
    - (void)chatDidReceiveMessage:(QBChatMessage *)message{
        NSUInteger fileID = [message.customParameters[@"fileID"] integerValue];
     
        // download file by ID
        [QBContent TDownloadFileWithBlobID:fileID delegate:self];
    }
     
    #pragma mark -
    #pragma mark QBActionStatusDelegate
     
    - (void)completedWithResult:(Result *)result{
        // Download file result
        if(result.success && [result isKindOfClass:QBCFileDownloadTaskResult.class]){
            // extract image
            QBCFileDownloadTaskResult *res = (QBCFileDownloadTaskResult *)result;
            UIImage *image = [UIImage imageWithData:res.file];
        }else{
            NSLog(@"Errors=%@", result.errors);
        }
    }

Chatrooms

Create a room

You can create 4 types of rooms:

  • members-only vs. open:
    • open - A room that non-banned users are allowed to enter without being on the member list
    • members-only - A room that a user cannot enter without being on the member list
  • persistent vs. temporary:
    • persistent - A room that is not destroyed if the last user exits
    • temporary - A room that is destroyed if the last occupant exits

Create an open & persistent room

[[QBChat instance] createOrJoinRoomWithName:@"Real Madrid fans" membersOnly:NO persistent:YES];
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidEnter:(QBChatRoom *)room{
    NSLog(@"Public room %@ was created", room.name);
 
    // You have to retain the created room if this is a temporary room. In other cases the room will be destroyed and all the occupants will be disconnected from the room
    myRoom = [room retain];
}

Note: when the room is released - you will leave it automatically.

Create a members-only & temporary room

[[QBChat instance] createOrJoinRoomWithName:@"Real Madrid fans" membersOnly:YES persistent:NO];
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidEnter:(QBChatRoom *)room{
    NSLog(@"Private room %@ was created", room.name);
 
    // You have to retain the created room if this is a temporary room. In other cases the room will be destroyed and all occupants will be disconnected from the room.
    myRoom = [room retain];
 
    // Add users to this room
    NSNumber *anny = [NSNumber numberWithInt:300];
    NSNumber *jim = [NSNumber numberWithInt:357];
    NSArray *users = [NSArray arrayWithObjects:anny, jim, nil];
 
    [[QBChat instance] addUsers:users toRoom:room];
}

Using a custom nickname In the cases above you will be connected to a room with a nickname=UserID. To use a custom nickname - use the method below:

[[QBChat instance] createOrJoinRoomWithName:testRoomName nickname:@"Garry Santos" membersOnly:NO persistent:NO];

Note: To be able to edit rooms created by API users in the Admin panel - just add an Admin user ID to the room:

- (void)chatRoomDidEnter:(QBChatRoom *)room{
 
    // add Admin to room
    [room addUsers:@[@3224124]];
}

Manage members

Add users to only-members room

NSNumber *user = [NSNumber numberWithInt:298];
NSArray *users = [NSArray arrayWithObject:user];
 
[[QBChat instance] addUsers:users toRoom:myRoom];

Delete users from only-members rooms

NSNumber *user = [NSNumber numberWithInt:298];
NSArray *users = [NSArray arrayWithObject:user];
 
[[QBChat instance] deleteUsers:users fromRoom:myRoom]];

Retrieve users who can join an only-members room

[[QBChat instance] requestRoomUsers:myRoom];
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidReceiveListOfUsers:(NSArray *)users room:(NSString *)roomName{
    NSLog(@"chatRoomDidReceiveListOfUsers %@, %@",roomName, users);
}

Retrieve online users

[[QBChat instance] requestRoomOnlineUsers:myRoom];
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidReceiveListOfOnlineUsers:(NSArray *)users room:(NSString *)roomName{
     NSLog(@"chatRoomDidReceiveListOfOnlineUsers %@, %@",roomName, users);
}


Handle online room users

#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidChangeOnlineUsers:(NSArray *)onlineUsers room:(NSString *)roomName{
    NSLog(@"chatRoomDidChangeOnlineUsers %@, %@",roomName, onlineUsers);
 
     for (QBChatRoomOccupant *onlineUsers in users){
         ...
     }
}


Send custom presence

You can send custom presence to room:

[[QBChat instance] sendPresenceWithParameters:@{@"status": @"Online", @"job" : @"doctor"} toRoom:self.myRoom];

This will fire delegate method chatRoomDidChangeOnlineUsers and other room occupants will be able to get your custom status through QBChatRoomOccupant.parameters field.

Join/leave rooms

Join room

[[QBChat instance] joinRoom:realMadridFansRoom];
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidEnter:(QBChatRoom *)room{
     NSLog(@"chatRoomDidEnter: %@", room);
}
 
- (void)chatRoomDidNotEnter:(NSString *)roomName error:(NSError *)error{
     NSLog(@"chatRoomDidNotEnter: %@, error: %@", roomName, error);
}


Leave a room

[[QBChat instance] leaveRoom:realMadridFansRoom;
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidLeave:(NSString *)roomName{
    self.myRoom = nil;
    NSLog(@"chatRoomDidLeave: %@", roomName);
}

Send & receive messages

In order to send & receive messages you must have joined a room.

Send a message

[[QBChat instance] sendMessage:@"Hey! Did you see last Liverpool match?" toRoom:liverpoolFansRoom];

Receive a message

#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidReceiveMessage:(QBChatMessage *)message fromRoom:(NSString *)roomName {
    NSLog(@"Did receive message: %@ from room:%@", message.text, roomName)
}

Destroy a room

Room owners can destroy rooms like this.

[[QBChat instance] destroyRoom:testRoom];
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatRoomDidDestroy:(NSString *)roomName{
    NSLog(@"chatRoomDidDestroy: %@", roomName);
}

Retrieve rooms

[[QBChat instance] requestAllRooms];
 
 
#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatDidReceiveListOfRooms:(NSArray *)_rooms{
    NSLog(@"Did receive list of rooms: %@", _rooms);
}

Manage rooms in the Admin panel

You can create rooms through the Admin panel, Chat module

  1. Just Sign In on Admin panel, go to Chat module page
  2. Enter your password from Admin panel again.
  3. Press the New Room button - a New room form will appear
  4. Enter the room's name and press the Create button
  5. QBChatAdmin createRoom.png

  6. Your room will be appear in the List of rooms. Now you can discover it & join
  7. If you want to set some of the room's options - click on it - and a page with room's details will be opened

Contact list

Contact list mode

In traditional IM applications, the "buddy" system is rather straightforward. User A sends a request to become "friends" with user B. User B accepts the friend request. And now user A and B appear in each other's roster. By default this SDK provides this mode.


But, alternatively, you can use twitter like logic. User A sends a presence subscription request to user B. Think about this more like following on twitter. User A is requesting permission to receive presence information from user B (following their presence). User B can accept this request, but may not be interested in receiving presence info from user B. Again, this is more like twitter following, but with the addition of required permission.So when user B accepts the request, this *only* means that user A will receive presence from user B. It does *not* mean that user B will receive presence from user A. Again, twitter-style, user A is now "following" user B. In diagram form, presence is flowing like this:

 A <-- B


Now, if B also wants to receive presence from user A, then user B must request this permission. And furthermore, user A must accept the request. Just because B has granted A permission to receive presence, doesn't mean that B gets a free pass to receive presence from A.

To enable twitter like logic use use next code:

[QBChat instance].useMutualSubscriptionForContactList = NO;

To check subscription state of particular contact use subscriptionState property of QBContactListItem class. It can be the next:

  • QBPresenseSubscriptionStateNone - the user does not have a subscription to the contact's presence information, and the contact does not have a subscription to the user's presence information
  • QBPresenseSubscriptionStateTo - the user has a subscription to the contact's presence information, but the contact does not have a subscription to the user's presence information
  • QBPresenseSubscriptionStateFrom - the contact has a subscription to the user's presence information, but the user does not have a subscription to the contact's presence information
  • QBPresenseSubscriptionStateBoth - both the user and the contact have subscriptions to each other's presence information

Access to the Contact list

To access contact list you can use the contactList property in QBChat class:

[QBChat instance].contactList.contacts // array of accepted contacts
 
//
 
[QBChat instance].contactList.pending // array of pending requests

You can also track contact list updates in real time by using delegates:

#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatContactListDidChange:(QBContactList *)contactList{
}
 
- (void)chatDidReceiveContactItemActivity:(NSUInteger)userID isOnline:(BOOL)isOnline status:(NSString *)status{
}

Adding/Removing users

To add users to the contact list just use the method below:

[[QBChat instance] addUserToContactListRequest:218650]; // user ID

This user will receive the request to be added to the contact list:

#pragma mark -
#pragma mark QBChatDelegate
 
- (void)chatDidReceiveContactAddRequestFromUser:(NSUInteger)userID{
    // do something
}

To confirm the request:

[[QBChat instance] confirmAddContactRequest:218650]; // user ID

To reject the request:

[[QBChat instance] rejectAddContactRequest:218650]; // user ID

To remove a previously added user from the contact list:

[[QBChat instance] removeUserFromContactList:218651]; // user ID

Custom status

A client MAY provide detailed status information to his contacts by using the status parameter in presence:

[[QBChat instance] sendPresenceWithStatus:@"I shall return!"];

Managing the Chat History

1 to 1 Chat history

There are 2 ways to organise a 1 to 1 chat history:

  1. Storing the history on client side (e.g. using local SQLite database or similar features)
  2. Using the Chat-to-CustomObjects plugin - it allows developers to store/view/retrieve 1 to 1 Chat history in the QuickBlox Custom Objects module. See CustomObjects iOS code sample to figure out how to work with CustomObjects module.


Room history

After you have joined an existing room you will receive the history as regular messages.

#pragma mark -
#pragma mark QBChatDelegate
- (void)chatRoomDidReceiveMessage:(QBChatMessage *)message fromRoom:(NSString *)roomName{
    // message.delayed = 1 for room history messages
}

By default, the maximum number of history messages returned by a room is 50. There is currently no way to change this value.

Connecting to Web XMPP Chat

Coming soon.

Comments

Feel free to comment on this page using the form below.

blog comments powered by Disqus