Introduction
The embedded learning Mobile SDK allows you to integrate an instance of your Docebo platform in your iOS, Android or React Native mobile application.
The Docebo platform instance opens when the user clicks on a button or interacts with an element - such as a link, or a string - in your mobile application. When embedded learning opens, the platform instance shows the training content you, as the Superadmin, have selected for the user based on the action the user is performing, in order to provide the best learning on the fly experience, enriching it with ad hoc training.
Depending on the embedded learning configuration, users can be automatically provisioned so that their learning in the flow of work is not an event interrupted by the need to log in.
This document is a technical guide on how to embed embedded learning into your React Native mobile application.
Activating embedded learning
To activate embedded learning, reach out to Docebo via the Help Center, or by contacting your Account Manager (if your plan includes this option).
Prerequisites
Before you can proceed with this guide, please make sure you have followed the instructions in Embedding embedded learning in your mobile application.
Native implementation
In this example, we will use the react-native-webview
community package. Please note that in order to avoid conflicts with the native postMessage
, this package uses a special window.ReactNativeWebView.postMessage
method to communicate with the native code. This should be modified accordingly in the public JavaScript file.
The webview is instantiated with the web page URL created earlier as a source, and a reference to the instance is created for later use.
import { WebView } from 'react-native-webview';
const webView = useRef<WebView>(null);
<WebView
ref={webView}
source={{ uri: '<YOUR_WEB_PAGE_URL>' }}
/>
When the webview has loaded the page, it's time to initialize the launcher by calling the connect function created earlier in the web page JavaScript code:
const onLoadEnd = () => {
// domain: the Docebo platform domain
// accessToken: the initial access token; this is optional, but providing it will improve the startup time. If not passed, the web page will call the onMessage function and obtain a new token.
// launcherCode: the app launcher code
const options = JSON.stringify({
domain: '<LMS_DOMAIN>',
accessToken: '<ACCESS_TOKEN>',
launcherCode: '<LAUNCHER_CODE>',
context: '<BUILDING_BLOCKS_CONTEXT>',
language: '<BUILDING_BLOCKS_LANGUAGE>',
});
// It's not advides to pass objects throught the javascript injection. Instead we serialize the
// options and parse it on the receiving side
webView.current?.injectJavaScript(`connect('${options}')`);
}
The last step is to prepare for when the web page will request a new token by intercepting postMessage
and responding to it
const onMessage = async (event) => {
const message = event.nativeEvent.data;
if (message === 'FETCH_ACCESS_TOKEN') {
const accessToken = await getAccessToken();
webView.current?.injectJavaScript(`window.postMessage('${accessToken}')`);
}
}
Complete code
// WebViewScreen.tsx
import { useRef } from 'react';
import WebView, { WebViewMessageEvent } from 'react-native-webview';
export const WebViewScreen = () => {
const webView = useRef<WebView>(null);
const onLoadEnd = () => {
const options = JSON.stringify({
domain: '<LMS_DOMAIN>',
accessToken: '<ACCESS_TOKEN>',
launcherCode: '<LAUNCHER_CODE>',
context: '<BUILDING_BLOCKS_CONTEXT>',
language: '<BUILDING_BLOCKS_LANGUAGE>',
});
webView.current?.injectJavaScript(`connect('${options}')`);
}
const onMessage = async (event: WebViewMessageEvent) => {
const message = event.nativeEvent.data;
if (message === 'FETCH_ACCESS_TOKEN') {
const accessToken = await getAccessToken();
webView.current?.injectJavaScript(`window.postMessage('${accessToken}')`);
}
}
return (
<WebView
ref={webView}
source={{ uri: '<YOUR_WEB_PAGE_URL>' }}
onMessage={onMessage}
onLoadEnd={onLoadEnd}
/>
)
}