# Expo

## Introduction

Using the native iOS/Android WebView implies some extra setup in your Expo project. This setup involves incorporating the IntelliProve plug-in Mobile SDK as a pre-packaged Expo Module and adding the necessary bridging code.

All this is nicely laid out in our step-by-step guide below.

The integration guide covers two sections:

1.  Setting up the Expo Module
2.  Interfacing with the Native code from Expo (_bridging_)

### GitHub

Our GitHub repository provides a fully functional example of our platform’s integration, demonstrating the seamless setup and utilisation of our pre-packaged Expo Module.

[https://github.com/IntelliProve/intelliprove-web-plugin-expo](https://github.com/IntelliProve/intelliprove-web-plugin-expo)

### Minimal Requirements

For this guide, we assume a minimal ‘Hello World’ application generated by the Expo project initialisation.

## 1\. Expo Module Setup

### Adding the framework

_**`Last update 22/08/2026 14:32`**_

[expo-intelliprovewebview-2.0.0.tgz](https://docs.intelliprove.com/downloads/expo-intelliprovewebview-2.0.0.tgz)

-   Copy the `expo-intelliprovewebview-x.x.x.tgz` tarball into your Expo App root directory.
-   In your Expo App root directory, execute `npm install /path/to/tarball/expo-intelliprovewebview-x.x.x.tgz`.

### Configuration for iOS

We need to configure the minimum deployment target of the application, and allow Camera Usage by the application.

-   Open `app.json` and add:

```json
   ...


    "ios": {
      ...,
      "deploymentTarget": "15.0",
      "infoPlist": {
        "NSCameraUsageDescription": "We need camera permission for performing the measurement."
      }
    },


    ...
```

-   Then run `npx pod-install` to ensure all iOS dependencies are added to your application.

Run `npx expo prebuild --clean` first if you don’t have an _./ios_ folder.

### Configuration for Android

-   Run `npx expo install expo-build-properties`. This allows you to edit the gradle build properties for the Android application.
-   Then in `app.json` add the following, so we can set the correct SDK versions and permissions:

```json
    ...


    "android": {
      ...,
      "permissions": [
        "android.permission.INTERNET",
        "android.permission.CAMERA"
      ]
    },


    ...


    "plugins": [
      [
        "expo-build-properties",
        {
          "android": {
            "compileSdkVersion": 34,
            "targetSdkVersion": 34,
            "minSdkVersion": 24,
            "kotlinVersion": "1.8.0",
            "buildToolsVersion": "34.0.0"
          }
        }
      ],


      ...
    ]
```

We also need to do some updates to the Android Manifest, so we can run the IntelliProve module from the application.

-   First, create a file at `plugins/withIntelliProveAndroidManifest.js` relative to the Expo Application root folder.
-   In that file, add the following code:

```javascript
const { withAndroidManifest } = require("@expo/config-plugins");


function addUsesFeatureCameraToManifest(androidManifest) {
  const { manifest } = androidManifest;


  if (!Array.isArray(manifest["uses-feature"])) {
    manifest["uses-feature"] = [];
  }


  if (!manifest["uses-feature"].find(
    (item) => item.$["android:name"] === "android.hardware.camera"
  )) {
    manifest["uses-feature"]?.push({
      $: {
        "android:name": "android.hardware.camera",
        "android:required": "false",
      },
    });
  }


  return androidManifest;
}


function addIntelliWebViewActivityToManifest(androidManifest) {
  const { manifest } = androidManifest;


  if (!Array.isArray(manifest["application"])) {
    console.warn("withIntelliProveAndroidManifest: No application array in manifest?");
    return androidManifest;
  }


  const application = manifest["application"].find(
    (item) => item.$["android:name"] === ".MainApplication"
  );
  if (!application) {
    console.warn("withIntelliProveAndroidManifest: No .MainApplication?");
    return androidManifest;
  }


  if (!Array.isArray(application["activity"])) {
    application["activity"] = [];
  }


  if (!application["activity"].find(
    (item) => item.$["android:name"] === "com.intelliprove.webview.IntelliWebViewActivity"
  )) {
    application["activity"]?.push({
      $: {
        "android:name": "com.intelliprove.webview.IntelliWebViewActivity"
      },
    });
  }


  return androidManifest;
}


module.exports = function withIntelliProveAndroidManifest(config, attributes) {
  return withAndroidManifest(config, (config) => {
    config.modResults = addUsesFeatureCameraToManifest(config.modResults);
    config.modResults = addIntelliWebViewActivityToManifest(config.modResults);
    return config;
  });
};
```

-   Finally, add the following to `app.json`:

```json
    ...
    "plugins": [
      ...
      [
        "./plugins/withIntelliProveAndroidManifest",
        {}
      ]
    ]
```

## 2\. Expo Integration

While many possibilities exist to bridge the gap between Native iOS/Android and Expo, this document serves as a guide to integrating the IntelliProveSDK into an Expo application project.

To be able to call functions on, and receive callbacks from the IntelliProve Expo Module, we need to import it in the Expo application.

-   Open `App.tsx` or wherever in the Expo app that the IntelliProve web view will be used. (For newer Expo projects, add the code to the `RootLayout` in the _\_layout.tsx_ file instead.)
-   Add the following imports:

```javascript
// For registering the event listener
import { useEffect } from 'react';
// The IntelliProve expo module
import * as ExpoIntelliProveWebView from 'expo-intelliprovewebview';
```

-   Add a function `handleOpenWebView` that calls the IntelliProve Expo Module to present the Web View
-   Also add a callback handler for receiving ‘PostMessage’ messages.
    -   The post messages allow you to **track the progress** of the Face Scan and **obtain the results** from the IntelliProve plug-in immediately after the user has performed the Face Scan. This allows you to use the results in your mobile app, enabling you to link actions to the results or design a custom results screen.
    -   You can find an overview of the different types of messages on the [Message events](https://docs.intelliprove.com/technical-docs/message-events) page.
-   Finally, we call the `handleOpenWebView()`function from wherever the entry point to the WebView should be.
-   The URL to open the IntelliProve Face Scan Plug-in (webapp) is also passed to this function. In our example, it is added on a Button press handler.
    -   Make sure to request the URL for the Face Scan plug-in using the [Get Face Scan URL](https://docs.intelliprove.com/technical-docs/rest-api#get-face-scan-url) API endpoint.

```typescript
export default function App() {
  const handleOpenWebView = () => {
    ExpoIntelliProveWebView.presentWebView('https://<subdomain.intelliprove.com/...');
  };


  // Add Event Listener for IntelliWebViewPostMessage API
  useEffect(() => {
    // Make sure the name of the listener matches what was used on Native code
    const subscription = ExpoIntelliProveWebView.addPostMessageListener((event) => {
      // Handle the received postMessage
      console.log('Expo PostMessage Full Body:', event.postMessage);


      try {
        // The PostMessage is received as a JSON String, so we need to parse it
        const parsedMessage = JSON.parse(event.postMessage);
        if (parsedMessage && parsedMessage.stage) {
          console.log('Expo PostMessage Stage:', parsedMessage.stage);
        } else {
          console.warn('Expo invalid PostMessage format:', parsedMessage);
        }
      } catch (error) {
        console.error('Expo error parsing PostMessage:', error);
      }
    });


    // Unsubscribe from the event when the component unmounts
    return () => {
      subscription.remove();
    };
  }, []);


  ...


  return (
    ...
    <Button title="Open WebView" onPress={handleOpenWebView} />
    ...
  )
}
```

The WebView is automatically dismissed by the SDK when receiving the `dismiss` post message.

Now run the application as you normally would, for example:

-   `npx expo prebuild --clean`
-   `npx expo run:ios` or `npx expo run:android`

## Next steps

-   To match the plug-in with your brand’s colours and fonts, please visit our our [UI Customization](https://docs.intelliprove.com/technical-docs/ui-customization) documentation.
