Skip to content

In‐app chat

Jakub Dzubak edited this page May 15, 2023 · 36 revisions

Find more info about Live chat product on Infobip docs.

Intro

In-app chat SDK is built on top of Mobile Messaging SDK and that's why Mobile Messaging should be included into your application and properly configured. If you haven't used Mobile Messaging SDK in you application yet, then please follow Quick start guide to enable it.

Once Mobile Messaging SDK is up and running, enabling In-app chat SDK is easy. Add dependencies to your app's build.gradle file:

dependencies {
    ...
    implementation "com.infobip:infobip-mobile-messaging-android-chat-sdk:8.+@aar"
    implementation 'androidx.exifinterface:exifinterface:1.1.0'  // can be any 1.+ version, 1.1.0 is an example
    //since version 8.0 you need to add following depencies (if you do not have them already)
    implementation 'org.jetbrains.kotlin:kotlin-stdlib:+'
    implementation 'androidx.databinding:viewbinding:+'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:+'
}

Starting from 4.0.0 version method for activation of in-app chat service should be called after initializing MobileMessaging SDK:

    InAppChat.getInstance(context).activate()
expand to see Java code

   InAppChat.getInstance(context).activate();

Now you can start sending messages.

Display In-app chat screen

Mobile Messaging In-app SDK provides a built-in chat view which you can quickly embed into your own application. You need to start chat view with just one line of code:

InAppChat.getInstance(context).inAppChatScreen().show()
expand to see Java code

InAppChat.getInstance(context).inAppChatScreen().show();

It will immediately open chat view activity on top of current activity.

Customize In-app chat

Starting from 8.0.0 version, we introduced new approach to customize In-app chat, where we added many new attributes to be customized. Simultaneously we have deprecated old customization approach, while there is still fallback to the old customization attributes when the new ones are not present.

Final value for every customizable attribute is resolved from multiple sources by source priority. Source with the highest priority defines final attribute value. If source does not define attribute value, there is fallback to the source with lower priority.

Sources by priority:

  1. New approach android theme attribute
  2. Old approach android theme attribute
  3. LiveChat widget theme
  4. In-app chat default theme

Theme

To customize In-app chat you have to define your own custom theme in application's styles.xml with name IB_AppTheme.Chat. In-app chat offers 4 theme attributes, each to customize separate part/view of In-app chat screen.

<resources>
  <style name="IB_AppTheme.Chat">
    <item name="ibChatToolbarStyle">@style/InAppChat.Demo.Toolbar</item> <!-- In-app chat toolbar style -->
    <item name="ibChatAttachmentToolbarStyle">@style/InAppChat.Demo.Toolbar</item> <!-- In-app chat attachment preview toolbar style -->
    <item name="ibChatInputStyle">@style/InAppChat.Demo.Input</item> <!-- In-app chat message input style -->
    <item name="ibChatStyle">@style/InAppChat.Demo.Chat</item> <!-- In-app chat style -->
  </style>
  <style name="Demo"/>
</resources>

Toolbar style

Both theme attributes ibChatToolbarStyle and ibChatAttachmentToolbarStyle support same toolbar style attributes. See also list of supported attributes for TextAppearance.

<style name="InAppChat.Demo.Toolbar" parent="Demo">
    <item name="ibChatToolbarBackgroundColor">@android:color/black</item>
    <item name="ibChatStatusBarBackgroundColor">@android:color/black</item>
    <item name="ibChatStatusBarIconsColorMode">light</item> <!-- Values light or dark, supported only for API >= 23 -->
    <item name="ibChatNavigationIcon">@drawable/ic_chat_arrow_back</item>
    <item name="ibChatNavigationIconTint">@android:color/white</item>
    <item name="ibChatTitleTextAppearance">@style/TextAppearance.MaterialComponents.Headline6</item>
    <item name="ibChatTitleTextColor">@android:color/white</item>
    <item name="ibChatTitleText">@null</item>
    <item name="ibChatTitleCentered">false</item>
    <item name="ibChatSubtitleTextAppearance">@null</item>
    <item name="ibChatSubtitleTextColor">@android:color/white</item>
    <item name="ibChatSubtitleText">@null</item>
    <item name="ibChatSubtitleCentered">false</item>
</style>

Notice:

ibChatTitleTextColor value has precedent over ibChatTitleTextAppearance's textColor attribute value. Same applies to ibChatSubtitleTextColor and ibChatSubtitleTextAppearance.

Chat style

Theme attribute ibChatStyle supports following chat style attributes. See also list of supported attributes for TextAppearance.

<style name="InAppChat.Demo.Chat" parent="Demo">
    <item name="ibChatBackgroundColor">@android:color/white</item>
    <item name="ibChatProgressBarColor">@android:color/black</item>
    <item name="ibChatNetworkConnectionErrorText">Your custom network connection error message</item>
    <item name="ibChatNetworkConnectionErrorTextColor">@android:color/black</item>
    <item name="ibChatNetworkConnectionErrorTextAppearance">@style/TextAppearance.MaterialComponents.Subtitle1</item>
    <item name="ibChatNetworkConnectionErrorLabelBackgroundColor">@android:color/gray</item>
</style>

Notice:

ibChatNetworkConnectionErrorTextColor value has precedent over ibChatNetworkConnectionErrorTextAppearance's textColor attribute value.

Chat input style

Theme attribute ibChatInputStyle supports following chat input style attributes. See also list of supported attributes for TextAppearance.

<style name="InAppChat.Demo.Input" parent="Demo">
    <item name="ibChatInputTextAppearance">@style/TextAppearance.MaterialComponents.Body1</item>
    <item name="ibChatInputTextColor">@android:color/black</item>
    <item name="ibChatInputBackgroundColor">@android:color/white</item>
    <item name="ibChatInputHintText">Your custom hint</item>
    <item name="ibChatInputHintTextColor">@android:color/darker_gray</item>
    <item name="ibChatInputAttachmentIcon">@null</item>
    <item name="ibChatInputAttachmentIconTint">@android:color/black</item>
    <item name="ibChatInputSendIcon">@null</item>
    <item name="ibChatInputSendIconTint">@android:color/black</item>
    <item name="ibChatInputSeparatorLineColor">@android:color/darker_gray</item>
    <item name="ibChatInputSeparatorLineVisible">true</item>
    <item name="ibChatInputCursorColor">@android:color/black</item>
</style>

Notice:

ibChatInputTextColor value has precedent over ibChatInputTextAppearance's textColor attribute value. ibChatInputAttachmentIconTint and ibChatInputSendIconTint support color state list resource type.

TextAppearance attributes

List of supported attributes for TextAppearance:

<attr name="textColor" />
<attr name="textSize" />
<attr name="textStyle" />
<attr name="typeface" />
<attr name="fontFamily" />
<attr name="textColorHighlight" />
<attr name="textColorHint" />
<attr name="textColorLink" />
<attr name="textAllCaps" format="boolean" />
<attr name="shadowColor" format="color" />
<attr name="shadowDx" format="float" />
<attr name="shadowDy" format="float" />
<attr name="shadowRadius" format="float" />
<attr name="elegantTextHeight" format="boolean" />
<attr name="letterSpacing" format="float" />
<attr name="fontFeatureSettings" format="string" />
Quick migration to new 8.0.0 customization approach

If you want to preserve current color setup and migrate to new customization approach follow the section.

Deprecated approach:

<resources>
    <style name="IB_AppTheme.Chat">
        <item name="colorPrimary">@color/colorPrimary</item> <!-- DEPRECATED | color of toolbar background and send chat button tint -->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!-- DEPRECATED | color of status / notification bar -->
        <item name="colorControlNormal">@android:color/white</item> <!-- DEPRECATED | color of navigation icon in toolbar -->
        <item name="titleTextColor">@android:color/white</item> <!-- DEPRECATED | color of toolbar title text -->
    </style>
</resources>
<resources>
    <style name="IB_AppTheme.ChatAttach">
        <item name="colorPrimary">@color/colorPrimary</item> <!-- DEPRECATED | color of toolbar background -->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!-- DEPRECATED | color of status / notification bar -->
        <item name="colorControlNormal">@android:color/white</item> <!-- DEPRECATED | color of navigation icon in toolbar -->
        <item name="titleTextColor">@android:color/white</item> <!-- DEPRECATED | color of toolbar title text -->
    </style>
</resources>

is equals to new approach

<resources>
    <style name="IB_AppTheme.Chat">
        <item name="ibChatToolbarStyle">@style/InAppChat.Demo.Toolbar</item> <!-- In-app chat toolbar style -->
        <item name="ibChatAttachmentToolbarStyle">@style/InAppChat.Demo.Toolbar</item> <!-- In-app chat attachment preview toolbar style -->
    </style>

    <style name="Demo"/>

    <style name="InAppChat.Demo.Toolbar" parent="Demo">
        <item name="ibChatToolbarBackgroundColor">@color/colorPrimary</item> <!-- color of toolbar background and send chat button tint -->
        <item name="ibChatStatusBarBackgroundColor">@color/colorPrimaryDark</item> <!-- color of status / notification bar -->
        <item name="ibChatNavigationIconTint">@android:color/white</item> <!-- color of navigation icon in toolbar -->
        <item name="ibChatTitleTextColor">@android:color/white</item> <!-- color of toolbar title text -->
    </style>
</resources>
Customization approach before version 8.0.0

Certain attributes of built-in chat view are customizable through resources.

Title

You can supply your custom title for chat activity via ib_chat_view_title string in strings.xml:

<resources>
    <string name="ib_chat_view_title">My Chat</string>
</resources>

Theme

You can define your own custom theme for the chat view in styles.xml and change action bar / toolbar and notification bar colors, colorPrimary and colorPrimaryDark respectively. Use IB_AppTheme.Chat name for this chat view theme and IB_AppTheme.ChatAttach name for chat attachments preview theme.

<resources>
    <style name="IB_AppTheme.Chat">
        <item name="colorPrimary">@color/colorPrimary</item> <!-- color of toolbar background and send chat button tint -->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!-- color of status / notification bar -->
        <item name="colorControlNormal">@android:color/white</item> <!-- color of navigation icon in toolbar -->
        <item name="titleTextColor">@android:color/white</item> <!-- color of toolbar title text -->
    </style>
</resources>
<resources>
    <style name="IB_AppTheme.ChatAttach">
        <item name="colorPrimary">@color/colorPrimary</item> <!-- color of toolbar background -->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!-- color of status / notification bar -->
        <item name="colorControlNormal">@android:color/white</item> <!-- color of navigation icon in toolbar -->
        <item name="titleTextColor">@android:color/white</item> <!-- color of toolbar title text -->
    </style>
</resources>

Handle notification taps

Mobile Messaging SDK triggers NOTIFICATION_TAPPED event when user taps on chat message notification. Note that chat messages may be recognized by Message.isChatMessage() attribute:

You can register broadcast receiver for this event and process corresponding message:

val tapReceiver = object: BroadcastReceiver() {
    override fun onReceive(context:Context, intent: Intent) {
        val message = Message.createFrom(intent)
        if (message.isChatMessage()) {
            // process message
        }
    }
}
LocalBroadcastManager.getInstance(context).registerReceiver(tapReceiver, IntentFilter(Event.NOTIFICATION_TAPPED.key))
expand to see Java code

private final BroadcastReceiver tapReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Message message = Message.createFrom(intent);
        
        if (message.isChatMessage()) {
            // process message
        }
    }
};

LocalBroadcastManager.getInstance(context).registerReceiver(tapReceiver, new IntentFilter(Event.NOTIFICATION_TAPPED.getKey()));

Tap behavior

The default behavior of Mobile Messaging SDK is to open default launcher activity when user taps on chat message notification. But you can also specify your own activity stack to use:

InAppChat.getInstance(context).setActivitiesToStartOnMessageTap(FirstActivity::class.java, SecondActivity::class.java)
expand to see Java code

InAppChat.getInstance(context).setActivitiesToStartOnMessageTap(FirstActivity.class, SecondActivity.class);

In this case library will create a stack of activities in the order specified in method call: SecondActivity will be on the top and then FirstActivity. Each activity will receive an intent with Message inside:

val message: Message = Message.createFrom(intent)
expand to see Java code

Message message = Message.createFrom(intent);

In-app chat events

In-app chat library supports all core SDK library events plus following chat specific events which you can receive with intents in broadcast receivers:

Event Parameters Description
CHAT_CONFIGURATION_SYNCED Triggered when chat configuration is synchronized.
UNREAD_MESSAGES_COUNTER_UPDATED Unread messages count Triggered when number of unread messages is changed.
CHAT_VIEW_CHANGED InAppChat view name Triggered when when view in InAppChat is changed.

You will need to register receiver for each event of interest. In your receiver you will be able to process parameters according to the table above, for example:

private val eventReceiver = object: BroadcastReceiver() {
    override fun onReceive(context:Context, intent: Intent) {
        // process event occurrence
    }
}
LocalBroadcastManager.getInstance(context).registerReceiver(eventReceiver, IntentFilter(InAppChatEvent.CHAT_CONFIGURATION_SYNCED.key))
expand to see Java code

private final BroadcastReceiver eventReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // process event occurrence
    }
};

LocalBroadcastManager.getInstance(context).registerReceiver(eventReceiver, new IntentFilter(InAppChatEvent.CHAT_CONFIGURATION_SYNCED.getKey()));

Examples

CHAT_CONFIGURATION_SYNCED

Action name to subscribe to: org.infobip.mobile.messaging.chat.CHAT_CONFIGURATION_SYNCED.

UNREAD_MESSAGES_COUNTER_UPDATED

Action name to subscribe to: org.infobip.mobile.messaging.chat.UNREAD_MESSAGES_COUNTER_UPDATED. Receiving event data in BroadcastReceiver:

override fun onReceive(context: Context, intent: Intent) {
    val unreadMessagesCount = intent.getIntExtra(BroadcastParameter.EXTRA_UNREAD_CHAT_MESSAGES_COUNT)
}
expand to see Java code

@Override
public void onReceive(Context context, Intent intent) {
    int unreadMessagesCount = intent.getIntExtra(BroadcastParameter.EXTRA_UNREAD_CHAT_MESSAGES_COUNT);
}

CHAT_VIEW_CHANGED

Action name to subscribe to: org.infobip.mobile.messaging.chat.CHAT_VIEW_CHANGED. Receiving event data in BroadcastReceiver:

override fun onReceive(context: Context, intent: Intent) {
    val view = intent.getStringExtra(BroadcastParameter.EXTRA_CHAT_VIEW)
    val inAppChatWidgetView = InAppChatWidgetView.valueOf(view)
}
expand to see Java code

@Override
public void onReceive(Context context, Intent intent) {
    String view = intent.getStringExtra(BroadcastParameter.EXTRA_CHAT_VIEW);
    InAppChatWidgetView inAppChatWidgetView = InAppChatWidgetView.valueOf(view);
}

Supported InAppChat view values:

LOADING, THREAD_LIST, LOADING_THREAD, THREAD, CLOSED_THREAD, SINGLE_MODE_THREAD

Sending attachments

Starting from 3.1.0 SDK version, we've added sending attachments feature. In order to be able to capture photo and video you will need to declare uses-permission in Manifest.xml. Add CAMERA and WRITE_EXTERNAL_STORAGE permission inside tag.

<manifest ...>
...
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
...

Notice:

Starting from Android 13, new granular permissions were introduced: READ_MEDIA_AUDIO, READ_MEDIA_IMAGES and READ_MEDIA_VIDEO, so they must be added inside tag:

<manifest ...>
...
  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
...

Notice:

Add requestLegacyExternalStorage="true" to AndroidManifest.xml to prevent issues with capturing attachments from camera for Android 10+ devices.

<manifest ... >
 <application android:requestLegacyExternalStorage="true" ... >
   ...
 </application>
</manifest>

Notice:

Images captured from camera saved to /Pictures/<Your app name>/InAppChat folder and starting from 5.2.4 version:

  1. If size is more than 5MB, image quality will be set to 80%
  2. If size is more than 10MB image also will be scaled down in 2 times.

Attachments preview

Starting from 3.4.0 SDK version, we added attachments preview feature. In order to be able to save attachment you will need to declare uses-permission in Manifest.xml. Add WRITE_EXTERNAL_STORAGE permission inside tag if it's not added on previous step.

<manifest ...>
...
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...

Supported attachment types

Media type File size File format
image 10MB JPG, JPEG, PNG
video 10MB MP4

Advanced

Display in-app chat as fragment

Supported starting from 4.3.0 version

In order to display in-app chat view you can use InAppChatActivity as described in Display In-app chat screen section, alternatively, you can use InAppChatFragment, which you can embed into your Activity.

To setup your Activity for using InAppChatFragment follow the steps (full code can be checked in ChatExample):

  1. Create layout in your activity.xml to use it as container for fragment. For MainActivity from ChatExample we used FrameLayout - activity_main.xml
<android.support.design.widget.CoordinatorLayout>
...
    <FrameLayout
        android:id="@+id/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.design.widget.CoordinatorLayout>
  1. Use following method to show in-app chat as Fragment. containerId - id of fragment container, which was added on previous step; fragmentManager - FragmentManager instance to make interactions with Fragment, you can get it in activity, calling getSupportFragmentManager();
InAppChat.getInstance(context).showInAppChatFragment(fragmentManager, containerId);
  1. Implement InAppChatFragment.InAppChatActionBarProvider interface in your Activity.
public class MainActivity extends AppCompatActivity implements InAppChatFragment.InAppChatActionBarProvider {

    /* InAppChatActionBarProvider */

    /**
     * Provide original ActionBar, to give in-app chat ability to hide it and use it's own ActionBar.
     * It will be hidden when in-app Chat fragment shown and returned back, when in-app Chat fragment hidden.
     */
    @Nullable
    @Override
    public ActionBar getOriginalSupportActionBar() {
        return getSupportActionBar();
    }

    /**
     * Implement back button behaviour.
     * Call following method with corresponding parameter:
     * {@link InAppChat#hideInAppChatFragment(FragmentManager)}
     */
    @Override
    public void onInAppChatBackPressed() {
        InAppChat.getInstance(MainActivity.this).hideInAppChatFragment(getSupportFragmentManager());
    }
...
}

Display in-app chat as view

Starting from 8.0.0 version, we introduced InAppChatView which you can embed into your Activity or Fragment. It allows you to use InAppChat with your custom-made toolbar, message input and whatever you wish to have in the chat screen. To customize InAppChatView see chat style section. Although you have full control over the chat screen content, there are mandatory setup steps you have to follow:

  1. Add InAppChatView into your layout.
<androidx.constraintlayout.widget.ConstraintLayout>
  ...
  <org.infobip.mobile.messaging.chat.view.InAppChatView
          android:id="@+id/inAppChatView"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>
  ...
</androidx.constraintlayout.widget.ConstraintLayout>
  1. Inject Activity/Fragment's Lifecycle into InAppChatView.

Notice:

  • To get Activity's Lifecycle call getLifecycle()
  • To get Fragment's Lifecycle call getViewLifecycleOwner().getLifecycle()
  1. In order to support multiple chat threads feature, you have to implement InAppChatView.EventsListener interface where you will obtain multiple useful callbacks, except another void onChatViewChanged(InAppChatWidgetView widgetView) one important for handling InAppChat internal navigation.
  2. (Optional) Handle InAppChat's errors on your own by implementing InAppChatView.ErrorsHandler interface. InAppChatView exposes its default error handler by calling inAppChatView.getDefaultErrorsHandler().
class MainActivity: AppCompatActivity() {
  
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //1. Injects activity's lifecycle
    val inAppChatView: InAppChatView = findViewById(R.id.inAppChatView)
    inAppChatView.init(lifecycle)

    //2. Set InAppChatView.EventsListener to handle multithread internal navigation
    inAppChatView.eventsListener = object : InAppChatView.EventsListener {
      override fun onChatLoaded(controlsEnabled: Boolean) {
        //Chat was loaded, if controlsEnabled = true there was no error
      }

      override fun onChatControlsVisibilityChanged(isVisible: Boolean) {
        //Handle chat controls visibility change, you can show/hide input based on isVisible value
      }

      override fun onAttachmentPreviewOpened(url: String?, type: String?, caption: String?) {
        //Handle attachment preview
      }

      override fun onChatViewChanged(widgetView: InAppChatWidgetView) {
        //Handle navigation in multithread livechat widget
        when (widgetView) {
          InAppChatWidgetView.LOADING,
          InAppChatWidgetView.THREAD_LIST,
          InAppChatWidgetView.SINGLE_MODE_THREAD -> {
            //no need to handle internal navigation
          }
          InAppChatWidgetView.LOADING_THREAD,
          InAppChatWidgetView.THREAD,
          InAppChatWidgetView.CLOSED_THREAD -> {
            //to navigate back to THREAD_LIST use inAppChatView.showThreadList();
          }
        }
        //Handle message input in multithread livechat widget
        when (widgetView) {
          InAppChatWidgetView.LOADING,
          InAppChatWidgetView.THREAD_LIST,
          InAppChatWidgetView.LOADING_THREAD,
          InAppChatWidgetView.CLOSED_THREAD -> {
            //it is prohibited to send messages
          }
          InAppChatWidgetView.SINGLE_MODE_THREAD,
          InAppChatWidgetView.THREAD -> {
            //you can send messages
          }
        }
      }

      override fun onChatWidgetInfoUpdated(widgetInfo: WidgetInfo) {
        //Useful livechat widget information
      }

    }

    //3. Set InAppChatView.ErrorsHandler to handle InAppChatView errors on your own
    inAppChatView.errorsHandler = object : InAppChatView.ErrorsHandler {
      override fun handlerError(error: String) {
        //Your custom handling of general error or use default handler
        inAppChatView.defaultErrorsHandler.handlerError(error);
      }

      override fun handlerWidgetError(error: String) {
        //Your custom handling of Livechat widget error or use default handler
        inAppChatView.defaultErrorsHandler.handlerWidgetError(error);
      }

      override fun handlerNoInternetConnectionError() {
        //Your custom handling of missing network connection error or use default handler
        inAppChatView.defaultErrorsHandler.handlerNoInternetConnectionError();
      }

    }
    
  }

}
expand to see Java code

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      //1. Injects activity's lifecycle
      InAppChatView inAppChatView = findViewById(R.id.inAppChatView);
      inAppChatView.init(getLifecycle());
      
      //2. Set InAppChatView.EventsListener to handle multithread internal navigation
      inAppChatView.setEventsListener(new InAppChatView.EventsListener() {

        @Override
        public void onChatLoaded(boolean controlsEnabled) {
          //Chat was loaded, if controlsEnabled = true there was no error
        }

        @Override
        public void onChatControlsVisibilityChanged(boolean isVisible) {
          //Handle chat controls visibility change, you can show/hide input based on isVisible value
        }

        @Override
        public void onAttachmentPreviewOpened(@Nullable String url, @Nullable String type, @Nullable String caption) {
          //Handle attachment preview
        }

        @Override
        public void onChatViewChanged(@NonNull InAppChatWidgetView widgetView) {
          //Handle navigation in multithread livechat widget
          switch (widgetView) {
            case LOADING:
            case THREAD_LIST:
            case SINGLE_MODE_THREAD:
              //no need to handle internal navigation
              break;
            case LOADING_THREAD:
            case THREAD:
            case CLOSED_THREAD:
              //to navigate back to THREAD_LIST use inAppChatView.showThreadList();
              break;
          }
          //Handle message input in multithread livechat widget
          switch (widgetView) {
            case LOADING:
            case THREAD_LIST:
            case LOADING_THREAD:
            case CLOSED_THREAD:
              //it is prohibited to send messages
              break;
            case SINGLE_MODE_THREAD:
            case THREAD:
              //you can send messages
              break;
          }
        }

        @Override
        public void onChatWidgetInfoUpdated(@NonNull WidgetInfo widgetInfo) {
          //Useful livechat widget information
        }
      });

      //3. Set InAppChatView.ErrorsHandler to handle InAppChatView errors on your own
      inAppChatView.setErrorsHandler(new InAppChatView.ErrorsHandler() {
        @Override
        public void handlerError(@NonNull String error) {
          //Your custom handling of general error or use default handler
          inAppChatView.getDefaultErrorsHandler().handlerError(error);
        }

        @Override
        public void handlerWidgetError(@NonNull String error) {
          //Your custom handling of Livechat widget error or use default handler
          inAppChatView.getDefaultErrorsHandler().handlerWidgetError(error);
        }

        @Override
        public void handlerNoInternetConnectionError() {
          //Your custom handling of missing network connection error or use default handler
          inAppChatView.getDefaultErrorsHandler().handlerNoInternetConnectionError();
        }
      });
    }

}

InAppChatView public functions

InAppChatView provides you options to set language, create message with attachment, send message draft, send contextual data and execute internal chat navigation in case you use multiple chat threads.

class InAppChatView {

    /**
     * Returns true if chat is synchronized and multithread feature is enabled, otherwise returns false
     */
    val isMultiThread: Boolean
    
    /**
     * [InAppChatView] event listener allows you to listen to Livechat widget events.
     */
    var eventsListener: EventsListener?

    /**
     * Allows you to set custom [InAppChatView.ErrorsHandler] handler to process [InAppChatView] errors on your own.
     */
    var errorsHandler: ErrorsHandler
    val defaultErrorsHandler: ErrorsHandler

    /**
     * Initialize [InAppChatView] with enclosing android component [Lifecycle].
     * @param lifecycle lifecycle of android Activity or Fragment
     */
    fun init(lifecycle: Lifecycle)

    /**
     * Set the language of the Livechat Widget
     * @param locale locale's language is used by Livechat Widget and native parts
     */
    fun setLanguage(locale: Locale)

    /**
     * Set contextual data of the Livechat Widget
     *
     * @param data                   contextual data in the form of JSON string
     * @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
     */
    fun sendContextualMetaData(data: String, allMultiThreadStrategy: Boolean)

    /**
     * Navigates Livechat widget from thread detail back to thread's list destination in multithread widget. It does nothing if widget is not multithread.
     */
    fun showThreadList()

    /**
     * Sends draft message to be show in chat to peer's chat.
     * @param draft message
     */
    fun sendInputDraft(draft: String)

    /**
     * Sends message to the chat with optional [InAppChatMobileAttachment].
     * @param message message to be send
     * @param attachment to create attachment use [InAppChatMobileAttachment]'s constructor where you provide attachment's mimeType, base64 and filename
     */
    fun sendChatMessage(message: String?, attachment: InAppChatMobileAttachment? = null)
    
    ...
}
expand to see Java code

public class InAppChatView {
    
    public void init(@NotNull Lifecycle lifecycle);
    public void setLanguage(@NotNull Locale locale);
    public void sendContextualMetaData(@NotNull String data, @NotNull Boolean allMultiThreadStrategy);
    public void showThreadList();
    public void sendInputDraft(@NotNull String draft);
    public void sendChatMessage(@Nullable String message);
    public void sendChatMessage(@Nullable String message, @Nullable InAppChatMobileAttachment attachment);
    public boolean isMultiThread();
    public void setEventListener(@Nullable InAppChatView.EventListener eventListener);
    @Nullable public InAppChatView.EventListener getEventListener();
    public void setErrorsHandler(@NotNull InAppChatView.ErrorsHandler errorsHandler);
    @NotNull public InAppChatView.ErrorsHandler getErrorsHandler();
    @NotNull public InAppChatView.ErrorsHandler getDefaultErrorsHandler();
    
    ...
}

Unread chat push messages counter

Starting from version 5.3.0, new API is available to get and reset current unread chat push messages counter. The counter increments each time the application receives chat push message (this usually happens when chat screen is inactive or the application is in background/terminated state). In order to get current counter value use following API:

val messageCounter = InAppChat.getInstance(context).messageCounter
// use the count the way that suits you
expand to see Java code

int unreadChatMessagesCount = InAppChat.getInstance(context).getMessageCounter();
// use the count the way that suits you

MobileMessaging SDK automatically resets the counter to 0 whenever user opens the chat screen. However, use the following API in case you need to manually reset the counter:

InAppChat.getInstance(context).resetMessageCounter()
expand to see Java code

InAppChat.getInstance(context).resetMessageCounter();

You can setup broadcast received for InAppChatEvent.UNREAD_MESSAGES_COUNTER_UPDATED, with an extra broadcast parameter BroadcastParameter.EXTRA_UNREAD_CHAT_MESSAGES_COUNT of int value, in order to get updates of the counter in runtime, for example:

<receiver android:name=".UnreadMessagesCounterReceiver" android:exported="false">
    <intent-filter>
        <action android:name="org.infobip.mobile.messaging.chat.UNREAD_MESSAGES_COUNTER_UPDATED"/>
    </intent-filter>
</receiver>

Receiver code:

override fun onReceive(context: Context?, intent: Intent) {
    val unreadChatMessagesCounter = intent.getIntExtra(BroadcastParameter.EXTRA_UNREAD_CHAT_MESSAGES_COUNT)
}
expand to see Java code

@Override
public void onReceive(Context context, Intent intent) {
    int unreadChatMessagesCounter = intent.getIntExtra(BroadcastParameter.EXTRA_UNREAD_CHAT_MESSAGES_COUNT);
}

Changing localization

The predefined messages prompted within the In-app chat (such as status updates, button titles, input field prompt) by default are localized using system locale setting, but can be easily changed providing your locale string with the following formats: "es_ES", "es-ES", "es"

InAppChat.getInstance(context).setLanguage("es-ES");

Sending Contextual Data / Metadata

It is possible to send contextual data / metadata to Infobip’s Conversations via In-App Chat SDK. The data can be send any time, several times, with only one restriction: the chat must be already loaded and presented, and the communication should have started (meaning, there are messages visible and not the initial “Start the chat” button). The data sent will be automatically linked to the conversationId and accountId internally. There are two parameters:

  1. The mandatory data, sent as string, in the format of Javascript objects and values (for guidance, it must be accepted by JSON.stringify())
  2. And optionally, a multithread strategy that can be left empty, and will use ACTIVE as default. Possible values are: metadata sent to "ACTIVE" conversation for the widget, or "ALL" non closed conversations for the widget.

Usage:

InAppChat chat = InAppChat.getInstance(context)
// Present and wait till the chat is loaded and ready, then simply call
chat.sendContextualData("{name: 'Robert'}");
// or with multithread flag
chat.sendContextualData("{name: 'Robert'}", true);

Multiple chat threads

Default LiveChat widget (name of the channel InAppChat uses in backend) works with single chat threads: one customer can only have one single open conversation. But the LiveChat widget could be enabled, in backend, to have multiple chat threads.

Multithread setting

When the setting above is enabled, the InAppChat UI will automatically offer in mobile:

  • A list (initially empty) of all the unsolved conversation threads the user has opened.
  • A button to "Start new chat" thread.
  • A navigation to each specific conversation thread, to open particular chat view tap on conversation thread in the list.
Threads list

The functionality for multiple chat threads works out of the box: there is no need for extra implementation in the mobile integrator's side. But there is something you may need to consider regarding navigation bar and the back button:

InAppChat, when multiple threads are in use, need to take control over the back button to allow a return to the threads list. In other words: InAppChat will handle internal back navigation logic. For this reason, if you show InAppChat as fragment, it is mandatory to implement InAppChatFragment.InAppChatActionBarProvider in your UI component as shown in example below. If you show InAppChat as activity it is not required to implement InAppChatFragment.InAppChatActionBarProvider.

class MainActivity: AppCompatActivity(), InAppChatFragment.InAppChatActionBarProvider {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //Shows in-app chat as Fragment
    InAppChat.getInstance(applicationContext).showInAppChatFragment(supportFragmentManager, R.id.fragmentContainer);
  }

  override fun getOriginalSupportActionBar(): ActionBar? = supportActionBar

  override fun onInAppChatBackPressed() {
    InAppChat.getInstance(this).hideInAppChatFragment(supportFragmentManager);
  }
  
}
expand to see Java code

public class MainActivity extends AppCompatActivity implements InAppChatFragment.InAppChatActionBarProvider {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Shows in-app chat as Fragment
        InAppChat.getInstance(getApplicationContext()).showInAppChatFragment(getSupportFragmentManager(), R.id.fragmentContainer);
    }
    
    @Nullable
    @Override
    public ActionBar getOriginalSupportActionBar() {
        return getSupportActionBar();
    }

    @Override
    public void onInAppChatBackPressed() {
        InAppChat.getInstance(MainActivity.this).hideInAppChatFragment(getSupportFragmentManager());
    }
}

Authenticated chat

It is possible to authenticate an user before accesing the InAppChat, given you have enabled this feature in the LiveChat widget.

Livechat widget JWT authentication setup

The authentication is accomplished by combining the Mobile Messaging SDK personalisation method with a JWT (JSON Web Token). The token that needs to be generated by your end (see instructions here).

The authentication will use a unique identifier for your user, that can be an email address, a phone number, or an external identifier. It is crucial for this identifier to be valid, and to match the identity defined in the UserIdentity you passed in Mobile Messaging SDK personalisation call - there will be an authentication error otherwise.

InAppChat contains JwtProvider interface to give InAppChat ability to authenticate. Implement the interface and pass the instance into InAppChat. JwtProvider.provideJwt() function can be triggered multiple times during InAppChat lifetime, due to various events like screen orientation change, internet re-connection and others. If you can ensure JWT expiration time is more than in-app chat lifetime, you can return cached token, otherwise it is important to provide fresh new token for each invocation.

/*
1 - The customer authenticate in your system, and you recognise his/her unique identifier
2 - You call personalise with this unique identifier (and optionally, with other attributes such as first name, second name, etc)
3 - Now you can display the chat as an authenticated user by doing the following:
*/

InAppChat.getInstance(context).jwtProvider = InAppChat.JwtProvider {
    //every invocation create and return fresh token
    "your JWT"
}
InAppChat.getInstance(context).inAppChatScreen().show()
expand to see Java code

/*
1 - The customer authenticate in your system, and you recognise his/her unique identifier
2 - You call personalise with this unique identifier (and optionally, with other attributes such as first name, second name, etc)
3 - Now you can display the chat as an authenticated user by doing the following:
*/

InAppChat.getInstance(context).setJwtProvider(new InAppChat.JwtProvider() {
    @Override
    public String provideJwt() {
        //every invocation create and return fresh token
        return "your JWT";
    }
});
InAppChat.getInstance(context).inAppChatScreen().show();

InAppChat demo application provided within the Mobile Messaging SDK offers a functional interface for testing the authentication use case (you just need to set your WIDGET_ID and WIDGET_SECRET_KEY_JSON values in MainActivity.java - chat flavour).

Clone this wiki locally