ShareID
  • SDKs
    • Web
    • iOS
    • Android
    • Flutter
    • React Native
  • Get a Token
    • Get a Token - Onboarding
    • Get a Token - Authenticate
  • Get the Analysis Result
    • Get Result - Onboarding
    • Get Result - Authenticate
  • Analysis Result
    • Analysis Result - Onboarding
    • Analysis Result - Authenticate
  • Message Handler
  • Photo-based authenticity API
  • Changelog
    • SDK Web
    • SDK iOS
    • SDK Android
    • Photo-based authenticity API
  • Terminology
  • Api
Powered by GitBook
On this page
  • Getting started
  • 1. Set up the SDK
  • 2. Get a token
  • 3. Start an onboarding or authenticate flow and get the user workflow result from SDK
  • 5. Get the Analysis result
  • Customisation
  • FAQ
Edit on GitHub
  1. SDKs

Flutter

This is a walkthrough of how you can integrate the Onboarding or Authenticate SDK for Flutter applications.

PreviousAndroidNextReact Native

Last updated 22 days ago

Getting started

In order to perform an Onboarding or an Authenticate, you should follow those steps:

  1. : install and import the SDK

  2. : request a token using your business credentials

  3. : launch a user workflow and use the Message handler to get insights about the user workflow

  4. : use your callback or the endpoint to get the analysis result

1. Set up the SDK

1.1. Project requirements

The proper functioning of the SDK necessitates the provision of several parameters. These parameters are essential for enabling the full range of functionalities offered by the SDK.

  • minSdk or minSdkVersion = 24

1.2. Install SDK

ShareID use Maven to provide its SDK securely with authentication managed in your <your-flutter-app>/android/build.gradle file.

allprojects {
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("https://repository.shareid.net/repository/mvn-hosted/")
            credentials {
                username = "<your-repository-username>"
                password = "<your-repository-password>"
            }
        }
    }
}

1.3. Add the dependency

To install the SDK, you'll need to add the dependency in your app module.

  1. Add the following to your build.gradle

implementation("ai.shareid:sdk:+") // or specific version
  1. You can now synchronise and use the SDK in your project

Make sure you update your various dependencies, distributionUrl, IDE, gradle version or anything else.

Conflicts of dependency

The SDK directly integrates most of the dependencies it uses to simplify your integration.

1.1. Project requirements

The proper functioning of the SDK necessitates the provision of several parameters. These parameters are essential for enabling the full range of functionalities offered by the SDK.

  • iOS 15+ (because of Swift minimum version)

  • Available for iPhone and iPad in portrait mode only

Mandatory app permission

The SDK uses the device's camera functionality.

1.2. Install SDK

To securely manage your credentials, you’ll need to create a .netrc file in your home directory with the necessary login details.

  1. Create and open

Type touch ~/.netrc & open ~/.netrc

  1. Add login details

machine repository.shareid.net
login <your-repository-username>
password <your-repository-password>
  1. Set file permissions

chmod 600 ~/.netrc

1.3. Add the dependency

To install the SDK with CocoaPods, you'll need to add the dependency to your Podfile. (if it doesn't exist, create one by running the following command in your project directory: pod init)

  1. Add the following to your target

platform :ios, '15.0'

target '<your-app>' do
  use_frameworks!
  pod 'shareid-sdk-ios' # or specific version
end
  1. Run pod install to install the dependency

  2. Now, you can import and use the SDK in your project

import shareid_sdk_ios

Signing & Capabilities

Before running your Flutter app with the ShareID SDK, you must configure Signing & Capabilities in Xcode to avoid build errors.

2. Get a token

Use the credentials you received from ShareID's team to get an authenticate token and launch an onboarding or authenticate workflow.

3. Start an onboarding or authenticate flow and get the user workflow result from SDK

Use your token to start an onboarding or an authenticate.

Step 1: Create the ShareID service

This service bridges Dart and native Android/iOS code using MethodChannel and EventChannel:

  • MethodChannel handles platform-specific method calls and responses, ideal for request-response interactions.

  • EventChannel listens to native data streams. The messageHandler closure processes feedback from the ShareID SDK, such as operation completions, failures, or errors.

Together, these channels enable seamless communication and real-time updates, overcoming Flutter’s isolation from native functionalities.

  1. Create the shareid_service.dart in libs

import 'package:flutter/services.dart';

class ShareIDService {
  static const MethodChannel _channel = MethodChannel('shareid_sdk_method_channel');
  static const EventChannel _eventChannel = EventChannel('shareid_sdk_event_channel');
  
  static Future<void> signUpWithShareID(String token) async {
    await _invokeMethod('signUp', token);
  }

  static Future<void> signInWithShareID(String token) async {
    await _invokeMethod('signIn', token);
  }
  
  static Stream<Map<String, dynamic>> get events {
    return _eventChannel.receiveBroadcastStream().map((event) => Map<String, dynamic>.from(event));
  }

  static Future<void> _invokeMethod(String method, String token) async {
    try {
      await _channel.invokeMethod(method, {"token": token});
    } catch (e) {
      throw Exception("Failed to start ShareID flow: $e");
    }
  }
}
  1. Use the ShareIDService into your main.dart (or your dart.file)

late final Stream<Map<String, dynamic>> _eventStream;

void startOnboarding() async {
  try {
    String token = '<your-token>'
    await ShareIDService.signUpWithShareID(token);
  } catch (e) {
    print("Error in onboarding: $e");
  }
}

void startAuthenticate() async {
  try {
    String token = '<your-token>'
    await ShareIDService.signInWithShareID(token);
  } catch (e) {
    print("Error in authentication: $e");
  }
}

@override
void initState() {
  super.initState();
  _eventStream = ShareIDService.events;
  _listenToEvents();
}

void _listenToEvents() {
  _eventStream.listen((event) {
    print('Event received: ${event['type']} - ${event['message']}');
  });
}

Step 2: Use the service in your native code

All you have to do is create the link with the native Android code in your MainActivity and connect the channel with your ShareID messageHandler .

Kotlin

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.EventChannel
import com.shareid.sdk.viewmodel.ShareID

class MainActivity : FlutterActivity() {

    private val METHOD_CHANNEL = "shareid_sdk_method_channel"
    private val EVENT_CHANNEL = "shareid_sdk_event_channel"

    private var eventSink: EventChannel.EventSink? = null
    
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, METHOD_CHANNEL).setMethodCallHandler { call, result ->
            val token = call.argument<String>("token")

            val service = when (call.method) {
                "signUp" -> ShareID.Service.onboarding
                "signIn" -> ShareID.Service.authenticate
                else -> {
                    result.error("INVALID_SERVICE", "Unknown service: ${call.method}", null)
                    return@setMethodCallHandler
                }
            }

            if (token.isNullOrEmpty()) {
                result.error("INVALID_TOkEN", "Empty token", null)
            } else {
                ShareID.shared.start(service, token)
                result.success("ShareID ${service.name} flow has been started")
            }
        }
        
        EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL).setStreamHandler(object : EventChannel.StreamHandler {
            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                eventSink = events
            }

            override fun onCancel(arguments: Any?) {
                eventSink = null
            }
        })
        
        ShareID.shared.messageHandler = { result ->
            runOnUiThread {
                when (result.type) {
                    ShareID.ResultType.success -> {
                        eventSink?.success(mapOf("type" to "success", "message" to result.code))
                    }
                    ShareID.ResultType.exit -> {
                        eventSink?.success(mapOf("type" to "exit", "message" to result.code))
                    }
                    ShareID.ResultType.failure -> {
                        eventSink?.success(mapOf("type" to "failure", "message" to result.code))
                    }
                    else -> {
                        eventSink?.error("UNKNOWN", "Unknown result type", null)
                    }
                }
            }
        }
    }
}

Java

import android.os.Bundle;
import androidx.annotation.NonNull;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.EventChannel;
import com.shareid.sdk.utils.ShareID;

public class MainActivity extends FlutterActivity {
    private static final String METHOD_CHANNEL = "shareid_sdk_method_channel";
    private static final String EVENT_CHANNEL = "shareid_sdk_event_channel";
    
    private EventChannel.EventSink eventSink;
    
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);

        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), METHOD_CHANNEL)
            .setMethodCallHandler((call, result) -> {
                String token = call.argument("token");

                ShareID.Service service;
                
                switch (call.method) {
                    case "signUp":
                        service = ShareID.Service.onboarding;
                        break;
                    case "signIn":
                        service = ShareID.Service.authenticate;
                        break;
                    default:
                        result.error("INVALID_SERVICE", "Unknown service: " + call.method, null);
                        return;
                }

                if (token == null || token.isEmpty()) {
                    result.error("INVALID_TOKEN", "Empty token", null);
                } else {
                    ShareID.Companion.getShared().start(service: service, token: token);
                    result.success("ShareID " + service.name() + " flow has been started");
                }
            });
            
        new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), EVENT_CHANNEL)
            .setStreamHandler(new EventChannel.StreamHandler() {
                @Override
                public void onListen(Object arguments, EventChannel.EventSink events) {
                    eventSink = events;
                }

                @Override
                public void onCancel(Object arguments) {
                    eventSink = null;
                }
            });

 
        ShareID.Companion.getShared().setMessageHandler(result -> {
            if (eventSink == null) return null;

            Map<String, Object> response = new HashMap<>();
            response.put("message", result.getCode());

            switch (result.getType()) {
                case success:
                    response.put("type", "success");
                    eventSink.success(response);
                    break;
                case exit:
                    response.put("type", "exit");
                    eventSink.success(response);
                    break;
                case failure:
                    response.put("type", "failure");
                    eventSink.success(response);
                    break;
                default:
                    eventSink.error("UNKNOWN", "Unknown result type", null);
            }
            return null;
        }); 
    }
}

All you have to do is create the link with the native iOS code in your AppDelegate and connect the channel with your ShareID messageHandler .

import UIKit
import Flutter
import shareid_sdk_ios

@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
    private let methodChannelName = "shareid_sdk_method_channel"
    private let eventChannelName = "shareid_sdk_event_channel"
    
    private var eventSink: FlutterEventSink?
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        
        let methodChannel = FlutterMethodChannel(name: methodChannelName, binaryMessenger: controller.binaryMessenger)
        methodChannel.setMethodCallHandler(handleMethodCall)

        let eventChannel = FlutterEventChannel(name: eventChannelName, binaryMessenger: controller.binaryMessenger)
        eventChannel.setStreamHandler(self)

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

    /// **Sets up a single persistent listener for ShareID events**
    private func setupMessageHandler() {
        ShareID.shared.messageHandler = { result in
            guard let eventSink = self.eventSink else { return }

            var response: [String: Any] = [
                "message": result.code
            ]
            
            switch result.type {
                case .success:
                    response["type"] = "success"
                case .failure:
                    response["type"] = "failure"
                case .exit:
                    response["type"] = "exit"
                @unknown default:
                    fatalError()
            }
            
            eventSink(response)
        }
    }
    
    private func handleMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any], let token = args["token"] as? String else {
            result(FlutterError(code: "INVALID_ARGUMENTS", message: "Token is required", details: nil))
            return
        }

        switch call.method {
            case "signUp":
                ShareID.shared.start(service: ShareID.Service.onboarding, token: token)
                result("ShareID onboarding flow has been started")
            case "signIn":
                ShareID.shared.start(service: ShareID.Service.authenticate, token: token)
                result("ShareID authenticate flow has been started")
            default:
                result(FlutterMethodNotImplemented)
        }
    }
}

extension AppDelegate: FlutterStreamHandler {
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        return nil
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        self.eventSink = nil
        return nil
    }
}

Make sure you use the same keys as shareid_service.dart

The service specifies the service in the SDK:

  • onboarding starts the onboarding process

  • authenticate starts the authenticate process

5. Get the Analysis result

When the processing of an onboarding request is finished, you may receive the result through the callback if you provided it. You may also, fetch yourself the result by calling our API.

Customisation

The ShareID SDK is designed to be highly customisable, allowing great flexibility through various configuration options or the application of themes to adapt the user interface to your needs. To do this, simply follow this same section in the Android and iOS documentation and add them to your code.

FAQ

Why does my IDE display "Code insight unavailable (related Gradle project not linked)" ?

This error appear in your IDE (probably Android Studio or IntelliJ IDEA) means that the Gradle project is not properly linked to the IDE. This issue prevents features like autocompletion, syntax highlighting, and code navigation from working properly.

There are several solutions to this problem. The most coherent would be to open the Android file directly to modify your Java or Kotlin files, and to open your Flutter project for the other modifications.

So, File > Open... > <your-flutter-app> > Select android file and press Open


Technical support and contact 💬

However, conflicts may arise that require you to integrate dependencies yourself (notably , , , etc.).

You must add NSCameraUsageDescription within your application's Info.plist file (see ).

ShareID supports with authenticate handled via a .netrc file.

Depending on the SDK you are integrating (Onboarding/Authenticate), you may use an API here

To view all possible end-of-process results in our SDK, please refer to the for all success, exit and failure states.

See for more details.

kotlin
material3
compose
Apple documentation
CocoaPods
Get a Token
Message Handler
Get the analysis result
support@shareid.ai
Set up the SDK
Get a token
Start an onboarding or authenticate flow and get the user workflow result from SDK
Get the Analysis result