-
Notifications
You must be signed in to change notification settings - Fork 17
In‐app chat
Find more info about Live chat product on Infobip docs.
- Intro
- Display In-app chat view
- Customize In-app chat view
- Handle notification taps
- Library events
- Sending attachments
- Attachments preview
- Supported attachment types
- Advanced
- Unread chat push messages counter
- Changing localization
- Sending Contextual Data / Metadata
- Multiple chat threads
- Authenticated chat
- Example application
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:4.+@aar"
implementation 'androidx.exifinterface:exifinterface:1.1.0' // can be any 1.+ version, 1.1.0 is an example
}
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.
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).inAppChatView().show()
expand to see Java code
InAppChat.getInstance(context).inAppChatView().show();
It will immediately open chat view activity on top of current activity.
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>
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 library supports following set of library events related to messages as core SDK which you can receive with intents in broadcast receivers:
Event | Parameters | Description |
---|---|---|
MESSAGE_RECEIVED |
Message.createFrom(intent) |
Triggered when the message is received by the SDK |
NOTIFICATION_TAPPED |
Message.createFrom(intent) |
Triggered when notification for particular message is tapped by user |
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 messageReceiver = object: BroadcastReceiver() {
override fun onReceive(context:Context, intent: Intent) {
val message = Message.createFrom(intent)
// process message
}
}
LocalBroadcastManager.getInstance(context).registerReceiver(messageReceiver, IntentFilter(Event.MESSAGE_RECEIVED.key))
expand to see Java code
private final BroadcastReceiver messageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Message message = Message.createFrom(intent);
// process message
}
};
LocalBroadcastManager.getInstance(context).registerReceiver(messageReceiver, new IntentFilter(Event.MESSAGE_RECEIVED.getKey()));
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"/>
...
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 starting from 5.2.4 version:
- 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.
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" />
...
Media type | File size | File format |
---|---|---|
image | 10MB | JPG, JPEG, PNG |
video | 10MB | MP4 |
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 view 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):
- Create layout in your activity.xml to use it as container for fragment.
For
MainActivity
from 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 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, callinggetSupportFragmentManager()
;
InAppChat.getInstance(context).showInAppChatFragment(fragmentManager, containerId);
- 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());
}
...
}
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);
}
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 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:
- The mandatory data, sent as string, in the format of Javascript objects and values (for guidance, it must be accepted by JSON.stringify())
- 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);
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?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
//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) {
//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());
}
}
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).inAppChatView().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).inAppChatView().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 have any questions or suggestions, feel free to send an email to support@infobip.com or create an issue.
- Library events
- Server errors
- Users and installations
- Messages and notifications management
- Inbox
Geofencing API- DEPRECATED- Android Manifest components
- Privacy settings
- In-app chat
- Infobip RTC calls and UI
- Backup rules