Embedding Into Your Native App

Learn how to create inspections through the API and render the returned inspection link inside your native app with minimal development

Create an inspection through the API, get the inspection link from the response, and render that link inside your native app with a WebView.

You can follow this flow whether you are building in Objective-C or Swift for iOS, Java or Kotlin for Android, or using a multi-platform framework like React Native. Vision runs inside a WebView, so you can bring the pre-built inspection experience into your app without rebuilding it natively.

In this guide, you will:

  1. Create the inspection through the API
  2. Add permissions: camera, location, microphone
  3. Add a WebView to render Vision
  4. Customize the inspection experience
  5. Load the inspection link returned by the API

1. Create the inspection through the API

Start by creating the inspection through the API and storing the inspection link returned in the response. This replaces the older deep-link exchange flow.

When you create the inspection for an embedded app flow, disable email and text messaging so Truepic does not send communication to the user. Your app is responsible for telling the user that an inspection is ready and getting them into the embedded experience.

A typical flow looks like this:

  1. Call the API to create the inspection.
  2. Disable email and text messaging for that inspection.
  3. Store the inspection link returned by the API.
  4. Open that link inside the WebView in your app when the user is ready to complete the inspection.

If your backend creates inspections on behalf of the mobile app, return the inspection link to the device through your existing API or app state flow. The important part is that your app loads the same inspection link returned when the inspection was created.

2. Add permissions: camera, location, microphone

With that housekeeping out of the way, you can now jump into the code to add camera, location, and microphone permissions to your native app. These are required for Vision to securely capture photos and videos within the inspection.

iOS

For iOS, add the following to Info.plist:

<key>NSCameraUsageDescription</key>
<string>We use your camera to capture photos and videos within your virtual inspection.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We associate your location with the photos and videos you capture within your virtual inspection.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We use your microphone to record audio with the videos you capture within your virtual inspection.</string>

The language can be adjusted to fit your brand and style.

Android

For Android, add the following to AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

Multi-platform framework

Your multi-platform framework may allow you to add these permissions via a config file. For example, Expo for React Native supports them in app.json:

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "We use your camera to capture photos and videos within your virtual inspection.",
        "NSLocationWhenInUseUsageDescription": "We associate your location with the photos and videos you capture within your virtual inspection.",
        "NSMicrophoneUsageDescription": "We use your microphone to record audio with the videos you capture within your virtual inspection."
      }
    },
    "android": {
      "permissions": [
        "android.permission.CAMERA",
        "android.permission.ACCESS_FINE_LOCATION",
        "android.permission.RECORD_AUDIO",
        "android.permission.MODIFY_AUDIO_SETTINGS"
      ]
    }
  }
}

3. Add a WebView to render Vision

The next step is to add a WebView to your native app that renders the inspection link returned by the API. How you implement this varies from platform to platform, but they all need the same input: the inspection URL.

Find the WebView for your platform

Just about every platform has a WebView class, framework, or library. Here is a list of the popular ones:

Render the inspection in the WebView

With the WebView for your platform identified, pass it the inspection link from your API flow. For example, in React Native, a basic WebView looks like this:

const inspectionUrl = '{Inspection link returned by the API}'

<ReactNativeWebView
  source={{
    uri: inspectionUrl,
  }}
/>

Adjust the WebView

Once you get a basic integration of the WebView working, there will likely be some adjustments you will need to make. This differs from WebView to WebView, as they all expose different options and defaults. Here are some questions to investigate:

  • Does the WebView need to be extended camera, location, and microphone permissions? Is it possible to inherit these permissions from the native app?
  • Do certain features need to be enabled in the WebView, such as the ability to play video inline?

Returning to the React Native example from above, asking these questions results in adding four options to fine-tune the WebView:

const inspectionUrl = '{Inspection link returned by the API}'

<ReactNativeWebView
  source={{
    uri: inspectionUrl,
  }}
  // Required by iOS to allow inline video playback, otherwise it's full-screen.
  allowsInlineMediaPlayback
  // Required by Android for location, as it's disabled by default.
  geolocationEnabled={true}
  // On Android, keep the WebView from over-scrolling.
  overScrollMode="never"
  // On iOS, permit the WebView to inherit camera and microphone permissions.
  mediaCapturePermissionGrantType="grant"
/>

4. Customize the inspection experience

With a working WebView, the next step is to customize the inspection experience. This is done by injecting custom JavaScript into the rendered page, which most WebViews support to facilitate communication between the native app and website.

The Vision web app reads a config object from window.visionConfig and emits events that your native app can hook into. Here's an annotated example of how that custom JavaScript looks:

// Config options that the Vision web app reads when it loads.
window.visionConfig = {
  // The name of your native app, used in places like the back button. Defaults
  // to `null`.
  appName: '{Your App}',
  // Whether to show a "Back to {Your App}" button that fires the `back` event.
  // Defaults to `false`.
  showBackToApp: true,
  // Whether to show the menu in the header for accessing Support, Terms &
  // Conditions, etc. Defaults to `true`.
  showMenu: false,
  // Styles to customize the look and feel of the app. `@font-face` and
  // `@import` declarations can be used to load custom fonts. CSS variables
  // added to `:root` override styles in the app. Defaults to `null`.
  styles: `
    @font-face {
      font-family: 'Roboto Slab Variable';
      font-style: normal;
      font-display: swap;
      font-weight: 100 900;
      src: url(https://cdn.jsdelivr.net/fontsource/fonts/roboto-slab:vf@latest/latin-wght-normal.woff2) format('woff2-variations');
      unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }

    :root {
      --vision-color-background: rgba(27 27 27 / 10%);
      --vision-font-family: 'Roboto Slab Variable', serif;
    }
  `,
}

// An event that's fired when the user taps the "Back to {Your App}" button
// that's enabled via the `showBackToApp` config.
window.addEventListener('back', (event) => {
  // Pass the event back to your native app.
})

// An event that's fired when the user finishes the inspection.
window.addEventListener('finished', (event) => {
  // Pass the event back to your native app.
})

How you inject this custom JavaScript into the page – as well as pass the event back to your native app – depends on the WebView you are using. For example, React Native WebView offers a few different ways, including injectedJavaScriptBeforeContentLoaded and onMessage. Here is an updated example of that custom JavaScript using these options:

const inspectionUrl = '{Inspection link returned by the API}'

<ReactNativeWebView
  source={{
    uri: inspectionUrl,
  }}
  allowsInlineMediaPlayback
  geolocationEnabled={true}
  overScrollMode="never"
  mediaCapturePermissionGrantType="grant"
  injectedJavaScriptBeforeContentLoaded={`
    window.visionConfig = {
      appName: '{Your App}',
      showBackToApp: true,
    }

    window.addEventListener('back', (event) => {
      window.ReactNativeWebView.postMessage(JSON.stringify({
        type: 'back',
        ...event.detail,
      }))
    })

    window.addEventListener('finished', (event) => {
      window.ReactNativeWebView.postMessage(JSON.stringify({
        type: 'finished',
        ...event.detail,
      }))
    })
  `}
  onMessage={(event) => {
    const { type, ...data } = JSON.parse(event.nativeEvent.data)

    switch (type) {
      case 'back':
        // Handle the event in your native app.
        return
      case 'finished':
        // Handle the event in your native app.
        return
    }
  }}
/>

5. Load the inspection link returned by the API

Once your WebView is working, connect it to the inspection creation flow in your app. Instead of handling a Branch deep link, your app should use the inspection link returned when you create the inspection through the API.

When you create the inspection, disable email and text messaging so Truepic does not contact the user. It is up to your app to communicate with the user and direct them to the embedded inspection flow.

Create the inspection and capture the link

Complete this flow in your app or backend:

  1. Create the inspection through the API.
  2. Disable email and text messaging for the inspection.
  3. Read the inspection link from the API response.
  4. Pass that link to the screen that hosts your WebView.

Pass the inspection link to the WebView

If inspectionUrl contains the link returned by the API, you can load it directly:

<ReactNativeWebView
  source={{
    uri: inspectionUrl,
  }}
/>

Guide the user into the inspection

Because Truepic is not sending the inspection by email or text in this flow, your app needs to handle user communication. Common approaches include:

  • Navigating the user directly into the inspection after it is created
  • Showing an in-app message that the inspection is ready
  • Sending your own push notification or other communication that brings the user back into your app

Your app should treat the inspection link as the source of truth for launching the embedded experience. Once that link is available, load it in the WebView and let the user complete the inspection without leaving your app.

Wrapping up

Your app should now be able to create inspections through the API, control how users are notified, and display the returned inspection link inside your native app. Please reach out with any questions along the way!