Android UX Helper
Rokt UX Helper is an open source project that helps you render beautiful customer experiences in a server to server environment. You can find and contribute to the project on the Github page.
This document outlines the process for integrating the Rokt UX Helper into your Android app, which works alongside the Server-to-Server integration(S2S) to deliver relevant experiences to your customers as they checkout.
System | Version |
---|---|
UX Helper | 0.4.0 |
Android Version/API Level | 5.0+ (API Level 21) |
Package Manager | Maven / Gradle |
Compose BOM | 2024.09.02 |
Installation Guide
In your module (app-level) Gradle file (usually <project>/<app-module>/build.gradle.kts
or <project>/<app-module>/build.gradle
), add the Rokt UX Helper dependency.
- Kotlin
- Groovy
implementation("com.rokt:roktux:0.1.0")
implementation 'com.rokt:roktux:0.1.0'
Initialize RoktLayout
Add RoktLayout to your Compose view
// Retrieve the experience response from your server
val experienceResponse = viewModel.experienceResponse.collectAsState()
experienceResponse.value?.let { experienceResponse ->
RoktLayout(
experienceResponse = experienceResponse,
location = "RoktEmbedded1",
onUxEvent = { println("RoktEvent: UxEvent Received $it") },
onPlatformEvent = { println("RoktEvent: onPlatformEvent received $it") },
roktUxConfig = RoktUxConfig.builder()
.imageHandlingStrategy(NetworkStrategy())
.build(),
)
}
UX Events
Use the onUXEvent handler to receive real-time feedback on user interactions.
At a minimum you must handle when a RoktUXEvent.OpenUrl event is triggered so you can open the link using the below example.
OpenUrl - onClose
When handling an event of type OpenUrl it is critical to call the onClose callback which will notify the RoktUXHelper to execute some logic like moving to the next offer.
- Kotlin
- Java
openUrlEvent.onClose.invoke(openUrlEvent.id)
openUrlEvent.getOnClose().invoke(openUrlEvent.getId());
- Kotlin
- Java
onUxEvent = { event ->
println("RoktEvent: onUxEvent received $event")
if (event is RoktUxEvent.OpenUrl) {
val openUrlEvent = event as RoktUxEvent.OpenUrl
when (openUrlEvent.type) {
OpenLinks.Internally -> {
// Open AndroidX browser or similar functionality to keep the user in app
val customTabsIntent = CustomTabsIntent.Builder().build()
customTabsIntent.launchUrl(context, Uri.parse(openUrlEvent.url))
openUrlEvent.onClose.invoke(openUrlEvent.id) // This must be called when the user is ready for the next offer
}
OpenLinks.Externally, OpenLinks.Passthrough -> {
// Open external browser allowing user to leave the app
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(openUrlEvent.url))
context.startActivity(intent)
openUrlEvent.onClose.invoke(openUrlEvent.id) // This must be called when the user is ready for the next offer
}
}
}
}
roktUxEvent -> {
// Handle open URL event
// Here is a sample how to open different types of URLs
if (roktUxEvent instanceof RoktUxEvent.OpenUrl openUrlEvent) {
if (openUrlEvent.getType() == OpenLinks.Internally) {
// Open AndroidX browser or similar functionality to keep the user in app
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder().build();
customTabsIntent.launchUrl(context, Uri.parse(openUrlEvent.getUrl()));
openUrlEvent.getOnClose().invoke(openUrlEvent.getId()); // This must be called when the user is ready for the next offer
} else {
// Open external browser allowing user to leave the app
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(openUrlEvent.getUrl()));
context.startActivity(intent);
openUrlEvent.getOnClose().invoke(openUrlEvent.getId()); // This must be called when the user is ready for the next offer
}
}
return null;
}
All events
Event | Description | Params |
---|---|---|
OfferEngagement | Triggered when the user engages with the offer | layoutId: String |
PositiveEngagement | Triggered when the user positively engages with the offer | layoutId: String |
LayoutInteractive | Triggered when a layout has been rendered and is interactable | layoutId: String |
LayoutReady | Triggered when a layout is ready to display but has not rendered content yet | layoutId: String |
LayoutClosed | Triggered when a layout is closed by the user | layoutId: String |
LayoutCompleted | Triggered when the offer progression reaches the end and no more offers are available to display | layoutId: String |
LayoutFailure | Triggered when a layout could not be displayed due to some failure | layoutId: String (optional) |
OpenUrl | Triggered when a link needs to be opened | url: String, id: String, type: OpenLinks (internally/externally/Passthrough), onClose: (id: String) -> Unit, onError: (id: String, throwable: Throwable) |
PlatformEvents
Platform events are an essential part of integration and they have to be sent to Rokt via your backend. To ease integration the object is of type RoktPlatformEventsWrapper
, implements @Serializable and offers a toJsonString
function.
- Kotlin
- Java
onPlatformEvent = { events ->
// Send these platform events to Rokt API including the event body
}
roktPlatformEvents -> {
// Send these platform events to Rokt API including the event body
return null;
}
You can find a full list of events here.
Optional: App Configurations
Color mode
Color mode allows you to fix the theme used when displaying Rokt layouts. By default Rokt matches the current system theme.
- Kotlin
- Java
val config = RoktUxConfig.builder()
.colorMode(ColorMode.DARK)
.build()
final RoktUxConfig build = new RoktUxConfig.builder()
.colorMode(ColorMode.DARK)
.build();
RoktUxColorMode object
Value | Description |
---|---|
LIGHT | Application is in Light Mode |
DARK | Application is in Dark Mode |
SYSTEM | Application defaults to System Color Mode |
ImageLoader
In Rokt UX Helper coil is used for loading images, UX Helper has several built in image loaders that you can utilise in your app. The easiest and recommended approach to implement is NetworkStrategy
, however depending on your networking library or preferences you can create custom image loading strategies.
- Kotlin
- Java
val roktUxConfig = RoktUxConfig.builder()
.imageHandlingStrategy(NetworkStrategy())
.build()
final roktUxConfig = new RoktUxConfig.builder()
.imageHandlingStrategy(new NetworkStrategy())
.build();
Fonts
val fontFamily = remember {
val robotoLight = Font(resId = R.font.roboto_light, weight = FontWeight.W100)
val robotoItalic = Font(resId = R.font.roboto_italic, weight = FontWeight.W400)
FontFamily(robotoLight, robotoItalic)
}
RoktUxConfig.builder()
.composeFontMap(mapOf("roboto" to fontFamily))
.build()
Installation Guide
In your module (app-level) Gradle file (usually <project>/<app-module>/build.gradle.kts
or <project>/<app-module>/build.gradle
), add the Rokt UX Helper dependency.
- Kotlin
- Groovy
implementation("com.rokt:roktux:0.1.0")
implementation 'com.rokt:roktux:0.1.0'
Initialize RoktLayout
To begin using the Rokt UX Helper you need to add the layout to the relevant XML for your app. In the example we use RoktEmbedded1
to indicate which layout is being loaded into this view, this has to match the setup of your page.
<com.rokt.roktux.RoktLayoutView
android:id="@+id/roktLayoutView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:location="RoktEmbedded1" />
- Kotlin
- Java
val roktLayoutView: RoktLayoutView = findViewById(R.id.roktLayoutView)
val experienceResponse: String = // Retrieve the experience response from your server
val roktUxConfig = RoktUxConfig.builder()
.build()
roktLayoutView.loadLayout(
experienceResponse = experienceResponse,
roktUxConfig,
onUxEvent = { event ->
// Handle UX events here
},
onPlatformEvent = { platformEvent ->
// Send these platform events to Rokt API
},
)
final RoktLayoutView roktLayoutView = findViewById(R.id.roktLayoutView);
final String experienceResponse = "";
final RoktUxConfig roktUxConfig = RoktUxConfig.builder()
.build()
roktLayoutView.loadLayout(
experienceResponse,
roktUxConfig,
roktUxEvent -> {
// Handle UX events here
return null;
},
roktPlatformEvent -> {
// Send these platform events to Rokt API
return null;
}
);
UX Events
Use the onUXEvent handler to receive real-time feedback on user interactions.
At a minimum you must handle when a RoktUXEvent.OpenUrl event is triggered so you can open the link using the below example.
OpenUrl - onClose
When handling an event of type OpenUrl it is critical to call the onClose callback which will notify the RoktUXHelper to execute some logic like moving to the next offer.
- Kotlin
- Java
openUrlEvent.onClose.invoke(openUrlEvent.id)
openUrlEvent.getOnClose().invoke(openUrlEvent.getId());
- Kotlin
- Java
onUxEvent = { event ->
println("RoktEvent: onUxEvent received $event")
if (event is RoktUxEvent.OpenUrl) {
val openUrlEvent = event as RoktUxEvent.OpenUrl
when (openUrlEvent.type) {
OpenLinks.Internally -> {
// Open AndroidX browser or similar functionality to keep the user in app
val customTabsIntent = CustomTabsIntent.Builder().build()
customTabsIntent.launchUrl(context, Uri.parse(openUrlEvent.url))
openUrlEvent.onClose.invoke(openUrlEvent.id) // This must be called when the user is ready for the next offer
}
OpenLinks.Externally, OpenLinks.Passthrough -> {
// Open external browser allowing user to leave the app
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(openUrlEvent.url))
context.startActivity(intent)
openUrlEvent.onClose.invoke(openUrlEvent.id) // This must be called when the user is ready for the next offer
}
}
}
}
roktUxEvent -> {
// Handle open URL event
// Here is a sample how to open different types of URLs
if (roktUxEvent instanceof RoktUxEvent.OpenUrl openUrlEvent) {
if (openUrlEvent.getType() == OpenLinks.Internally) {
// Open AndroidX browser or similar functionality to keep the user in app
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder().build();
customTabsIntent.launchUrl(context, Uri.parse(openUrlEvent.getUrl()));
openUrlEvent.getOnClose().invoke(openUrlEvent.getId()); // This must be called when the user is ready for the next offer
} else {
// Open external browser allowing user to leave the app
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(openUrlEvent.getUrl()));
context.startActivity(intent);
openUrlEvent.getOnClose().invoke(openUrlEvent.getId()); // This must be called when the user is ready for the next offer
}
}
return null;
}
All events
Event | Description | Params |
---|---|---|
OfferEngagement | Triggered when the user engages with the offer | layoutId: String |
PositiveEngagement | Triggered when the user positively engages with the offer | layoutId: String |
LayoutInteractive | Triggered when a layout has been rendered and is interactable | layoutId: String |
LayoutReady | Triggered when a layout is ready to display but has not rendered content yet | layoutId: String |
LayoutClosed | Triggered when a layout is closed by the user | layoutId: String |
LayoutCompleted | Triggered when the offer progression reaches the end and no more offers are available to display | layoutId: String |
LayoutFailure | Triggered when a layout could not be displayed due to some failure | layoutId: String (optional) |
OpenUrl | Triggered when a link needs to be opened | url: String, id: String, type: OpenLinks (internally/externally/Passthrough), onClose: (id: String) -> Unit, onError: (id: String, throwable: Throwable) |
PlatformEvents
Platform events are an essential part of integration and they have to be sent to Rokt via your backend. To ease integration the object is of type RoktPlatformEventsWrapper
, implements @Serializable and offers a toJsonString
function.
- Kotlin
- Java
onPlatformEvent = { events ->
// Send these platform events to Rokt API including the event body
}
roktPlatformEvents -> {
// Send these platform events to Rokt API including the event body
return null;
}
You can find a full list of events here.
Optional: App Configurations
Color mode
Color mode allows you to fix the theme used when displaying Rokt layouts. By default Rokt matches the current system theme.
- Kotlin
- Java
val config = RoktUxConfig.builder()
.colorMode(ColorMode.DARK)
.build()
final RoktUxConfig build = new RoktUxConfig.builder()
.colorMode(ColorMode.DARK)
.build();
RoktUxColorMode object
Value | Description |
---|---|
LIGHT | Application is in Light Mode |
DARK | Application is in Dark Mode |
SYSTEM | Application defaults to System Color Mode |
ImageLoader
In Rokt UX Helper coil is used for loading images, UX Helper has several built in image loaders that you can utilise in your app. The easiest and recommended approach to implement is NetworkStrategy
, however depending on your networking library or preferences you can create custom image loading strategies.
- Kotlin
- Java
val roktUxConfig = RoktUxConfig.builder()
.imageHandlingStrategy(NetworkStrategy())
.build()
final roktUxConfig = new RoktUxConfig.builder()
.imageHandlingStrategy(new NetworkStrategy())
.build();
Fonts
Firstly you need to add your font files e.g. roboto_light.ttf
to your Andorid resources folder and then configure UX Helper to use them with RoktUxConfig
. The below example is for fonts configured in resources, however we also support fonts in assets with AssetFontItem
.
- Kotlin
- Java
val robotoFonts: List<ResourceFontItem> = listOf(
ResourceFontItem(R.font.roboto_light, FontItemWeight.W100, FontItemStyle.Normal),
ResourceFontItem(R.font.roboto_light, FontItemWeight.W300, FontItemStyle.Normal),
ResourceFontItem(R.font.roboto_italic, FontItemWeight.W400, FontItemStyle.Italic),
ResourceFontItem(R.font.roboto_bold, FontItemWeight.W700, FontItemStyle.Normal),
ResourceFontItem(R.font.roboto_black, FontItemWeight.W900, FontItemStyle.Normal),
// Add any relevant fonts
)
// If you have multiple fonts create them here and add them to the fontFamilyMap
val config = RoktUxConfig.builder()
.xmlFontFamilyMap(mapOf("roboto" to robotoFonts))
.build()
final List<ResourceFontItem> fontItems = Arrays.asList(
new ResourceFontItem(R.font.roboto_light, FontItemWeight.W100, FontItemStyle.Normal),
new ResourceFontItem(R.font.roboto_light, FontItemWeight.W300, FontItemStyle.Normal),
new ResourceFontItem(R.font.roboto_italic, FontItemWeight.W400, FontItemStyle.Italic),
new ResourceFontItem(R.font.roboto_bold, FontItemWeight.W700, FontItemStyle.Normal),
new ResourceFontItem(R.font.roboto_black, FontItemWeight.W900, FontItemStyle.Normal)
// Add any relevant fonts
);
// If you have multiple fonts create them here and add them to the fontFamilyMap
final Map<String, List<ResourceFontItem>> fontFamilyMap = new HashMap<>();
fontFamilyMap.put("roboto", fontItems);
final RoktUxConfig config = new RoktUxConfig.builder()
.xmlFontFamilyMap(fontFamilyMap)
.build();