Chat SDK is a fully featured open source instant messaging framework for iOS. Chat SDK is fully featured, scalable and flexible and follows the following key principles:

  • Open Source. The Chat SDK is open source under the MIT license for compiled binaries
  • Full data control. You have full and exclusive access to the user's chat data
  • Quick integration. Chat SDK is fully featured out of the box
  • Firebase Powered by Google Firebase

A demo of the project is available on the App Store.

App Store

Features

  • Private and group messages
  • Public chat rooms
  • Username / password, Facebook, Twitter, Anonymous and custom login
  • Push notifications
  • Text, Image and Location messages
  • User profiles
  • User search
  • Powered by Firebase
  • Firebase UI
  • Cross Platform - see Android Version

Full breakdown is available on the features page.

Help spread the word

Chat SDK is free and open source. If you like the project help us spread the word by:

  • Giving us a Github star ⭐
  • Upvoting our page on Product Hunt

Get involved!

We're very excited about the project and we're looking for other people to get involved. Over time we would like to make the best messaging framework for mobile. Helping us could involve any of the following:

  • Providing feedback and feature requests
  • Reporting bugs
  • Fixing bugs
  • Writing documentation
  • Improving the user interface
  • Help us update the library to use Swift
  • Helping to write adapters for other services such as Layer, Pusher, Pubnub etc...
  • Write a tutorial - we pay $100 for quality tutorials

If you're interested please review the Contributing Document for details of our development flow and the CLA then email me at team@chatsdk.co.

Apps that use Chat SDK

If you have an app that uses the Chat SDK let us know and we'll add a link.

Running the demo project

This repository contains a fully functional version of the Chat SDK which is configured using our Firebase account and social media logins. This is great way to test the features of the Chat SDK before you start itegrating it with your app.

  1. Clone Chat SDK
  2. Run pod install in the Xcode directory
  3. Open the Chat SDK Firebase.xcworkspace file in Xcode
  4. Compile and run

Swift Version

The Chat SDK is fully compatible with Swift projects and contains a Swift demo project.

  1. Clone Chat SDK
  2. Run pod install in the XcodeSwift directory
  3. Open the ChatSDKSwift.xcworkspace file in Xcode
  4. Compile and run

Setup Service

We provide extensive documentation on Github but if you’re a non-technical user or want to save yourself some work you can take advantage of our setup and integration service.

Explore the Wiki

We have a number of additional guides available on our Wiki including:

And more... so check it out!

Integration with an existing project

Project Structure

We've tried to make it as easy as possible to add Chat SDK to your project. However since it's it's a relatively complex project with a lot of dependencies (and because of some issues with Cocoapods) the setup needs to be handled carefully.

So that things run smoothly, we recommend that you keep the Chat SDK library in the folder outside your Xcode project folder. A typical structure would look like this:

ChatSDK
---- ChatSDKCore
---- ChatSDKCoreData
---- ChatSDKFirebaseAdapter
---- ChatSDKUI

YourProject
---- YourProject.xcodeproj
---- YouProject
-------- [.m and .h files]
---- Podfile

All the paths in the instructions will be provided assuming this project structure. If you use a different structure, you will need to modify the paths accordingly.

Adding the Chat SDK To your project

  1. Download or clone the Chat SDK and put the library files in a convenient location
  2. Add the Chat SDK development pods to your Podfile

    use_frameworks!
    pod "ChatSDKCore", :path => "../ChatSDK/ChatSDKCore"
    pod "ChatSDKUI", :path => "../ChatSDK/ChatSDKUI"
    pod "ChatSDKCoreData", :path => "../ChatSDK/ChatSDKCoreData"
    

    Note
    The path can be absolute or relative but you need to make sure it's correct for your project. The path should be from the location of the Podfile to the folder containing the Chat SDK podspec. Make sure to use the use_frameworks! flag.

  3. Add additional support pods. These are external pods that are needed by the Chat SDK

    pod "Firebase/Auth"  
    pod "Firebase/Database"  
    pod "Firebase/Messaging"  
    pod "Firebase/Storage"  
    
  4. Run pod install

  5. Add the ChatSDKFirebaseAdapter code directly to your Xcode project. Copy the ChatSDKFirebaseAdapter folder from chat-sdk-ios/ChatSDK/ChatSDKFirebaseAdapter/Classes into your Xcode project. From inside Xcode, right click in the left panel click Add Files and add the ChatSDKFirebaseAdapter folder.

    Note
    There are currently ongoing issues with the Firebase pods which make it very difficult for us to include the Chat SDK Firebase Adapter in a development pod. Until these issues are resolved, the easiest approach is to drag the files into Xcode directly.

  6. Simlinking. Alternatively, you can add the FirebaseNetworkAdapter using a simlink. This allows you to have one copy of the code which can be referenced by multiple Xcode projects. To setup the simlinks you need to locate the setup_links.sh script. This should be added to your Xcode project where you want to setup the simlinks. Run the script using sh setup_links.sh. Enter the path to the ChatSDK folder contining the Chat SDK project. If you use the default project structure, you can just leave this blank (the default path is ../../). Then open Xcode and add the simlink folders using the normal process.

  7. Open the App Delegate add the following code to initialise the chat

    Objective C

    AppDelegate.m -> application: didFinishLaunchingWithOptions:

    #import <ChatSDKCore/ChatCore.h>
    #import <ChatSDKUI/ChatUI.h>
    #import <ChatSDKCoreData/ChatCoreData.h>
    #import "ChatFirebaseAdapter.h"
    

    Add the following code to the start of your didFinishLaunchingWithOptions function:

    // Create a network adapter to communicate with Firebase
    // The network adapter handles network traffic
    [BNetworkManager sharedManager].a = [[BFirebaseNetworkAdapter alloc] init];
    
    // Set the default interface manager
    [BInterfaceManager sharedManager].a = [[BDefaultInterfaceAdapter alloc] init];
    
    [BStorageManager sharedManager].a = [[BCoreDataManager alloc] init];
    
    // This is the main view that contains the tab bar
    UIViewController * mainViewController = [[BAppTabBarController alloc] initWithNibName:Nil bundle:Nil];
    
    // Set the login screen
    [BNetworkManager sharedManager].a.auth.challengeViewController = [[BLoginViewController alloc] initWithNibName:Nil bundle:Nil];
    
    [self.window setRootViewController:mainViewController];
    

    Swift

    AppDelegate.swift

    import ChatSDKCore
    import ChatSDKUI
    import ChatSDKCoreData
    

    Add the following to your briding header

    #import "ChatFirebaseAdapter.h"
    

    Add the following code to the start of your didFinishLaunchingWithOptions function:

    BInterfaceManager.shared().a = BDefaultInterfaceAdapter.init()
    BNetworkManager.shared().a = BFirebaseNetworkAdapter.init()
    BStorageManager.shared().a = BCoreDataManager.init()
    
    let mainViewController = BAppTabBarController.init(nibName: nil, bundle: nil)
    BNetworkManager.shared().a.auth().setChallenge(BLoginViewController.init(nibName: nil, bundle: nil));
    
    self.window = UIWindow.init(frame: UIScreen.main.bounds)
    self.window?.rootViewController = mainViewController;
    self.window?.makeKeyAndVisible();
    
  8. The Chat SDK is now added to your project

Firebase Setup

  1. Go to the Firebase website and sign up
  2. Go to the Firebase console and make a new project
  3. Click Add project
  4. Choose a name and a location
  5. Click Settings (the gear icon). On the General tab, click Add Firebase to your iOS app
  6. Enter your bundle ID
  7. Download the GoogleServices file and add it to the root of your Xcode project

    Note:
    It is worth opening your downloaded GoogleService-Info.plist and checking there is an API_KEY field included. Sometimes Firebase's automatic download doesn’t include this in the plist. To rectify, just re-download the plist from the project settings menu.

  8. Next add the Chat SDK specific settings. Open the demo Chat SDK project and locat the chat_sdk entry in the Info.plist file. Copy this entry into the Info.plist file in your project.

  9. Expand the entry and then expand the firebase settings. Set the root_path to a value of your choice. Set the storage_path to the value found in the Firebase console under the storage tab.

    Note
    The root path variable allows you to run multiple Chat SDK instances on one Firebase account. Each different root path will represent a completely separate set of Firebase data. This can be useful for testing because you could have separate test and prod root paths.

  10. Copy the following rows from the demo ChatSDK Info.plist file to your project's Info.plist

    1. App Transport Security Settings
    2. URL types
    3. FacebookAppID
    4. All the privacy rows. These will allow the app to access the camera, location and address book
  11. In the Firebase dashboard click Authentication -> Sign-in method and enable all the appropriate methods

Module Setup

There are a number of free and premium extensions that can be added to the Chat SDK.

Firebase Modules

For the following modules:

The free modules are located in the chat-sdk-ios/ChatSDKFirebase folder. The premium modules can be purchased and downloaded from the links provided above.

To install a module you should use the following steps:

  1. Copy the module code into your Xcode source folder and add the files to your project from inside Xcode. If you are using the Simlink you can use the simlink script (mentioned above) and then just add a link to the ChatSDKFirebase folder to Xcode.
  2. Add any necessary dependencies to your Podfile
  3. Import the module's header file (or add it to the bridging header for a Swift project)
  4. Activate the module in the AppDelegate.m file

Social Login

The social login module allows you to support user authentication using some popular social networks including Twitter, Facebook and Google Plus.

After adding the SocialLogin files to your Xcode project, add the following to your Podfile:

pod 'TwitterKit', '2.3'
pod 'GoogleSignIn'
pod 'FBSDKLoginKit'

Objective C

AppDelegate.m -> application: didFinishLaunchingWithOptions:

 #import "BFirebaseSocialLoginModule.h"

[[[BFirebaseSocialLoginModule alloc] init] activateWithApplication:application withOptions:launchOptions];

Also add this function:

// During the Facebook login flow, your app passes control to the Facebook iOS app or Facebook in a mobile browser.
// After authentication, your app will be called back with the session information.
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
    if ([BNetworkManager sharedManager].a.socialLogin) {
        return [[BNetworkManager sharedManager].a.socialLogin application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
    }
    return NO;
}

Swift

[YourProject]-Bridging-Header.h

 #import "BFirebaseSocialLoginModule.h"

AppDelegate.swift

BFirebaseSocialLoginModule.init().activate(with: application, withOptions: launchOptions);

Also add this function:

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
    if(BNetworkManager.shared().a.socialLogin() != nil) {
        return BNetworkManager.shared().a.socialLogin().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
    }
    return false
}

Follow the social login setup guides.

Push Notifications

The Push Notification module allows you to send free push notifications using Firebase Clound Messenger.

After adding the Push Notifications module to your Xcode project, add the following to the App Delegate to enable the module.

Objective C

AppDelegate.m -> application: didFinishLaunchingWithOptions:

 #import "BFirebasePushModule.h"

[[[BFirebasePushModule alloc] init] activateWithApplication:application withOptions:launchOptions];

Also add these functions:

-(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [[BNetworkManager sharedManager].a.push application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [[BNetworkManager sharedManager].a.push application:application didReceiveRemoteNotification:userInfo];
}

Swift

[YourProject]-Bridging-Header.h

 #import "BFirebasePushModule.h"

AppDelegate.swift

BFirebasePushModule.init().activate(with: application, withOptions: launchOptions);

Also add these functions:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    if (BNetworkManager.shared().a.push() != nil) {
        BNetworkManager.shared().a.push().application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
    }
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if (BNetworkManager.shared().a.push() != nil) {
        BNetworkManager.shared().a.push().application(application, didReceiveRemoteNotification: userInfo)
    }
}

Then follow the Firebase Push notification setup guide.

File Storage

The File Storage module allows you to send image messages. These messages are stored on the Firebase server.

After adding the files to your Xcode project, add the following to the App Delegate to enable the module.

Objective C

AppDelegate.m -> application: didFinishLaunchingWithOptions:

 #import "BFirebaseFileStorageModule.h"

[[[BFirebaseFileStorageModule alloc] init] activate];

Swift

[YourProject]-Bridging-Header.h

 #import "BFirebaseFileStorageModule.h"

AppDelegate.swift

BFirebaseFileStorageModule.init().activate();

Ensure that the file storage path has been setup.

  1. Go to the Firebase console
  2. Click the Storage tab
  3. Copy the storage URL which starts with gs://
  4. Paste it into your Info.plist file at the location chat_sdk -> firebase -> storage_path

Firebase UI

The File UI module allows you to use the native Firebase user interface for authentication.

After adding the files to your Xcode project, add the following to the App Delegate to enable the module.

Objective C

AppDelegate.m -> application: didFinishLaunchingWithOptions:

 #import "BFirebaseUIModule.h"

[[[BFirebaseUIModule alloc] init] activateWithProviders: @[]];

Swift

[YourProject]-Bridging-Header.h

 #import "BFirebaseUIModule.h"

AppDelegate.swift

BFirebaseUIModule.init().activate(withProviders: []);

You should pass in array of the FUIAuthProvider objects you want to support.

Also add the following to your Podfile depending on which authentication methods you want to support:

pod 'FirebaseUI/Facebook', '~> 4.0'
pod 'FirebaseUI/Google', '~> 4.0'
pod 'FirebaseUI/Twitter', '~> 4.0'
pod 'FirebaseUI/Phone', '~> 4.0'

Then run pod install.

Note If you want to Firebase Auth UI make sure you comment out the following line:

BNetworkManager.shared().a.auth().setChallenge(BLoginViewController.init(nibName: nil, bundle: nil));

Other Modules

For the following modules:

These modules are distributed as development pods. After you've downloaded the module, unzip it and add it to the ChatSDKModules folder. Then:

  1. Open your Podfile
  2. Add the line:

    ChatSDKModules/[ModuleName], :path => "[Path to ChatSDKModules folder]"
    
  3. Run pod install
  4. In your AppDelegate -> application: didFinishLaunchingWithOptions: add the following

    Objective C

    #import "B[ModuleName]Module.h"
    
    [[[B[ModuleName]Module alloc] init] activate];
    

    Swift

    AppDelegate.swift

    import ChatSDKModules
    
    B[Module Name]Module.init().activate()
    

Security Rules

Firebase secures your data by allowing you to write rules to govern who can access the database and what can be written. On the Firebase dashboard click Database then the Rules tab.

Copy the contents of the rules.json file into the rules and click publish.

Integrating the Chat SDK with an existing login system

To start with, you should have completed the steps above to add the Chat SDK to your project. To integrate the Chat SDK we need to intercept three key events in your app:

  • Login
  • User profile update
  • Logout

Once this is done, you will be able to access the Chat SDK API to perform actions like searching for users, creating threads and sending messages.

When integrating the Chat SDK with an existing app it's best practice to create a new class with static methods to handle the lifecycle of the Chat SDK. This means that you can perform actions like setting the authentication token, updating the user and logging out from anywhere in your app. This also helps to separate the Chat SDK code from your own code.

Login

To integrate with a third party server two steps are necessary:

  1. Generate an authentication token on your server
  2. Pass the token to the Chat SDK

To generate a token, you should follow the Firebase custom authentication guide.

In PHP, an implementation may look like this:

// Get your service account's email address and private key from the JSON key file
$service_account_email = "abc-123@a-b-c-123.iam.gserviceaccount.com";
$private_key = "-----BEGIN PRIVATE KEY-----...";

function create_custom_token($uid, $is_premium_account) {
  global $service_account_email, $private_key;

  $now_seconds = time();
  $payload = array(
    "iss" => $service_account_email,
    "sub" => $service_account_email,
    "aud" => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
    "iat" => $now_seconds,
    "exp" => $now_seconds+(60*60),  // Maximum expiration time is one hour
    "uid" => $uid,
    "claims" => array(
      "premium_account" => $is_premium_account
    )
  );
  return JWT::encode($payload, $private_key, "RS256");
}

Note:
It is recommended to set the token expiry to a high value to prevent the case where the user is logged in to the server but not the Chat SDK.

The id should be the id your server uses to identify the user who is currently logged in. This token should be passed back to the app. Then the user can be authenticated as follows:

Objective C

[[BNetworkManager sharedManager].a.auth authenticateWithDictionary:@{bLoginTypeKey: @(bAccountTypeCustom),
bLoginCustomToken: token}].thenOnMain(^id(id<PUser> user) {
    // Login Success
    return Nil;
}, ^id(NSError * error) {
    // Login Failure
    return Nil;
});

Swift

let dict = [bLoginTypeKey: bAccountTypeCustom.rawValue, bLoginCustomToken: token] as [String : Any]

let promise = BNetworkManager.shared().a.auth().authenticate(with: dict)
_ = promise!.promiseKitThen().then { (result: Any?) in
    if (result is Error) {
        // Login Failure
    }
    else {
        // Login Success
    }
    return AnyPromise.promiseWithValue(result)
}

Note:
This code could be added as a static function to the Chat SDK handler class as mentioned above.

User integration

The Chat SDK uses CoreData to persist it's data. This includes a user object which is used to store the current user's information.

Whenever the user updates their details in your app, they should also update the information that is used by Chat SDK.

id<PUser> user = [BNetworkManager sharedManager].a.core.currentUserModel;

user.name = @"Name goes here";
user.email = @"Email goes here";
user.phoneNumber = @"Number goes here"

// Set the 
[user setImage:UIImagePNGRepresentation(image)];
[user setThumbnail:UIImagePNGRepresentation(thumbnail)];

// Upload the image and thumbnail if necessary
[[BNetworkManager sharedManager].a.upload uploadImage:image thumbnail:thumbnail].thenOnMain(^id(NSDictionary * urls) {

    // Set the paths to the image and thumbnail
    [user setMetaString:urls[bImagePath] forKey:bUserPictureURLKey];
    [user setMetaString:urls[bThumbnailPath] forKey:bUserPictureURLThumbnailKey];

    // Update the user profile on Firebase
    [[BNetworkManager sharedManager].a.core pushUser];

    return urls;
}, Nil);

Logging out

When your user logs out of the app, they should also log out of the Chat SDK.

Objective C

[[BNetworkManager sharedManager].a.auth logout];

Swift

BNetworkManager.shared().a.auth().logout()

Using the Chat SDK API

The Chat SDK API is based around the network manager and a series of handlers. A good place to start is by looking at the handlers Pods/Development Pods/ChatSDK/Core/Core/Classes/Interfaces. Here you can review the handler interfaces which are well documented. To use a handler you would use the following code:

Objective C

[[BNetworkManager sharedManager].a.handler_name function: to: call:]

Swift

BNetworkManager.shared().a.handler_name() function: to: call:]
Searching for a user

For example, to search for a user you could use the search handler:

-(RXPromise *) usersForIndexes: (NSArray *) indexes withValue: (NSString *) value limit: (int) limit userAdded: (void(^)(id<PUser> user)) userAdded;

Here you pass in a series of indexes to be used in the search i.e. name, email etc... and a value. It will then return a series of user objects.

You can also see example implementations of these handlers by looking at the BFirebaseSearchHandler class. And also seeing how the method is used in the Chat SDK.

Starting a chat

To start a chat you can use the core handler.

-(RXPromise *) createThreadWithUsers: (NSArray *) users
                       threadCreated: (void(^)(NSError * error, id<PThread> thread)) thread;

When this method completes, the thread will have been created on Firebase and all the users will have been added. You could then open the thread using the interface adapter.

UIViewController * chatViewController = [[BInterfaceManager sharedManager].a chatViewControllerWithThread:thread];

So a more complete example would look like this:

-(void) startChatWithUser {
    MBProgressHUD * hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.label.text = [NSBundle t:bCreatingThread];

    [[BNetworkManager sharedManager].a.core createThreadWithUsers:@[_user] threadCreated:^(NSError * error, id<PThread> thread) {
        if (!error) {
            [self pushChatViewControllerWithThread:thread];
        }
        else {
            [UIView alertWithTitle:[NSBundle t:bErrorTitle] withMessage:[NSBundle t:bThreadCreationError]];
        }
        [MBProgressHUD hideHUDForView:self.view animated:YES];
    }];
}

-(void) pushChatViewControllerWithThread: (id<PThread>) thread {
    if (thread) {
        UIViewController * chatViewController = [[BInterfaceManager sharedManager].a chatViewControllerWithThread:thread];
        [self.navigationController pushViewController:chatViewController animated:YES];
    }
}

Troubleshooting Cocoapods

  1. Always open the .xcworkspace file rather than .xcodeproj
  2. Check CocoaPod warnings - make sure to fix any warnings before proceeding
  3. Make sure that your base configuration isn’t set: Project -> project name -> Info -> Configuration
  4. Make sure that the “Build Active Architecture Only” setting is the same for both the main project and the pods project.
  5. Check the build settings in the Xcode project and check which fields are in bold (this means that their value has been overridden and CocoaPods can't access them). If you press backspace while selecting those fields, their values will be set to the default value.

The license

We offer a choice of two license for this app. You can either use the Chat SDK license or the GPLv3 license.

Most Chat SDK users either want to add the Chat SDK to an app that will be released to the App Store or they want to use the Chat SDK in a project for their client. The Chat SDK license gives you complete flexibility to do this for free.

Chat SDK License Summary

  • License does not expire.
  • Can be used for creating unlimited applications
  • Can be distributed in binary or object form only
  • Commercial use allowed
  • Can modify source-code but cannot distribute modifications (derivative works)

If a user wants to distribute the Chat SDK source code, we feel that any additions or modifications they make to the code should be contributed back to the project. The GPLv3 license ensures that if source code is distributed, it must remain open source and available to the community.

GPLv3 License Summary

  • Can modify and distribute source code
  • Commerical use allowed
  • Cannot sublicense or hold liable
  • Must include original license
  • Must disclose source

What does this mean?

Please check out the Licensing FAQ for more information.