ANDROID SDK

In-App Chat Android SDK

Overview

eRTC SDK is secure, easy to integrate, deploy and manage.

The following principles are followed during development:

  • Modularity: Code is segregated into multiple modules and follows chain of responsibility model
  • Ease of Integration: Maven artifacts can be downloaded from a public hosted url. eRTC SDK can be integrated into any mobile app within minutes
  • Scalability: SDK is highly scalable and can support Enterprise traffic
  • Built on Latest Tech Stack
  • Data ownership: SDK provides a data layer to effectively manage and control data
  • Firebase powered by Google: Highly reliable and scalable
  • Reactive using RxAndroid

Features

  • Individual messages
  • Push notifications
  • Text, Image, Video, Audio messages
  • Typing Indicators
  • Delivered and Read receipts
  • Chat history
  • Chat user list
  • Contact details

Quickstart

  • To start with an existing app, just initialize the SDK in your Application’s onCreate() method and start using the SDK features
  • Please note that we are using Java 8 in our SDK, so you'll need to add Java 8 support in the compile options
  • We are using AndroidX in our SDK, so please add AndroidX support in gradle.properties
  • Once you do these prerequisites, you are ready to start using our SDK

How to add the eRTC SDK to your Android app

Integration with an existing project is simple. You can add the core libraries using Gradle.

Gradle

To download the SDK, you will need to include the repository manually:

  • Add repository
    repositories {
       mavenCentral()
       maven { url "http://artifactory.pantepic.com/artifactory/ext-sdk-new" }
    }
  • Then add this to your dependencies area:
    implementation ('com.ripbull.coresdk:ripbull-chat-sdk:1.1.0.release-rc1'){
       transitive = true
    }
  • You also need to enable Java 8
    compileOptions {
       sourceCompatibility JavaVersion.VERSION_1_8
       targetCompatibility JavaVersion.VERSION_1_8
    }

Android X

Make sure you’ve added the following to your gradle.properties file.

android.useAndroidX=true

Initializing the Chat SDK

Now open your application’s main class and find the onCreate method. Add the following to set up the Chat SDK:

try {
// set your api key here
val config =
Configuration.Builder().context(this).apiKey("edu6qgwsjxxxxxApiKey").build()

// SDK initialize
eRTCSDK.initializeWithConfig(config)

} catch (Exception e) {
   // Handle any exceptions
   e.printStackTrace();
}

API documentation

Namespace validation

disposable.add(
  eRTCSDK.tenant().validate(namespace)
    .subscribeOn(Schedulers.io()).observeOn(
      AndroidSchedulers.mainThread()
    ).subscribe(
      Consumer<Result> { this.success(it) }, error
    )
)

User Login

disposable.add(
  eRTCSDK.tenant().login(AccountDetails.username(username, password))
    .subscribeOn(Schedulers.io()).observeOn(
      AndroidSchedulers.mainThread()
    ).subscribe({ this.success(it, username) }, error)
)

Change password

disposable.add(
  eRTCSDK.tenant().changePassword(
    AccountDetails.changePwd(
      oldPassword, newPassword
    )
  ).subscribeOn(Schedulers.io()).observeOn(
    AndroidSchedulers.mainThread()
  ).subscribe(
    Consumer<Result> { this.success(it) }, error
  )
)

Forgot password

disposable.add(
  eRTCSDK.tenant().forgotPassword(AccountDetails.forgotPwd(namespace))
    .subscribeOn(Schedulers.io()).observeOn(
      AndroidSchedulers.mainThread()
    ).subscribe(Consumer<Result> { this.success(it) }, error
  )
)

Get Chat Users

disposable.add(
  eRTCSDK.user().chatUsers
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onUserListSuccess,
      this::onUserListError
    )
)

Get Mentioned users

disposable.add(
  eRTCSDK.user().mentionedUsers
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ userRecords ->

    }, { throwable ->

    })
)

Get Reaction Users

disposable.add(
  eRTCSDK.user().getReactionedUsers(reactionUnicodes, msgId, threadID, ChatType.CHAT_THREAD)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ userRecords ->

    }, { throwable ->

    })
)

Logout

disposable.add(
  eRTCSDK.user().logout().subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //clear session locally
    }, { throwable ->
      //error
    })
)

User Metadata On – MQTT subscription(To get user updates in real time)

disposable.add(
  eRTCSDK.user()
    .subscribeToUserMetaData()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ userRecord ->

    }, { throwable ->

    })
)

Get user details

disposable.add(
  eRTCSDK.user().getUserById(userId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onUserSuccess,
      this::onUserError
    )
)

Update user profile(with & without profile image)

disposable.add(
  eRTCSDK.user().updateProfile(
    profileStatus, this.filePath.let { if(it.isNullOrEmpty()) "" else it },
    AttachmentManager.MediaType.IMAGE.toString()
  )
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->

    })
)

Remove profile pic

disposable.add(   eRTCSDK.user().removeProfilePic()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->

    })
)

Set Global notification settings

disposable.add(
  eRTCSDK.notification()
    .muteNotifications(action, MuteNotificationType.USER_LEVEL)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ dataString->
      //Success
    }, { throwable ->
    })
)

Get global notification settings

disposable.add(
  eRTCSDK.notification().getSettings()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ dataString->
      dataString?.let { notificationSettings ->
        //set notification settings on UI
      }
    }, { throwable ->
      //Error handling
    })
)

metaDataOn(Global notification setting)

disposable.add(   eRTCSDK.user()
    .metaDataOn(ERTCApplication.getSession(activity!!).getUserId())
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ userMetaDataRecord ->
      userMetaDataRecord.notificationSettings?.let { notificationSettings ->
        //set notification settings on UI
      }
    }, { throwable ->

    })
)

Set user availability status

val status = AvailabilityStatus.AUTO or AvailabilityStatus.AWAY or AvailabilityStatus.INVISIBLE or AvailabilityStatus.DND

disposable.add(
  eRTCSDK.user().setUserAvailability(status)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->
      //Error
    })
)

Get user availability status

eRTCSDK.user().userAvailabilityStatus

Create Group

val groupRecord = GroupRecord(
  groupName,
  groupDesc,
  this.filePath.let { if(it.isNullOrEmpty()) "" else it },
  selectedUser
)

disposable.add(
  eRTCSDK.group().createPrivateGroup(groupRecord)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onGroupCreateSuccess, this::onGroupCreateError
    )
)

Get all groups

disposable.add(
  eRTCSDK.group().groups
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onListSuccess, this::onListError
    )
)

Get group info by groupId

disposable.add(
  eRTCSDK.group().getGroupById(groupId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    }, { throwable ->
      //Error
    })
)

Update Group details

disposable.add(eRTCSDK.group().updateGroupDetail(
  groupId,
  groupName,
  groupDesc,
  this.filePath.let { if(it.isNullOrEmpty()) "" else it }
).subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(
    this::onGroupUpdateSuccess, this::onGroupUpdateError
  )
)

Add participants

disposable.add(
  eRTCSDK.group().addParticipants(groupId, userList)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    {,{ throwable ->
      //Error
    })
)

Remove participants

disposable.add(
  eRTCSDK.group().removeParticipants(groupId, userList)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    },{ throwable ->
      //Error
    })
)

Add admin

disposable.add(
  eRTCSDK.group().addAdmin(groupId, userId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    },{ throwable ->
      //Error
    })
)

Remove admin

disposable.add(
  eRTCSDK.group().removeAdmin(groupId, userId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    },{ throwable ->
      //Error
    })
)

Exit group

disposable.add(
  eRTCSDK.group().exitGroup(groupId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    },{ throwable ->
      //Error
    })
)

Remove group picture

disposable.add(
  eRTCSDK.group().removeGroupPic(groupDetail?.groupId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->
      //Error
    })
)

Group Metadata On

disposable.add(   eRTCSDK.group()
    .subscribeToGroupUpdate()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ groupRecord ->
      //Success
    },{ throwable ->
      //Error
    })
)

Create Thread

disposable.add(
  eRTCSDK.chat().createThread(appUserId)
    .subscribeOn(Schedulers.io()).observeOn(
      AndroidSchedulers.mainThread()
    ).subscribe({ threadId ->
      //store threadId and use it in application
    }, { throwable ->
      //Error
    })
)

Get Threads

disposable.add(
  eRTCSDK.chat().getThreads()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onThreadListSuccess, this::onThreadListError
    )
)

Send Message

A chat between two users is considered a thread of communication. To initiate a chat between users, you need to create threads and send messages over that threadID.

//For TEXT
val message = Message(
  message = textMessage,
  chatType = chatType,
  mentions = mention,
  mentioned_users = mentionList
)

//IMAGE
val message = Message(
  media = Media(filePath, MessageType.IMAGE),
  chatType = chatType
)

//GIF
val message = Message(
  media = Media(filePath, MessageType.GIF),
  chatType = chatType
)

//VIDEO
val message = Message(
  media = Media(filePath, MessageType.VIDEO),
  chatType = chatType
)

//AUDIO
val message = Message(
  media = Media(filePath, MessageType.AUDIO),
  chatType = chatType
)

//FILE
val message = Message(
  file = com.ripbull.coresdk.chat.model.File(filePath, MessageType.FILE),
  chatType = chatType
)

//CONTACT
val message = Message(
  contact = Contact(contactName, phoneRecords, emailRecords, CONTACT),
  chatType = chatType)

//LOCATION
val message = Message(
  location = Location(address, latLng.latitude, latLng.longitude, LOCATION),
  chatType = chatType
)

//GIPHY
val message = Message(
  giphy = Giphy(url, GIPHY),
  chatType = chatType
)
disposable.add(
  eRTCSDK.chat()
    .sendMessage(threadID!!, message)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageRecord ->
      //add this message on your list and update listview.
    }, { throwable ->
      //Error
    })
)

Get Messages

disposable.add(
  eRTCSDK.chat().getMessages(threadID)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onMessageListSuccess, this::onMessageListError
    )
)

Get ChatThread Messages

disposable.add(
  eRTCSDK.chat().getChatThreadMessages(threadID, parentMsgId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onMessageListSuccess, this::onMessageListError
    )
)

Send Reaction

disposable.add(
  eRTCSDK.chat()
    .sendReaction(
      threadID,
      messageMetaData
    )
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ chatReactionRecord ->
      //use this data and update UI(list or recyclerview)
    }, { throwable ->
      //Error
    })
)

Message metadata On

disposable.add(
  eRTCSDK.chat().messageMetaDataOn(threadID!!)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageMetaDataRecord ->
      messageMetaDataReord.chatReactionRecord?.let { it ->
        //update UI when you will receive reaction record via MQTT
      }
    }, { throwable ->
      //Error
    })
)

Thread data update on main thread

disposable.add(
  eRTCSDK.chat().sourceOnMain()
    .filter(ChatEvent.filterType(EventType.THREAD_MESSAGE_METADATA))
    .filter { it.threadId == threadID }
    .subscribe({ chatEvent ->
      chatEvent.threadMetadata?.let { it ->
        //update UI with latest thread meta data
      }
    }, { throwable ->
      //Error
    })
)

Get Message by messageId

disposable.add(
  eRTCSDK.chat()
    .getMessage(threadId, forwardMessageId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageRecord ->
      //Success
    }, { throwable ->
      //Error
    })
)

Get chat thread message by messageId

disposable.add(
  eRTCSDK.chat()
    .getChatThreadMessage(threadId, forwardMessageId)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageRecord ->
      //Success
    }, { throwable ->
      //Error
    })
)

Forward chat

disposable.add(
  eRTCSDK.chat()
    .forwardChat(messageList, contactIdList, groupThreadIdList, chatType)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->
      //Error
    })
)

Delete Message

/* there are two option for outgoing message deleteForMe and deleteForEveryOne And one option for incoming message is delete for me*/
disposable.add(
  eRTCSDK.chat()
    .deleteMessage(deleteType, threadId, messageRecords)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageRecords ->
      //update all these record’s UI to message is deleted
    }, { throwable ->
      //Error
    })
)

Edit Message

disposable.add(
  eRTCSDK.chat()
    .editMessage(threadID, message)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageRecord ->
      //update UI of edited message in list or recyclerview
    }, { throwable ->
      //Error
    })
)

Chat Restore

disposable.add(
  eRTCSDK.chat().chatRestore()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->
      //Error
    })
)

Chat skipRestore

disposable.add(
  eRTCSDK.chat().chatSkipRestore()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //Success
    }, { throwable ->
      //Error
    })
)

Search message(local search)

disposable.add(
  eRTCSDK.chat()
    .searchMessages(searchedText)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onSearchedListSuccess, this::onSearchedListError
    )
)

Search message(global search)

disposable.add(
  eRTCSDK.chat()
    .globalSearch(searchedText)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onSearchedListSuccess, this::onSearchedListError
    )
)

Mark as Read

//you can use this method for thread also.
//In that case you have to pass parentMsgId in the second parameter.

eRTCSDK.chat()
  .markAsRead(it, "")
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe({
  }, {
    it.printStackTrace()
  })

Message Read status – MQTT Listener

//you can use this method for thread also.
//In that case you have to pass parentMsgId in the second parameter.

disposable.add(
  eRTCSDK.chat()
    .msgReadStatus(threadID, "", chatType)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ networkEvet ->
      //notify message status changed(update UI)
      markAsRead()
    }, { throwable ->
      //Error
    })
)

Message On – MQTT Listener (for normal message)

//you can use this method for thread also.
//In that case you have to pass parentMsgId in the second parameter.

disposable.add(
  eRTCSDK.chat()
    .messageOn(threadID, "", chatType)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ networkEvet ->
      networkEvent.messageRecord()
      //add this message record in your list or recycler view and update UI
    }, { throwable ->
      //Error
    })
)

Message On – MQTT Listener (Edit/Delete/Favorite)

//for the main chat window or you can use this method to get notification also by this method you will be notified on every message.

disposable.add(
  eRTCSDK.chat()
    .messageOn()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .filter(NetworkEvent.filterType(EventType.MESSAGE_UPDATED)).subscribe ({
      val messageRecord = it.messageRecord()
      if(messageRecord.updateType == MessageUpdateType.DELETE){
        // update UI for delete
      } else if (messageRecord.updateType == MessageUpdateType.EDIT){
        // update UI for edit
      } else if (messageRecord.updateType == MessageUpdateType.FAVORITE{
        // update UI for favorite
      }
    },{ throwable ->
      //Error
    })
)

Block/unblock user

val action: String = if (user.blockedStatus.equals(AppConstants.USER_BLOCKED)) {
  "unblock"
} else {
  “block”
}

disposable.add(
  eRTCSDK.chat()
    .blockUnblock(action, user.id!!)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
      //update UI on success
    }, { throwable ->
      //Error
    })
)

Mark as favorite

/***********
msgFavList = ArrayList<MessageRecord>
isFavorite = true/false
***********/

disposable.add(
  eRTCSDK.chat()
    .markAsFavorite(threadId, msgFavList, isFavorite)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ messageList ->
      //update UI on success
    }, { throwable ->
      //Error
    })
)

Get all Favorite Messages

disposable.add(
  eRTCSDK.chat()
    .getAllFavoriteMessages()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onMessageListSuccess, this::onMessageListError
    )
)

Get all favorite thread specific messages

disposable.add(
  eRTCSDK.chat()
    .getAllFavoriteMessages(threadID)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
      this::onMessageListSuccess, this::onMessageListError
    )
)

Typing indicator subscription

disposable.add(
  eRTCSDK.typing()
    .subscribe(threadID)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ typingIndicatorRecord ->
      //you got typing indication for this thread id so you have to display it on UI
    }, { it.printStackTrace() })
)

Typing indicator publish

//when you are typing you have to execute this method

disposable.add(
  eRTCSDK.typing()
    .publish(threadID, state)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ }, { it.printStackTrace() })
)

Download Media

disposable.add(
  eRTCSDK.chat()
    .downloadMedia(msgId, serverUrl, dirPath, mediaType)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
    }, { throwable ->
      //Error
    })
)

Download Media On – MQTT Listener

//you can use this method for thread also.
//in that case you have to pass parentMsgId in the second parameter.

disposable.add(
  eRTCSDK.chat()
    .downloadOn(threadID, "", chatType)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ networkEvet ->
      //Update UI with download status(make it completed)
    }, { throwable ->
      //Error
    })
)

Mute notification

disposable.add(
  eRTCSDK.notification()
    .muteNotifications(action, MuteNotificationType.THREAD_LEVEL, it, chatType)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ muteSetting ->
      //update UI
    }, { throwable ->
      //Error
    })
)

Get notification settings

disposable.add(
  eRTCSDK.notification()
    .getSettings(threadID)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ muteSetting ->
      //update UI
    }, { throwable ->
      //Error
    })
)

Chat metadata on for notification setting – MQTT Listener

disposable.add(
  eRTCSDK.chat()
    .chatMetaDataOn(threadID)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ muteSetting ->
      //update UI
    }, { throwable ->
      //Error
    })
)

FCM implementation Module

You need FCM registration before Login API. for that you need to write below line in your application

eRTCSDK.registerFCMToServer()

For redirection to an activity, say MainActivity, You need to set Intent using the below code

val intent = Intent(applicationContext, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
eRTCSDK.getIntentForFCM(intent)

To manage thread-based notification, When a user clicked on Notification you need to write the below piece of code(e.g. In MainActivity)

override fun onNewIntent(intent: Intent?) {
  super.onNewIntent(intent)
  if (intent != null) {
    eRTCSDK.fcm().clearNotification()
  }
}

Resources

Modules:

  • Core SDK module
  • Permission module
  • Attachment module
  • Data Module
  • MQTT module
  • Analytics module
  • Core Http Module (Rest APIs)
  • Core Encryption
In-App Chat Android