Embedding Livble in Your Mobile App

💡Overview

As a tenant portal provider, you might have a mobile app for your renters. If that is the case please make sure to read the following instructions to ensure the Livble experience and widget work properly.

📘

NPM Package Version Requirements

  • If you are using the new Livble SDK version, please make sure to use >= 3.92.0
  • If you are using the old Livble SDK version (with LivbleProvider), please make sure to use >= 2.0.71

ReactNative

The Livble SDK, Widget and Experience will work exactly as React web.


WebView based

If you are using a WebView to show a web app within your mobile app, Livble will work as usual. However, you will have to add the following configuration to the WebView props


import React, { useState, useCallback } from "react";
import { Linking } from "react-native";
import { WebView } from "react-native-webview";

const BASE_URL = "YOUR_URL";

export default function Index() {
  const [
    shouldOpenOAuthInExternalBrowser,
    setShouldOpenOAuthInExternalBrowser,
  ] = useState(false);

  /**
   * Handle WebView navigation requests.
   * Opens OAuth redirects in the external browser when the experience is open.
   */
  const handleShouldStartLoadWithRequest = useCallback(
    (event: { url: any }) => {
      const { url } = event;
      const isRedirect = url.includes("redirect_uri=");

      if (isRedirect && shouldOpenOAuthInExternalBrowser) {
        Linking.canOpenURL(url)
          .then((supported) => {
            if (supported) {
              Linking.openURL(url).catch((err) =>
                console.error("Failed to open URL:", err)
              );
            }
          })
          .catch((err) => console.error("Error checking URL support:", err));

        return false; // Prevent WebView from handling the redirect
      }

      return true; // Allow WebView to handle other URLs
    },
    [shouldOpenOAuthInExternalBrowser]
  );

  /**
   * Handles messages received from the WebView.
   * Toggles whether OAuth links should open in an external browser.
   */
  const handleWebViewMessage = (event: { nativeEvent: { data: any } }) => {
    const { data } = event.nativeEvent;

    // Ensure message is a valid JSON string before parsing
    if (!data || typeof data !== "string") return;

    try {
      const parsedData = JSON.parse(data);

      if (parsedData.eventType === "CLOSE_EXPERIENCE_REQUEST") {
        setShouldOpenOAuthInExternalBrowser(false);
      } else if (parsedData.eventType === "OPEN_EXPERIENCE_REQUEST") {
        setShouldOpenOAuthInExternalBrowser(true);
      }
    } catch {}
  };

  /**
   * Inject JavaScript to ensure window.postMessage is properly handled.
   */
  const injectedJavaScript = `
    (function () {
      window.addEventListener(
        "message",
        function (event) {
          window.ReactNativeWebView.postMessage(
            typeof event.data === "string"
              ? event.data
              : JSON.stringify(event.data)
          );
        },
        false
      );
    })();
    true; // Required for iOS
  `;

  return (
    <WebView
      source={{ uri: BASE_URL }}
      onMessage={handleWebViewMessage}
      injectedJavaScript={injectedJavaScript}
      onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest}
    />
  );
}

Flutter

Not supported natively yet


Android (Native)

Not supported natively yet


IOS (Native)

Not supported natively yet