Mobile chat for Android
Using the Pyrus SDK for Android, you can embed chat in your mobile app. Your clients can contact support directly from your app and get help. Your support specialists will process tickets in Pyrus even when the user communicates with you from a messenger app.
You can use the default chat setup or customize it for your app. You can also receive files and subscribe users to push notifications about new messages.
This guide will help developers embed Pyrus chat into their app.
Get an App ID
First, connect your app to the Pyrus form where support team processes clients’ requests. To get started, you need an administrator account in Pyrus with access to the form settings. If you aren’t a form administrator, ask a colleague who has this access.
Go to the service ticket form configuration page and find Integrations. Click Set Up next to Mobile App Chat.
Copy App ID from the Credentials section.
Prepare the project
Add to the build.gradle file:
repositories { jcenter() } dependencies { ... implementation 'com.pyrus:servicedesk:1.5.23' }
Get permission to access the phone’s camera and gallery
To let users attach files to messages, grant access to the camera and gallery.
"android.permission.WRITE_EXTERNAL_STORAGE" "android.permission.CAMERA"
Choose the type of authorization
The Pyrus Mobile Chat library can be authorized in one of two ways: anonymously, or externally.
Anonymous authorization makes implementation easier, as the chat is tied to a device. On an authorized device a user can participate in the chat without entering any login info.
The biggest disadvantage of anonymous authorization is that if you use the mobile app on another device, you cannot see the previous chat.
If you want the chat history to be accessible to the same user on multiple devices, you have to set up external authorization. To do this, you have to turn on a web service that tells the system a user has access to the chat.
Please note that anonymous and external authorization are mutually exclusive. If you switch the Pyrus Mobile Chat library from anonymous to external, the previous chat, which was conducted in anonymous authorization mode, will become invisible to mobile app users.
How the authorization service works
In external authorization mode the Pyrus backend does not decide on its own whether a user has access to a chat; it asks a special authorization service, which you have to turn on. Here’s how this works:
The user logs in on a mobile app, and then receives a pair (userID, securityKey) from your backend. The Pyrus Mobile Chat library and the Pyrus backend do not participate at this stage.
When initializing the Pyrus Mobile Chat library, the userID and securityKey definitions are given as parameters.
From then on, whenever any request is sent to the backend (for example, a request for a chat history, or when a user comment is being sent), the Pyrus Mobile Chat library automatically also sends the Pyrus backend these parameters ( userID, securityKey).
Before processing the request, the Pyrus backend verifies your access rights. That’s what it sends the pair ( userID, securityKey) to your authorization web service for.
The authorization web service and your backend communicate to authenticate the parameters (userID, securityKey), and they send the results of that check back to the Pyrus backend.
Upon receipt of confirmation from the authorization service, the Pyrus backend processes the request: it sends the chat history, saves the user’s comments, etc.
The authorization service URL has to be indicated in the form the mobile chat is connected to. To make sure it is, go into the settings of the selected form, and, in the Extensions section, select Mobile app chat.
Then, on the page that opens, enter the URL in the appropriate field.
Initialize the library
When starting the app, invoke the init() method of the PyrusServiceDesk class.
The parameters of the init() method:
- application — an Application class object used by your app.
- appId — your application ID in Pyrus. It’s stored in the settings of the connected form in Pyrus. If you aren’t a form administrator, ask a colleague who has this access to copy the AppID as described in the Get an App ID section.
These parameters are used only for external authorization.
- userID, a String class object. User ID line in the external system. Must stay the same for single user.
- securityKey, a String class object. The user identification line user_id in the external system. Can change for single user, if the system allows it.
Initializing the chat in anonymous authorization mode
public class SampleApp extends Application { @Override public void onCreate() { super.onCreate(); PyrusServiceDesk.init( application: this, appId: "your_app_id" ); } }
Initialization of chat in external authorization mode
public class SampleApp extends Application { @Override public void onCreate() { super.onCreate(); PyrusServiceDesk.init( application: this, appId: "your_app_id", userId: "id_of_current_user", securityKey: "secrutity_key_of_that_user" ); } }
If you send the parameter userId=nil, then anonymous authorization turns on. This is connected to a device, not to a user.
Launch chat UI
To launch the user interface, invoke the start() method of the PyrusServiceDesk class.
The start(activity) method launches the default user interface:
- activity is an Activity class object. It’s used to run the user interface.
To configure the chat appearance, use the start(activity,configuration) method:
- activity is an Activity class object. It’s used to run the user interface.
- configuration is an ServiceDeskConfiguration class object. It’s used for setting up the chat appearance.
public class SampleActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { ... findViewById(R.id.support).setOnClickListener( view -> PyrusServiceDesk.start( /* activity */this, /* configuration */ serviceDeskConfigurationInstance ); } }
Customize the chat
To launch the interface, use the start(activity, configuration) method. To create and configure the ServiceDeskConfiguration object, use the object of the ServiceDeskConfiguration.Builder class.
The methods of the ServiceDeskConfiguration.Builder object:
- setUserName(name) is the username that a support specialist sees in a Pyrus ticket. If a user is logged into the app, you can pass his or her name, email, and other info to this method. It will help your support specialist understand who he or she is talking to and resolve the ticket more quickly.
- setChatTitle(title) is the title of the chat window.
- setWelcomeMessage(message) is the welcome message that the user sees in the chat.
- setThemeColor(color) sets the color of the main elements of the chat interface.
- setAvatarForSupport(drawableResID) sets an icon to use as a support specialist’s avatar. drawableResID is an ID of the resource of the avatar picture.
- build() creates a ServiceDeskConfiguration class object.
new ServiceDeskConfiguration.Builder() .setUserName("Ivan Petrov") .setChatTitle("Support CompanyName") .setWelcomeMessage("Hello! How can I help you?") .setThemeColor(Color.RED) .setAvatarForSupport(R.drawable.logo) .build())
Notifications about new messages
You can use push notifications to notify the user about new messages in the chat. This is the alternative option. It’s easier to implement, but notifications will be delayed and you won’t see a new message’s content. Enable push notifications
To receive notifications about new messages from a support specialist, implement the NewReplySubscriber interface and pass the implementation to the subscribeToReplies() of the PyrusServiceDesk class.
If you're using the Pyrus Mobile Chat library on multiple devices, which you can do in external authorization mode, it's useful for your mobile app to know which new comments have already been read on another device. In this case, the library calls the onNewReply function with a hasUnreadComments parameter equal to false. If the chat is open, the function will not be called even if new comments appear.
public class SampleActivity extends Activity implements NewReplySubscriber { @Override protected void onCreate(Bundle savedInstanceState) ... PyrusServiceDesk.subscribeToReplies(this) ... } @Override protected void onDestroy() { ... PyrusServiceDesk.unsubscribeFromReplies(this); ... } @Override public void onNewReply( boolean hasUnreadComments, @Nullable String lastCommentText, int lastCommentAttachmentsCount, @Nullable List<String> lastCommentAttachments, long utcTime ) { ... } }
Enabling push notifications
You can use push notifications to inform the user about new messages in the chat. Here’s how it works:
When launching, your app communicates with Google’s push notification server to get its device token, which you then forward to your provider server. Your server includes that token with any notifications it sends.
To subscribe a user to notifications about new messages, register a push token by invoking setPushToken(token, callback) of the PyrusServiceDesk class.
The parameters of the setPushToken(token, callback) method:
- token is a token that is registered in Pyrus. It sends notifications about new messages.
- callback is an implementation of the SetPushTokenCallback interface. Its onResult() method will be evoked when the token registration is completed. It isn’t guaranteed that the onResult() method will be invoked in the same stream with setPushToken(token, callback).
SetPushTokenCallback contains the onResult(@Nullable Exception exception) method. Its exception parameter will be null if the registration is successful, otherwise it will return an error message.
Example:
public class SampleApp extends Application { @Override public void onCreate() { super.onCreate(); PyrusServiceDesk.init( this, "my_app_id" ); PyrusServiceDesk.setPushToken( "my_push_token", exception -> { Log.d("SAMPLE_APP", exception.getMessage()); }); } }
On the application server side, you should implement a webhook to receive notifications about new messages in the app chat. Add the webhook URL in the form settings in Pyrus.
When there is a new message from the support team, a POST request will be sent to the webhook URL. It contains:
ticket_id — the number of the task that the comment is added to.
token — a user's identifier, including:
- user_id — user ID, which is passed with each request
- app_id — mobile application/web chat identifier
- device_id — device identifier
- type — device type: "Android"
comment — information about the new comment:
- comment_id — number of the new comment
- body — comment text
- is_inbound — always false, shows that the comment is from the support team
author — information about the author of the comment:
- name — author's name
- avatar_id — author's avatar identifier
- avatar_color — the color of the author's avatar. Used if avatar_id is not specified.
created_at — the date and time when the comment was created.
attachments — description of the attached files:
- id — file identifier
- name — file name
- size — file size in bytes
Setting up the chat menu
For an enhanced support experience, your users can send files without leaving the chat flow. Users can attach photos taken with the device camera or select images from gallery by default. To add support for other types of files, like configuration files, use the registerFileChooser() method of the PyrusServeDesk class.
PyrusServiceDesk.registerFileChooser(chooser), where chooser is an implementation of the FileChooser interface. To stop using the configured FileChooser, pass null to the method.
FileChooser methods:
- getLabel() is the name of the corresponding menu option.
- getIntent() returns an object of the Intent type, which is used to start the activity. The custom activity that will be invoked with Intent must return the result containing the URI to access the file. You can URI to the result using the intent.setData(uri) method.
Note: the scheme of the URI should be “content”. Otherwise, the comment with the attached file won’t be sent.
public class SampleApp extends Application { @Override public void onCreate() { ... PyrusServiceDesk.registerFileChooser(new FileChooser() { @NonNull @Override public String getLabel() { return "Send logs"; } @NonNull @Override public Intent getIntent() { return new Intent(SampleApp.this, LogChooser.class); } }); } }
Types and methods description
PyrusServiceDesk
This is the main class for working with embeddable chat.
init
public static void init(@NonNull Application application, @NonNull String appId)
Initializes the embeddable Pyrus Service Desk module. You should invoke this method in [Application.onCreate].
Note: do it before other public methods are invoked, or else IllegalStateException will occur.
Parameters
appId | App identifier in Pyrus. |
application | The app where the chat is embedded. |
init ()
@ @objc static public func createWith(_ clientId: String?, userId: String, securityKey: String)
Parameters
userID: | User ID line in the external system. Must stay the same for single user. ble %} |
registerFileChooser
public static void registerFileChooser(@Nullable FileChooser fileChooser)
Specifies the source that will be added to the menu. The user can attach files to messages. The max size of the attached files should be up to [RequestUtils.MAX_FILE_SIZE_MEGABYTES]. Now it is 2 GB.
Parameters
fileChooser | Starts the interface for selecting files. To disable it, pass null to the method. |
setPushToken
public static void setPushToken(@NonNull String token, @NonNull SetPushTokenCallback callback)
Registers your push token. The callback [callback] can be invoked in a stream that is different from the stream where the [setPushToken] was invoked.
Parameters
callback | A callback that is invoked when the token has been registered. If the token is successfully registered, the callback is made without error. |
token | The token to be registered. |
start
public static void start(@NonNull Activity activity)
Starts the default PyrusServiceDesk interface.
Parameters
activity | Starts the customized PyrusServiceDesk interface. |
start
public static void start(@NonNull Activity activity, @NonNull ServiceDeskConfiguration configuration)
Starts the PyrusServiceDesk interface.
Parameters
activity | Starts the PyrusServiceDesk interface. |
configuration | The [ServiceDeskConfiguration] entity that configures the chat interface. |
subscribeToReplies
public static void subscribeToReplies(@NonNull NewReplySubscriber subscriber)
Subscribes [subscriber] to notifications about new messages in the chat.
unsubscribeFromReplies
public static void unsubscribeFromReplies(@NonNull NewReplySubscriber subscriber)
Unsubscribes [subscriber] from notifications about new messages.
onAuthorizationFailed
Is entered when the securityKey and userID parameters have failed the authentication.
ServiceDeskConfiguration.Builder
public class Builder
Creates a custom chat [ServiceDeskConfiguration].
build
public ServiceDeskConfiguration build()
Creates a [ServiceDeskConfiguration] object.
setAvatarForSupport
public Builder setAvatarForSupport(@DrawableRes int drawableResId)
Specifies the identifier of the image resource that’s used as a support specialist’s avatar. By default, the standard icon is used with the color set when the **PyrusServiceDesk.start()** method is invoked. If the color isn’t specified, the background color is #008C8C.
Parameters
ID | Image identifier. |
setChatTitle
public Builder setChatTitle(@NonNull String title)
Contains the text for chat title. By default, it’s “Support”.
Parameters
title | Contains the chat title. |
setThemeColor
public Builder setThemeColor(@ColorInt int color)
Sets chat window color. By default, it’s #008C8C.
Parameters
color | The color of the main elements. |
setUserName
public Builder setUserName(@NonNull String userName)
The username (client’s name) that a support specialist sees in ticket in Pyrus. The name “Guest” is used by default. If a user is logged into the app, you can pass name, email address, and other info to this method.
Parameters
userName | The name of a user. |
setWelcomeMessage
public Builder setWelcomeMessage(@NonNull String message)
The first message that the user sees in the chat. If not specified, the chat will be displayed without a welcome message.
Parameters
message | Welcome message. |
NewReplySubscriber
public interface NewReplySubscriber
This interface implementation can be subscribed to notifications about new messages in the chat using the subscribeToReplies() method of the PyrusServiceDesk class.
onNewReply
void onNewReply( boolean hasUnreadComments, @Nullable String lastCommentText, int lastCommentAttachmentsCount, @Nullable List<String> lastCommentAttachments, long utcTime )
Invoked when a new support message is received.
Parameters
hasUnreadComments: | True if reply subscriber has some unread comments. |
lastCommentText: | Text of last unread comment. Max 500 chars. |
lastCommentAttachmentsCount: | The number of attachments for the last unread comment. |
lastCommentAttachments: | List of attachment names. Max 10 names. |
utcTime: | The time the last unread comment was created in UTC milliseconds. |
FileChooser
public interface FileChooser
To attach files to chat messages, implement the interface and pass it to [PyrusServiceDesk.registerFileChooser].
getIntent
Intent getIntent()
Used to start a file selection menu when a user clicks on the text option contained in [getLabel].
getLabel
String getLabel()
Text that appears in the menu for selecting the file source.
SetPushTokenCallback
public interface SetPushTokenCallback
A callback that is invoked when push token has been registered. Returning without exception means that the token has been successfully registered.
onResult
public void onResult(@Nullable Exception exception)
A method that is invoked when a push token has been registered.
The authorization web service
Receives the command HTTP POST with the parameters:
- app_id: this line is created in Pyrus in the mobile chat settings;
- user_id: this line of up to 100 symbols is the user ID in the external system. This value must never change, and cannot be the same for different users, including former ones;
- security_key: this line of up to 100 symbols is for authenticating the user’s user_id in the external system. In this mode, the logic of the formation and use of the security_key is entirely up to you. We do not recommend using this mode without hash coding the passwords, secret keys, and other parameters that grant users access to any of your systems, or to get authorized on a mobile app.
The expected response:
- if authorization is successful: HTTP 200 OK;
- if the request was formed incorrectly (the wrong fields were filled in, or the security_key is in the wrong format for your system): HTTP 400 Bad Request;
- if authorization fails: HTTP 403 Forbidden.