Flutter

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

Getting started

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

  1. Set up the SDK: install and import the SDK

  2. Get a token: request a token using your business credentials

  3. Start an onboarding or authenticate flow and get the user workflow result from SDK: launch a user workflow and use the Message handler to get insights about the user workflow

  4. Get the Analysis result: 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

Conflicts of dependency

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

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

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.

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

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.utils.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 ->
            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;
        }); 
    }
}

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

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

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.

See Get the analysis result for more details.

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


Technical support and contact 💬

Last updated