---
title: Flutter
slug: technical-docs/flutter
icon: 🧑‍💻
docTags: 
createdAt: 2024-02-28T07:33:23.305Z
---

# Introduction

Using the native iOS/Android WebView implies some extra setup in your Flutter project. This setup involves incorporating the IntelliProve plug-in Mobile SDK files into your project dependencies for both iOS and Android and adding the necessary bridging code.

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

The integration guide covers three sections:

1. Setting up the iOS code
2. Setting up the Android code
3. Interfacing with the native code from Flutter (*bridging*)

## GitHub

Our GitHub repository provides a fully functional example of our platform's integration, demonstrating the seamless setup and utilisation of our native SDKs for iOS and Android platforms.

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

## Minimal Requirements

For this guide, we assume a minimal 'Hello World' application generated by the Flutter project initialisation.

# 1. iOS Framework Setup

## Adding the framework

`Last update 04/01/2026 13:40`

::File{src="https://api.archbee.com/api/presign/_0R_DnpmBBLLXmaoWvG2u/Xt1rOrhf0CYjWQvUbE2W6_intelliprovesdkxcframework.zip" label="IntelliProveSDK.xcframework.zip"}

- Add folder `ios/Frameworks`
- Copy the unzipped `IntelliProveSDK.xcframework` folder into this folder
- Open the `ios/Runner.xcodeproj` project in XCode
- Open `Project Settings > General` and in the `Frameworks, Libraries, and Embedded Content` section, add the `IntelliProveSDK.xcframework` that you copied above as a dependency

![](https://api.archbee.com/api/optimize/_0R_DnpmBBLLXmaoWvG2u/UbHJMIKfTMRmass5mPD2l_image.png)

## Setting up the project

- In `Project Settings > Build Settings` tab, verify that the `iOS Deployment Target` is set appropriately. The minimum supported version for the IntelliProveSDK is iOS 15.0
- Now open the `Project Settings > Info` tab to add the following `Info.plist` value:
  - `NSCameraUsageDescription` - Add a String here that will be displayed when the application asks the user for Camera Usage permissions

![](https://api.archbee.com/api/optimize/_0R_DnpmBBLLXmaoWvG2u/2zboUFyD8ei-TocPySMZ__image.png)

## Updating the code

- In the project tree, open `AppDelegate.swift`, and add the following code:

```swift
// Add the IntelliProveSDK import
import IntelliProveSDK
...

// This is an example of how the AppDelegate may look, it may be defined differently in another project
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)

        // This registers a MethodChannel with your Flutter application.
        // The name is important, it must match the name of the channel in the *.dart file 
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let webviewChannel = FlutterMethodChannel(
            name: "com.intelliprove/webview",
            binaryMessenger: controller.binaryMessenger
        )

        // This registers a method call handler,
        // so the Native `openWebView()` function can be called from within the Flutter code
        webviewChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
            if call.method == "openWebview" {
                if let args = call.arguments as? [String: Any],
                   let urlString = args["url"] as? String {
                    self?.openWebView(urlString: urlString)
                }
                result(nil)
            } else {
                result(FlutterMethodNotImplemented)
            }
        })

        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    /// This function creates a new IntelliWebView using the Factory method,
    /// passing in the provided urlString, and setting the AppDelegate as a delegate for the IntelliWebView
    private func openWebView(urlString: String) {
        let webViewController = IntelliWebViewFactory.newWebView(urlString: urlString, delegate: self)
        webViewController.modalPresentationStyle = .fullScreen
        window?.rootViewController?.present(webViewController, animated: true)
    }
}

/// Implementation of the `IntelliWebViewDelegate` protocol
/// This dispatches received `PostMessage API` messages through to the Flutter application
extension AppDelegate: IntelliWebViewDelegate {
    func didReceive(postMessage: String) {
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let webviewChannel = FlutterMethodChannel(
            name: "com.intelliprove/webview",
            binaryMessenger: controller.binaryMessenger
        )
        webviewChannel.invokeMethod("didReceivePostMessage", arguments: postMessage)
    }
}
```

# 2. Android Framework Setup

## Adding the framework

`Last update 16/09/2025 09:35`

::File{src="https://api.archbee.com/api/presign/_0R_DnpmBBLLXmaoWvG2u/hNlKIHWTdeKoVgHsPmCgf-20250914-201443.aar" label="IntelliProveWebView.aar"}

- All the following actions are taken in the `android` root folder of the Flutter project
- Add folder `app/libs`
- Copy the `IntelliProveWebView.aar` into this folder
- In `app/build.gradle`, add a dependency for the `IntelliProveWebView.aar`and androidx's AppCompatibility ConstraintLayout.

```java
dependencies {
    ...
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    implementation files('libs/IntelliProveWebView.aar')
}
```

## Setting up the project

- In `build.gradle`, ensure the correct Kotlin version is used:

```java
buildscript {
    ext.kotlin_version = '1.8.0'
    ...
}
```

- In `app/build.gradle`, define the `minSdkVersion`:

```java
android {
    ...
    defaultConfig {
        ...
        minSdkVersion 24
        ...
    }
    ...
}
```

- In `app/src/main/AndroidManifest.xml`, add the needed permissions for Camera and Internet usage, and an activity tag, so the `IntelliWebViewActivity` can be shown in the application:

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    ...

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />

    ...

    <application ...>
        ...
        <activity
            android:name="com.intelliprove.webview.IntelliWebViewActivity"
            android:theme="@style/Theme.AppCompat.NoActionBar"
            />
        ...
    </application>
</manifest>
```

## Updating the code

- Now open the Activity from where the IntelliWebView will be triggered. In our example this is `MainActivity.kt`. Add the following code:

```kotlin
// Imports for the IntelliProve WebView
import com.intelliprove.webview.IntelliWebViewActivity
import com.intelliprove.webview.IntelliWebViewDelegate

// Imports for the Flutter MethodChannel bridging
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

...

// The MainActivity in our example also implements the `IntelliWebViewDelegate` interface
// That way it can receive callbacks from the Web App's `PostMessage API`
class MainActivity(private var webViewChannel: MethodChannel? = null): FlutterActivity(), IntelliWebViewDelegate {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        // We keep the MethodChannel bridge to Flutter on a member
        // Make sure to use the same name as in the Flutter App code
        webViewChannel = MethodChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.intelliprove/webview"
        )

        // Add a MethodCallHandler to react to the trigger and show the WebView sent from the Flutter App code
        webViewChannel?.setMethodCallHandler { call, result ->
            if (call.method == "openWebview") {
                val args = call.arguments as? Map<*, *>
                val urlString = args?.get("url") as? String
                urlString?.let {
                    openWebView(it)
                }
                result.success(null)
            } else {
                result.notImplemented()
            }
        }
    }

    private fun openWebView(urlString: String) {
        IntelliWebViewActivity.start(this, urlString, this)
    }

    override fun didReceivePostMessage(postMessage: String) {
        runOnUiThread {
            webViewChannel?.invokeMethod("didReceivePostMessage", postMessage)
        }
    }
}
```

# 3. Flutter Integration

:::hint{type="info"}
While many possibilities exist to bridge the gap between Native iOS/Android and Flutter, this document serves as a guide to integrating the IntelliProveSDK into a Flutter application project.
:::

To be able to call functions on, and receive callbacks from the Native application, we can implement a `MethodChannel` in the Flutter Application.

- Open `main.dart` (or wherever in the Flutter app that the IntelliProve web view will be used)
- Add the following imports:

```dart
import 'package:flutter/services.dart'; // To use MethodChannel
import 'dart:convert'; // To convert the received JSON String to a dictionary
```

- Add a MethodChannel with a method to open the IntelliWebView.  In our example we add it as a static const on our `State<HomePage>` implementation.&#x20;
- 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](docId\:KZ6XSnd6V4G8EfCgd02ib) page.

```dart
// Make sure the name of the MethodChannel matches the one used in the Native App code
static const platform = MethodChannel('com.intelliprove/webview');

@override
void initState() {
    super.initState();
    platform.setMethodCallHandler(handleNativeCallback);
}

void openWebView(String url) async {
    try {
        // Make sure the method name also matches the one registered in Native App code
        await platform.invokeMethod('openWebview', {'url': url});
    } on PlatformException catch (e) {
        print("Failed to open webview: ${e.message}");
    }
}

Future<void> handleNativeCallback(MethodCall call) async {
    if (call.method == 'didReceivePostMessage') {
        String postMessage = call.arguments;
        print("Flutter PostMessage Full Body: $postMessage");

        // postMessage is received as JSON string, so we need to parse it
        Map<String, dynamic> postData = jsonDecode(postMessage);
        String stage = postData['stage'];
        print("Flutter PostMessage Stage: $stage");
    }
}
```

- Finally, call the `openWebView(...)` function from wherever the entry point to the WebView should be.
- The URL to open the IntelliProve Face Scan Plug-in (webapp) is also added 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](docId\:BiuPVixvHltbukKLR2ATI) API endpoint.

```dart
ElevatedButton(
    onPressed: () => openWebView('https://<subdomain>.intelliprove.com/...'),
    child: Text('Open WebView'),
)
```

:::hint{type="warning"}
The WebView is automatically dismissed by the SDK when receiving the `dismiss` post message.
:::

# Next steps

- To match the plug-in with your brand's colours and fonts, please visit our  [UI Customization](docId\:vzz-ODpLrSTmbHTHZKLLd) documentation.

