Multi-Tenancy Support for Android SDKs

Anu Vakkachen
The PayPal Technology Blog
4 min readJun 15, 2021
Photo by Amélie Mourichon on Unsplash

We recently added multi-tenancy support in our Mobile Software Development Kits (SDKs) and learned a lot during that process. I want to share my experience with the technology community as a quick start guide for developers who are interested in making their SDKs multi-tenant friendly.

This article focuses on Android and is based on the architecture, design, and patterns we used in Android Assistant SDK for adding multi-tenancy support.

What is Assistant SDK?

Assistant SDK offers a seamless messaging experience within an app to help app users with their queries. The user starts off by chatting with a bot. If the bot cannot handle the user’s request, the chat will be transferred to a human agent based on agent availability.

Our SDK was already integrated in the PayPal consumer app, so when a new requirement was requested for the Venmo app, we saw this as the right time to add multi-tenancy support.

Why did we need multi-tenancy support?

Assistant SDK offers a personalized user experience based on the signed-in user. This involves Identity Management, which varies across different tenants.

In addition, our SDK has UI components which should maintain a look and feel similar to its tenant. We also wanted to offer tenants an option to pick from different agent platforms.

The following screenshot shows how our chat sheet is rendered in Venmo and PayPal.

Here, the differences are subtle since both have a blue theme. But we can clearly notice differences in the avatar, gripper, minimize button, title, and graphic assets

Venmo chat vs PayPal chat

Let’s get started

The first step was to split our SDK to a Core part and a Tenant specific part. Starting from PayPalAssistantUI SDK, we split the SDK into CoreAssistantUI, PayPalAssistantUI and VenmoAssistantUI.

Core SDK holds the parts that wouldn’t change across tenants. It holds most of the logic and is also highly configurable. Meanwhile, tenant specific SDKs act as thin wrappers that can be used to configure Core.

What can be customized?

At this point, we had to identify what would be uniform and what could be customized. We decided the uniform portion would be the Core components used for displaying chat. We display chats in a bottom sheet with buttons to close and minimize the chat and a gripper that can be used to drag the sheet up or down. Everything that plays a part in initializing and handling these components like fragments, view models, and data observers go into Core and would be uniform.

Android Assistant SDK Architecture

Adding StyleConfig

The next step was to make the Core SDK as configurable as possible, so that each tenant can customize based on their needs.

We started off by adding a style config, which can be used to customize components in the main UI. Based on the configuration passed, it can show or hide different elements and influence their behavior. For instance, the PayPal app doesn’t have a gripper whereas Venmo does.

data class StyleConfig(
val showGripper: Boolean = false,
val showMinimizeChevron: Boolean = true,
val showEndMessage: Boolean = false,
val openContactFormOnError: Boolean = true
)

Customizing Colors, Shape, and Typography

When it came to look and feel, each tenant had a different theme. We wanted to provide an option that would be easy to customize and align with material design guidelines. So, we picked custom styles for our components. Each tenant provides their specific styles that we’ll use for rendering. With this in place, it was easy to apply light grey for PayPal bot message bubbles and change it to light blue for Venmo bubbles.

Venmo bot bubble vs PayPal bot bubble
<style name="coreassistantui_MessagingStyle.PayPal" parent="">
<item name="coreassistantui_colorBotBubble">
?ui_color_grey_100
</item>
<item name="coreassistantui_colorBotText">
?ui_color_grey_700
</item>
<item name="coreassistantui_colorUserBubble">
?ui_color_blue_600
</item>
<item name="coreassistantui_colorUserText">
@android:color/white
</item>
<item name="coreassistantui_colorButtonStroke">
?ui_color_blue_600
</item>
<item name="coreassistantui_colorButtonText">
?ui_color_blue_600
</item>
<item name="coreassistantui_colorMainUITheme">
?ui_color_blue_600
</item>
<item name="coreassistantui_buttonStyle">
@style/coreassistantui_PayPalButton
</item>
<item name="coreassistantui_textAreaStyle">
@style/coreassistantui_PayPalTextArea
</item>
<item name="coreassistantui_textInputLayoutStyle">
@style/coreassistantui_PayPalTextInputLayout
</item>
</style>

We then set this customized style to be used by the SDK for rendering components.

CoreAssistant.setStyle(R.style.coreassistantui_MessagingStyle.PayPal)

Identity Management

Identity Management is an important part to handle; the key here is abstraction. We can use features provided by the PayPal platform, so instead of handling authentication from the SDK, we provide tenants with an option to authenticate themselves and provide us with the result. Each tenant can handle this in their own specific way. This approach allowed the tokens required for authentication to be returned to us by the tenant.

Our SDK accepts an authentication interface during initialization, giving us access to the tokens whenever required.

Splitting data service

Customizing data service was easier than customizing the UI. This layer holds all our data handling logic, including network requests and responses.

We followed the same process for splitting the SDK and ended up with a CoreAssistantDataservice, PayPalAssistantDataservice, and VenmoAssistantDataservice. We made our core service layer generic and added customizations for tenants.

Some SDKs might be able to skip this part depending on the customizable components in the data layer.

--

--