-
Notifications
You must be signed in to change notification settings - Fork 2
In‐app chat
Find more info about Live chat product on Infobip docs.
- Intro
- Requirements
- Permissions
- Quick-start guide
- Example application
- Display an In-app chat screen
- Customer's Chat History
- Advanced
- Customize In-app chat
- Customize notifications
- Handle notification taps
- In-app chat events
- Attachments
- Unread chat push messages counter
- Changing localization
- Sending Contextual Data / Metadata
- Multiple chat threads
- Authenticated chat
- Troubleshooting
In-app chat is a mobile component for connecting and interacting with the Infobip's LiveChat product. In-app chat is built on top of the Mobile Messaging SDK and that's why Mobile Messaging should be included in your application and properly configured.
- Android Studio
- Supported API Levels: 21 (Android 5.0 - Lollipop) - 33 (Android 13.0 - Tiramisu)
- HMS Core (APK) 4.0.0.300 or later
- AppGallery
- AndroidX
- In-app chat SDK source and target compatibility set to Java 8
- Infobip account
The In-app chat SDK declares the following as dangerous
permissions:
Runtime check and request for all dangerous permissions is handled by library UI components. There is also one more normal
permission ACCESS_NETWORK_STATE
declared in library.
In-app chat requires from you a careful setup, both in your mobile app and in your Infobip account. The following steps must be prepared in order to ensure the chat communication:
-
Include and set up the Mobile Messaging SDK in your application. If you haven't already, follow its Quick start guide carefully. Only by being able to receive a
pushRegistrationId
in your device, you'll be able to successfully connect to the In-app chat, which we explain in the next steps. -
Create a LiveChat Widget and connect it with the Mobile Messaging application profile you've created in step 1 to the widget configuration.
-
Add dependencies to your app's
build.gradle
file:
dependencies {
...
implementation "com.infobip:infobip-mobile-messaging-huawei-chat-sdk:6.+@aar"
implementation 'androidx.exifinterface:exifinterface:1.1.0' // can be any 1.+ version, 1.1.0 is an example
//since version 4.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 1.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.
The In-app chat 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 a chat activity on top of a current activity. It is quick and simple to integrate full screen end-to-end chat solution.
In-app chat SDK provides also another more flexible and customizable ways to show chat. To prepare tailor-made chat read Advanced section. Together with chat customization options you can integrate In-app chat to perfectly fit all your design needs.
Once your app is installed, it is assigned a set of IDs for receiving push notifications and connecting to LiveChat. Additionally, a mostly empty "person" entity is automatically created on the Infobip side as part of the installation. For more details, see another page explaining users and installations terminology.
While having an anonymous customer/person fits some use cases, most likely you'll have an authenticated customer you can/want to identify (for example, by their email, phone number, or some other unique ID). To do so, use the Personalize feature of the Mobile messaging SDK. You can link your customer to your app installation and also you'll be able to recover a chat history with that customer.
Once your app has received the push registration, personalize your customer. Next time the chat shows up, previously sent messages will be present, recovering the open conversation.
There is also an option to depersonalize a customer. This reverts the customer to its original, anonymous state emptying the chat history. This is a common/suggested practice for log-out flows.
In-app chat screen consists of 3 UI components: navigation toolbar, messages list and message input. In-app chat SDK provides 3 ways how to show a chat. Every approach allows you different level of difficulty to integrate and control over the chat. It is up to you to pick the way matching your needs:
-
InAppChatScreen
- It is easiest and fastest way how to integrate and show chat. It shows activity - full screen chat with all 3 UI components. You don't need to handle anything. All UI components works together smoothly. To show the activity see Display an In-app chat screen section. -
InAppChatFragment
- If you want to show chat in own activity, you can embed the chat fragment. The fragment shows chat with all 3 UI components by default. There is an option to hide default navigation toolbar or message input and implement own one. To integrate the fragment see Display an in-app chat as fragment section. -
InAppChatView
- It is just messages list UI component, without navigation toolbar and message input. It is Android view, you can place it in a screen as you wish. You have full control over the chat. To integrate the view see Display an in-app chat as view section.
There are 2 options how to show InAppChatFragment
:
- Assisted approach - Fragment instance is created and managed by In-app chat SDK. You can only show and hide fragment. It is similar solution as
InAppChatScreen
, only difference is you can embed fragment into your custom activity. Fragment shows navigation toolbar with logic for internal navigation in chat with multiple thread. Fragment shows also message input with logic required to send messages and attachments, including permissions requests. You have no option hide UI components. To show fragment see assisted approach section. - Full ownership - You create and show instance of
InAppChatFragment
. Fragment offers many public properties and functions what provides you significant flexibility. You can control visibility of chat UI components. To show fragment see Full ownership section.
To set up your Activity for using InAppChatFragment
follow the steps below. Full code can be checked in the ChatExample).
- Create a layout in your
activity.xml
to use it as a container for the fragment. ForMainActivity
from the ChatExample we usedFrameLayout
- 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>
- Use the following method to show an in-app chat as Fragment.
containerId
- ID of the fragment container which was added in the previous step;fragmentManager
-FragmentManager
an instance to make interaction with Fragment. You can get it from activity, callinggetSupportFragmentManager()
;
InAppChat.getInstance(context).showInAppChatFragment(fragmentManager, containerId);
- Implement the
InAppChatFragment.InAppChatActionBarProvider
interface in your Activity.
class MainActivity: AppCompatActivity(), InAppChatFragment.InAppChatActionBarProvider {
/* InAppChatActionBarProvider */
/**
* Provide the original ActionBar to give the in-app chat ability to hide it and use its own ActionBar.
* It will be hidden when an in-app Chat fragment is shown and returned back when an in-app Chat fragment hidden.
*/
override val originalSupportActionBar: ActionBar?
get() = supportActionBar
/**
* Implement a back button behaviour.
* Call the following method with a corresponding parameter:
* {@link InAppChat#hideInAppChatFragment(FragmentManager)}
*/
override fun onInAppChatBackPressed() {
InAppChat.getInstance(this).hideInAppChatFragment(supportFragmentManager)
//you can pass "true" as second argument to disconnect chat when fragment is hidden to receive push notifications
//InAppChat.getInstance(this).hideInAppChatFragment(supportFragmentManager, true)
}
...
}
expand to see Java code
public class MainActivity extends AppCompatActivity implements InAppChatFragment.InAppChatActionBarProvider {
/* InAppChatActionBarProvider */
/**
* Provide the original ActionBar to give the in-app chat ability to hide it and use its own ActionBar.
* It will be hidden when an in-app Chat fragment is shown and returned back when an in-app Chat fragment hidden.
*/
@Nullable
@Override
public ActionBar getOriginalSupportActionBar() {
return getSupportActionBar();
}
/**
* Implement a back button behaviour.
* Call the following method with a corresponding parameter:
* {@link InAppChat#hideInAppChatFragment(FragmentManager)}
*/
@Override
public void onInAppChatBackPressed() {
InAppChat.getInstance(MainActivity.this).hideInAppChatFragment(getSupportFragmentManager());
//you can pass "true" as second argument to disconnect chat when fragment is hidden to receive push notifications
//InAppChat.getInstance(this).hideInAppChatFragment(supportFragmentManager, true);
}
...
}
Full code of example integration of InAppChatFragment
can be checked in the ChatExample application.
Version 6.5.0 onwards introduces many new public properties and functions in InAppChatFragment
class.
You can control visibility of navigation toolbar and message input. You can decide to hide it if you want to implement custom replacement. Although you have a full control over the chat screen
content, there are steps we recommend you to follow:
- Create instance
InAppChatFragment
instance and set UI components visibility. - Set
InAppChatFragment.EventsListener
chat events listener. Interface provides various useful callbacks. It is required when you implement custom navigation toolbar, and you want to support multiple chat threads feature. - Handle InAppChat's errors on your own by implementing the
InAppChatFragment.ErrorsHandler
interface. TheInAppChatFragment.defaultErrorHandler
property exposes its default error handler.
class MainActivity: AppCompatActivity() {
lateinit var fragment: InAppChatFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//1. Create instance and set UI components visibility
fragment = InAppChatFragment()
fragment.withInput = false
fragment.withToolbar = true
//2. Set events listener
fragment.eventsListener = object : InAppChatFragment.EventsListener {
/**
* Called once chat has been loaded and connection established.
*
* @param controlsEnabled true if chat is loaded and connected without errors, false otherwise
*/
override fun onChatLoaded(controlsEnabled: Boolean) {}
/**
* Chat connection has been stopped.
*/
override fun onChatDisconnected() {}
/**
* Chat connection has been re-established.
*/
override fun onChatReconnected() {}
/**
* Chat controls visibility has changed.
*
* @param isVisible true if controls are visible, false otherwise
*/
override fun onChatControlsVisibilityChanged(isVisible: Boolean) {}
/**
* Chat view has changed.
*
* @param widgetView current chat view
*/
override fun onChatViewChanged(widgetView: InAppChatWidgetView) {}
/**
* Chat [WidgetInfo] has been updated.
*
* @param widgetInfo updated widget info
*/
override fun onChatWidgetInfoUpdated(widgetInfo: WidgetInfo) {}
/**
* Chat theme has changed.
*
* @param widgetThemeName name of the applied theme
*/
override fun onChatWidgetThemeChanged(widgetThemeName: String) {}
/**
* Chat message has been received.
*
* @param rawMessage raw message received by the chat
*/
override fun onChatRawMessageReceived(rawMessage: String) {}
/**
* Called when attachment from chat has been interacted.
*
* It allows you to handle attachment preview on your own. Return true if you handled attachment preview.
* Return false to let [InAppChatFragment] handle attachment preview.
*
* @param url attachment url
* @param type attachment type
* @param caption attachment caption
* @return true if attachment preview has been handled, false otherwise
*/
override fun onAttachmentPreviewOpened(
url: String?,
type: String?,
caption: String?
): Boolean {
return false
}
/**
* Called by default InAppChat's Toolbar back navigation logic to exit chat. You are supposed to hide/remove [InAppChatFragment].
*/
override fun onExitChatPressed() {
supportFragmentManager
.beginTransaction()
.remove(fragment)
.commit()
}
}
//3. Set errors handler
fragment.errorsHandler = object : InAppChatFragment.ErrorsHandler {
override fun handlerError(error: String) {
//Your custom handling of general error or use a default handler
fragment.defaultErrorsHandler.handlerError(error)
}
override fun handlerWidgetError(error: String) {
//Your custom handling of Livechat widget error or use default handler
fragment.defaultErrorsHandler.handlerWidgetError(error)
}
override fun handlerNoInternetConnectionError(hasConnection: Boolean) {
//Your custom handling of missing network connection error or use default handler
fragment.defaultErrorsHandler.handlerNoInternetConnectionError(hasConnection)
}
}
//4. Add fragment to your activity
supportFragmentManager
.beginTransaction()
.replace(R.id.yourFragmentContainer, fragment, "chatFragmentTag")
.commit()
}
}
expand to see Java code
class MainActivity extends AppCompatActivity {
private InAppChatFragment fragment = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1. Create instance and set UI components visibility
fragment = new InAppChatFragment();
fragment.setWithToolbar(true);
fragment.setWithInput(false);
//2. Set events listener
fragment.setEventsListener(new InAppChatFragment.EventsListener() {
/**
* Called once chat has been loaded and connection established.
*
* @param controlsEnabled true if chat is loaded and connected without errors, false otherwise
*/
@Override
public void onChatLoaded(boolean controlsEnabled) {}
/**
* Chat connection has been stopped.
*/
@Override
public void onChatDisconnected() {}
/**
* Chat connection has been re-established.
*/
@Override
public void onChatReconnected() {}
/**
* Chat controls visibility has changed.
*
* @param isVisible true if controls are visible, false otherwise
*/
@Override
public void onChatControlsVisibilityChanged(boolean isVisible) {}
/**
* Chat view has changed.
*
* @param widgetView current chat view
*/
@Override
public void onChatViewChanged(@NonNull InAppChatWidgetView widgetView) {}
/**
* Chat [WidgetInfo] has been updated.
*
* @param widgetInfo updated widget info
*/
@Override
public void onChatWidgetInfoUpdated(@NonNull WidgetInfo widgetInfo) {}
/**
* Chat theme has changed.
*
* @param widgetThemeName name of the applied theme
*/
@Override
public void onChatWidgetThemeChanged(@NonNull String widgetThemeName) {}
/**
* Chat message has been received.
*
* @param rawMessage raw message received by the chat
*/
@Override
public void onChatRawMessageReceived(@NonNull String rawMessage) {}
/**
* Called when attachment from chat has been interacted.
*
* It allows you to handle attachment preview on your own. Return true if you handled attachment preview.
* Return false to let [InAppChatFragment] handle attachment preview.
*
* @param url attachment url
* @param type attachment type
* @param caption attachment caption
* @return true if attachment preview has been handled, false otherwise
*/
@Override
public boolean onAttachmentPreviewOpened(@Nullable String url, @Nullable String type, @Nullable String caption) {
return false;
}
/**
* Called by default InAppChat's Toolbar back navigation logic to exit chat. You are supposed to hide/remove [InAppChatFragment].
*/
@Override
public void onExitChatPressed() {
getSupportFragmentManager()
.beginTransaction()
.remove(fragment)
.commit();
}
});
//3. Set errors handler
fragment.setErrorsHandler(new InAppChatFragment.ErrorsHandler() {
@Override
public void handlerError(@NonNull String error) {
//Your custom handling of general error or use a default handler
fragment.getDefaultErrorsHandler().handlerError(error);
}
@Override
public void handlerWidgetError(@NonNull String error) {
//Your custom handling of Livechat widget error or use default handler
fragment.getDefaultErrorsHandler().handlerWidgetError(error);
}
@Override
public void handlerNoInternetConnectionError(boolean hasConnection) {
//Your custom handling of missing network connection error or use default handler
fragment.getDefaultErrorsHandler().handlerNoInternetConnectionError(hasConnection);
}
});
//4. Add fragment to your activity
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.yourFragmentContainer, fragment, "chatFragmentTag")
.commit();
}
}
class InAppChatFragment {
/**
* Returns true if chat is loaded and multithread feature is enabled, otherwise returns false.
*/
val isMultiThread: Boolean
/**
* [InAppChatFragment] events listener allows you to listen to chat related events.
* Your in-app chat events listener set using [InAppChat.setEventsListener] is used as initial default value.
*/
var eventsListener: InAppChatFragment.EventsListener? = InAppChat.getInstance(context).eventsListener
/**
* Allows you to set custom [InAppChatFragment.ErrorsHandler] handler to process chat errors on your own.
*/
var errorsHandler: InAppChatFragment.ErrorsHandler
val defaultErrorHandler: InAppChatFragment.ErrorsHandler
/**
* Allows you to control presence of InAppChatFragment's Toolbar.
* If you want to use your own Toolbar, set it to false. Default value is true.
*
* When you use own Toolbar it is up to you to handle back navigation logic.
* You can use [InAppChatFragment.navigateBackOrCloseChat] for default back navigation logic,
* what handles internal multithread widget navigation together with android native navigation.
* In case you want to handle back navigation on your own, there is [InAppChatFragment.showThreadList]
* to navigate from [InAppChatWidgetView.THREAD] back to [InAppChatWidgetView.THREAD_LIST] in multithread widget.
*/
var withToolbar: Boolean = true
/**
* Allows you to control presence of InAppChatFragment's message input.
* If you want to use your own message input, set it to false. Default value is true.
*
* When you use own message input it is up to you to handle message and attachment sending logic
* including request Android permissions for attachment picker.
* You can reuse provided [InAppChatInputView] or create custom UI.
* Use [InAppChatFragment.sendChatMessage] to send message.
* Use [InAppChatFragment.sendChatMessageDraft] to send draft message.
*/
var withInput: Boolean = true
/**
* Allows to stop chat connection when fragment is hidden.
* Chat is reconnected automatically once fragment is shown again.
* Default value is false.
*
* By chat connection you can control push notifications.
* Push notifications are active only when chat connection is not active.
*
* It calls [InAppChatView.stopConnection] when fragment is hidden and [InAppChatView.restartConnection] once fragment is visible again.
*/
var disconnectChatWhenHidden: Boolean = false
/**
* Allows to enable/disable back press handling logic.
* If true, it triggers default back navigation logic [navigateBackOrCloseChat], useful especially for multithread widgets.
* If false, back press events are not handled.
* It does not affect ActionBar back button.
*
* Default value is true.
*/
var handleBackPress: Boolean = true
/**
* Set the language of the Livechat Widget.
*
* It does nothing if [InAppChatFragment] is not attached.
*
* @param locale locale's language is used by Livechat Widget and native parts
*/
fun setLanguage(locale: Locale)
/**
* Set contextual data of the Livechat Widget.
*
* If the function is called when [InAppChatFragment] is attached and the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
*
* Every function invocation will overwrite the previous contextual data.
*
*
* @param data contextual data in the form of JSON string
* @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
* @see [InAppChatFragment.EventsListener.onChatLoaded] to detect if chat is loaded
*/
fun sendContextualData(data: String, allMultiThreadStrategy: Boolean)
/**
* Navigates Livechat widget from [InAppChatWidgetView.THREAD] back to [InAppChatWidgetView.THREAD_LIST]
* destination in multithread widget. It does nothing if widget is not multithread.
*
* It does nothing if [InAppChatFragment] is not attached.
*/
fun showThreadList()
/**
* Sends draft message to be show in chat to peer's chat.
*
* It does nothing if [InAppChatFragment] is not attached.
*
* @param draft message
*/
fun sendChatMessageDraft(draft: String)
/**
* Sends message to the chat with optional [InAppChatMobileAttachment].
*
* It does nothing if [InAppChatFragment] is not attached.
*
* @param message message to be send, max length allowed is 4096 characters
* @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)
/**
* Set the theme of the Livechat Widget.
* You can define widget themes in <a href="https://portal.infobip.com/apps/livechat/widgets">Live chat widget setup page</a> in Infobip Portal, section `Advanced customization`.
* Please check widget <a href="https://www.infobip.com/docs/live-chat/widget-customization">documentation</a> for more details.
*
* Function allows to change widget theme while chat is shown - in runtime.
* If you set widget theme before [InAppChatFragment] is shown the theme will be used once chat is loaded.
*
* It does nothing if [InAppChatFragment] is not attached.
*
* @param widgetThemeName unique theme name, empty or blank value is ignored
*/
fun setWidgetTheme(widgetThemeName: String)
/**
* Executes back navigation. In multithread widget it handles internal navigation
* from [InAppChatWidgetView.THREAD] back to [InAppChatWidgetView.THREAD_LIST] using
* [InAppChatFragment.showThreadList], otherwise it triggers [InAppChatFragment.EventsListener.onExitChatPressed] event
* and [InAppChatFragment.InAppChatActionBarProvider.onInAppChatBackPressed].
*
* It is default InAppChatFragment back navigation logic.
*/
fun navigateBackOrCloseChat()
}
expand to see Java code
public class InAppChatFragment {
public boolean isMultiThread();
public void setEventListener(@Nullable InAppChatFragment.EventListener eventListener);
@Nullable public InAppChatFragment.EventListener getEventListener();
public void setErrorsHandler(@NotNull InAppChatFragment.ErrorsHandler errorsHandler);
@NotNull public InAppChatFragment.ErrorsHandler getErrorsHandler();
@NotNull public InAppChatFragment.ErrorsHandler getDefaultErrorsHandler();
public void setWithToolbar(@NotNull Boolean withToolbar);
@NotNull public Boolean getWithToolbar();
public void setWithInput(@NotNull Boolean withInput);
@NotNull public Boolean getWithInput();
public void setDisconnectChatWhenHidden(@NotNull Boolean disconnect);
@NotNull public Boolean getDisconnectChatWhenHidden();
public void setHandleBackPress(@NotNull Boolean handleBackPress);
@NotNull public Boolean getHandleBackPress();
public void setLanguage(@NotNull Locale locale);
public void sendContextualData(@NotNull String data, @NotNull Boolean allMultiThreadStrategy);
public void showThreadList();
public void sendChatMessageDraft(@NotNull String draft);
public void sendChatMessage(@Nullable String message);
public void sendChatMessage(@Nullable String message, @Nullable InAppChatMobileAttachment attachment);
public void setWidgetTheme(@NotNull String widgetThemeName);
public void navigateBackOrCloseChat();
}
Full code of example integration of InAppChatView
can be checked in the ChatExample application.
Starting from 4.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:
- 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>
- Inject Activity/Fragment's
Lifecycle
intoInAppChatView
.
- To get Activity's Lifecycle call
getLifecycle()
- To get Fragment's Lifecycle call
getViewLifecycleOwner().getLifecycle()
- In order to support multiple chat threads feature, you have to implement
InAppChatView.EventsListener
interface where you will obtain multiple useful callbacks, except anothervoid onChatViewChanged(InAppChatWidgetView widgetView)
one important for handling InAppChat internal navigation. - (Optional) Handle InAppChat's errors on your own by implementing
InAppChatView.ErrorsHandler
interface.InAppChatView
exposes its default error handler by callinginAppChatView.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 onChatDisconnected() {
//Chat was disconnected, blank page is loaded.
}
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
}
override fun onChatWidgetThemeChanged(widgetThemeName: String) {
//Applied widget theme name
}
override fun onChatRawMessageReceived(rawMessage: String) {
//You can use raw message for further processing on your side
}
}
//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(hasConnection: Boolean) {
//Your custom handling of missing network connection error or use default handler
inAppChatView.defaultErrorsHandler.handlerNoInternetConnectionError(hasConnection)
}
}
}
}
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 onChatDisconnected() {
//Chat was disconnected, blank page is loaded.
}
@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
}
@Override
public void onChatWidgetThemeChanged(@NonNull String widgetThemeName) {
//Applied widget theme name
}
@Override
public void onChatRawMessageReceived(@NonNull String rawMessage) {
//You can use raw message for further processing on your side
}
});
//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(@NonNull Boolean hasConnection) {
//Your custom handling of missing network connection error or use default handler
inAppChatView.getDefaultErrorsHandler().handlerNoInternetConnectionError(hasConnection);
}
});
}
}
InAppChatView
provides you options to set language, create message with attachment, send message draft, send contextual data, execute internal chat navigation in case you use multiple chat threads and much more.
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].
*
* Chat connection is established and stopped based on provided [Lifecycle].
* Chat connection is active only when [Lifecycle.State] is at least [Lifecycle.State.STARTED].
*
* @param lifecycle lifecycle of android Activity or Fragment
*/
fun init(lifecycle: Lifecycle)
/**
* Load chat. Use it to re-establish chat connection when you previously called [stopConnection].
*
* It is not needed to use it in most cases as chat connection is established and stopped based on [Lifecycle] provided in [init].
* Chat connection is active only when [Lifecycle.State] is at least [Lifecycle.State.STARTED].
*
* By chat connection you can control push notifications.
* Push notifications are suppressed while the chat is loaded.
*
* To detect if chat is loaded use [isChatLoaded] or [EventsListener.onChatLoaded] event from [EventsListener].
*/
fun restartConnection()
/**
* Load blank page, chat connection is stopped.
*
* It is not needed to use it in most cases as chat connection is established and stopped based on [Lifecycle] provided in [init].
* Chat connection is stopped when [Lifecycle.State] is below [Lifecycle.State.STARTED].
*
* By chat connection you can control push notifications.
* Push notifications are active only when chat connection is not active.
*
* Can be used to enable chat's push notifications when [InAppChatView] is not visible.
* Use [restartConnection] to reestablish chat connection.
*
* To detect if chat connection is stopped use [isChatLoaded] or [EventsListener.onChatDisconnected] event from [EventsListener].
*/
fun stopConnection()
/**
* 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.
*
* If the function is called when the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
*
* Every function invocation will overwrite the previous contextual data.
*
* @param data contextual data in the form of JSON string
* @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
* @see [InAppChatView.EventsListener.onChatLoaded] to detect if chat is loaded
*/
fun sendContextualData(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 sendChatMessageDraft(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)
/**
* Set the theme of the Livechat Widget.
* You can define widget themes in <a href="https://portal.infobip.com/apps/livechat/widgets">Live chat widget setup page</a> in Infobip Portal, section `Advanced customization`.
* Please check widget <a href="https://www.infobip.com/docs/live-chat/widget-customization">documentation</a> for more details.
*
* Function allows to change widget theme while chat is shown - in runtime.
* If you set widget theme before chat is initialized by [InAppChatView.init] the theme will be used once chat is loaded.
*
* @param widgetThemeName unique theme name, empty or blank value is ignored
*/
fun setWidgetTheme(widgetThemeName: String)
}
expand to see Java code
public class InAppChatView {
public void init(@NotNull Lifecycle lifecycle);
public void restartConnection();
public void stopConnection();
public void setLanguage(@NotNull Locale locale);
public void sendContextualData(@NotNull String data, @NotNull Boolean allMultiThreadStrategy);
public void showThreadList();
public void sendChatMessageDraft(@NotNull String draft);
public void sendChatMessage(@Nullable String message);
public void sendChatMessage(@Nullable String message, @Nullable InAppChatMobileAttachment attachment);
public boolean isChatLoaded();
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();
public void setWidgetTheme(@NotNull String widgetThemeName);
}
In-app chat consists of native Android views and Livechat widget presented in WebView
. Navigation toolbar and chat input are done using native Android views. Livechat widget shows messages list. You can customize native Android views and Livechat widget separately. To customize native parts of In-app chat you must provide Android theme. Read more about Livechat widget customization options in Livechat widget theme section. Using combination of both, Android theme and Livechat widget theme, you can fully customize In-app chat.
For higher integration flexibility over In-app chat, you can display an In-app chat as view and avoid all not necessary native Android views and use only Livechat widget.
Version 4.0.0 onwards introduces a new approach to customize the In-app chat with new attributes. Simultaneously, we have deprecated old customization approach while there is still fallback to the old customization attributes if the new ones are not present.
Final value for every customizable attribute is resolved from multiple source-by-source priority. The source with the highest priority defines a final attribute value. If source does not define an attribute value, there is fallback to the source with lower priority.
Sources by priority:
-
InAppChatTheme
provided in runtime - New-approach
IB_AppTheme.Chat
android theme attribute defined in xml, with itemsibChatToolbarStyle
,ibChatAttachmentToolbarStyle
,ibChatInputStyle
andibChatStyle
- Old-approach
IB_AppTheme.Chat
android theme attribute defined in xml, with itemscolorPrimary
,colorPrimaryDark
,colorControlNormal
andtitleTextColor
- LiveChat widget theme
- In-app chat default theme
To customize the In-app chat you have to define your own custom theme. There are two ways to do that:
- In application's
styles.xml
with nameIB_AppTheme.Chat
. The In-app chat offers 4 theme attributes, each to customize separate part/view of the 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>
- In code, you can pass
InAppChatTheme
toInAppChat.setTheme()
, which provides same customization as the xml approach.
InAppChat.getInstance(context).setTheme(
InAppChatTheme(
InAppChatToolbarStyle(), //chat toolbar
InAppChatToolbarStyle(), //attachment toolbar
InAppChatStyle(),
InAppChatInputViewStyle()
)
)
expand to see Java code
InAppChat.getInstance(context).setTheme(
new InAppChatTheme(
new InAppChatToolbarStyle(), //chat toolbar
new InAppChatToolbarStyle(), //attachment toolbar
new InAppChatStyle(),
new InAppChatInputViewStyle()
)
);
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="ibChatSaveAttachmentMenuItemIcon">@drawable/ic_chat_save</item> <!-- ibChatAttachmentToolbarStyle only -->
<item name="ibChatMenuItemsIconTint">@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>
ibChatTitleTextColor
value has precedent overibChatTitleTextAppearance
'stextColor
attribute value. Same applies toibChatSubtitleTextColor
andibChatSubtitleTextAppearance
.
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>
ibChatNetworkConnectionErrorTextColor
value has precedent overibChatNetworkConnectionErrorTextAppearance
'stextColor
attribute value.
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="ibChatInputAttachmentBackgroundColor">@android:color/white</item>
<item name="ibChatInputAttachmentBackgroundDrawable">@null</item>
<item name="ibChatInputAttachmentIcon">@null</item>
<item name="ibChatInputAttachmentIconTint">@android:color/black</item>
<item name="ibChatInputSendBackgroundColor">@android:color/white</item>
<item name="ibChatInputSendBackgroundDrawable">@null</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>
ibChatInputTextColor
value has precedent overibChatInputTextAppearance
'stextColor
attribute value.ibChatInputAttachmentIconTint
andibChatInputSendIconTint
support color state list resource type.
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 4.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 4.0.0
Certain attributes of built-in chat view are customizable through resources.
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>
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>
Version 6.3.0 onwards introduces a new option to set Livechat widget theme. Livechat widget themes are defined on the Live chat widget setup page on Infobip Portal. You can define multiple custom themes and customize various widget attributes, read Livechat documentation to get information about all possible widget customization options.
To set Livechat theme in In-app chat you must:
- Define the name and values of your theme(s) in a JSON format, under widget section Theme -> Advance Customisation, in Infobip Portal.
- Once you know the names of your themes, you can use following function in runtime, and the customisation will automatically be applied:
InAppChat.getInstance(context).setWidgetTheme("myThemeName")
expand to see Java code
InAppChat.getInstance(context).setWidgetTheme("myThemeName");
The correct way to deal with dark and light mode is to set Android theme together with Livechat widget theme in run-time, as explained in previous section. This means, you are responsible for checking the current system mode, and apply the desired themes. The old way of dealing with dark mode is now deprecated, and its use is not recommended at all. It will be removed in a future release.
Set title and message body in in-app chat notifications and override default values.
Default value for title is Chat message
.
Default value for body is original message content from push notification.
To use default values again you have to set setChatPushTitle(null)
and setChatPushBody(null)
.
InAppChat.getInstance(context).setChatPushTitle("Custom chat push title")
InAppChat.getInstance(context).setChatPushBody("Custom chat push body")
expand to see Java code
InAppChat.getInstance(context).setChatPushTitle("Custom chat push title");
InAppChat.getInstance(context).setChatPushBody("Custom chat push body");
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()));
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 SDK provides you multiple useful chat related events. Based on the approach you use to display a chat, there are different ways to subscribe for chat events. If you display chat:
- as
InAppChatScreen
orInAppChatFragment
with assisted approach, you can observe the events usingInAppChatEventsListener
interface:InAppChat.getInstance(context).setEventsListener(InAppChatEventsListener)
- as
InAppChatFragment
with full ownership approach, you can observe the events usingInAppChatFragment.EventsListener
interface:InAppChatFragment.eventsListener = object : InAppChatFragment.EventsListener { //TODO override interface callbacks }
- as
InAppChatView
, you can observe the events usingInAppChatView.EventsListener
interface:InAppChatView.eventsListener = object : InAppChatView.EventsListener { //TODO override interface callbacks }
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 view in InAppChat is changed. |
IN_APP_CHAT_AVAILABILITY_UPDATED |
Boolean telling if chat is available | Triggered when chat availability is updated. |
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()));
Action name to subscribe to: org.infobip.mobile.messaging.chat.CHAT_CONFIGURATION_SYNCED
.
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);
}
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
Action name to subscribe to: org.infobip.mobile.messaging.chat.CHAT_AVAILABILITY_UPDATED
. Receiving event data in BroadcastReceiver:
override fun onReceive(context: Context, intent: Intent) {
val isChatAvailable = intent.getStringExtra(BroadcastParameter.EXTRA_IS_CHAT_AVAILABLE)
}
expand to see Java code
@Override
public void onReceive(Context context, Intent intent) {
String isChatAvailable = intent.getStringExtra(BroadcastParameter.EXTRA_IS_CHAT_AVAILABLE);
}
Starting from 1.0.3 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"/>
...
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" /> ...
Add
requestLegacyExternalStorage="true"
toAndroidManifest.xml
to prevent issues with capturing attachments from camera for Android 10+ devices.<manifest ... > <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Images captured from camera saved to
/Pictures/<Your app name>/InAppChat
folder and
- If size is more than 5MB, image quality will be set to 80%
- If size is more than 10MB image also will be scaled down in 2 times.
Media type | File size | File format |
---|---|---|
image | 10MB | JPG, JPEG, PNG |
video | 10MB | MP4 |
Starting from 1.0.3 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" />
...
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 receiver 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);
}
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");
It is possible to send contextual data / metadata to Infobip’s Conversations via the In-App chat SDK. Data can be sent several times but only last sent data are stored in conversation. Every sent data will overwrite the previously sent contextual data.
There are two possible scenarios:
- Contextual data is sent before chat is present and loaded. In-app chat SDK stores the data and automatically sends it once the chat is loaded.
- Contextual data is sent when chat is present and loaded. In a single thread, the data will be sent to an open conversation. In multi-thread, LiveChat widget tracks a list of open conversations, and based on the strategy, it will either send it to a currently
ACTIVE
conversation orALL
conversations.
In-app chat supports having multiple conversations between an agent and a customer. Considering this, In-app chat needs to know to which conversations send contextual data:
-
ACTIVE
- sends metadata to a currently active conversation -
ALL
- sends metadata to all conversations between an agent and a customer (This field has no impact in case of a single-thread LiveChat widget.)
In-app chat SDK function to send contextual data has two parameters:
- The mandatory data, sent as string, in a format of JavaScript objects and values (for guidance, it must be accepted by JSON.stringify())
- An optional parameter, a multithread strategy that can be omitted and will use
false
as a default value. Possible values are:-
true
= metadata sent toALL
non-closed conversations for a widget -
false
= metadata sent toACTIVE
only conversation for a 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);
If you use InAppChat as View you must use
InAppChatView
public function to send contextual data. If you use InAppChat as Fragment you must useInAppChatFragment
public function to send contextual data.
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.
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.
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)
//you can pass "true" as second argument to disconnect chat when fragment is hidden to receive push notifications
//InAppChat.getInstance(this).hideInAppChatFragment(supportFragmentManager, true)
}
}
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());
//you can pass "true" as second argument to disconnect chat when fragment is hidden to receive push notifications
//InAppChat.getInstance(MainActivity.this).hideInAppChatFragment(getSupportFragmentManager());
}
}
It is possible to authenticate an user before accesing the InAppChat, given you have enabled this feature in the LiveChat widget.
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).
If you face any issue using the InAppChat, specially on the first time integration, we encourage to try your Example application, as this may give you a hint of potential mistakes. An example of the most common issues our integrators face:
- The chat content appears blank, and the text input fields is disabled.
InAppChat should only be presented once it is activated using InAppChat.getInstance(context).activate()
and valid pushRegistrationId
is obtained. If you try to present it otherwise, the connection won't be established, and chat will be blank. There are also another reasons why InAppChat is not loaded, from incorrect/missing infobip_application_code
, to badly defined Livechat widget in Infobip's web portal. Usually, the logs from Logcat will give you a hint of the issue, and re-checking this guide, or comparing with our Example application, should be enough to successfully integrate InAppChat. But if the issue continues, don't hesitate to contact our support or ask for help here in our repository's Issues section.
- My InAppChat is activated and I have
pushRegistrationId
, but the chat keeps appearing blank.
If your Livechat widget setup in Installation and Security tab has enabled Authenticate users on mobile using JSON Web Token, make sure you provided to InAppChat a correct JSON Web Token. If you enabled it by mistake, disable it.
- I get in the logs an error about no
pushRegistrationId
.
Please re-check the quick start guide and the steps mentioned above.
- When a chat push notification is tapped, the app is invoked, and remains wherever it previously was - but I want it to display the chat related to the push notification I tapped.
InAppChat cannot present itself: if needs the parent application (your app) to present it. So, when a push notification is tapped, your app needs to recognise that event, and present the chat if you wish so. You can detect when a push notification is tapped, its nature and content, by listening to our library-events. For this case, the event you are looking for is called NOTIFICATION_TAPPED
.
- Library events
- Server errors
- Users and installations
- Messages and notifications management
- Inbox
Geofencing APIDEPRECATED- Android Manifest components
- Privacy settings
- In-app chat