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. Get the user workflow result from SDK: 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

Respect all the parameters and requirements of the Android SDK so that Flutter can function fully.

Install SDK

Unlike native Android integration, you'll need to use Maven in your <your-flutter-app>/android/build.gradle file.

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

The minSdk or minSdkVersion of the Flutter project must be identical to that of our Android SDK.

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

Use your token to start an onboarding or an authenticate.

Step 1: Create the ShareID service

The purpose of this service is to act as a bridge between your Dart code and the native Android/iOS code. It relies on MethodChannel, which enables Flutter to call platform-specific features and receive results, since Flutter runs in a separate engine that cannot directly access 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 Future<void> signUpWithShareID(String token) async {
    await _invokeMethod('signUp', token);
  }

  static Future<void> signInWithShareID(String token) async {
    await _invokeMethod('signIn', token);
  }

  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

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");
  }
}

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.

Kotlin

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

class MainActivity : FlutterActivity() {

    private val METHOD_CHANNEL = "shareid_sdk_method_channel"
    
    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")
            }
        }
    }
}

Java

import android.os.Bundle;
import androidx.annotation.NonNull;

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

public class MainActivity extends FlutterActivity {
    private static final String METHOD_CHANNEL = "shareid_sdk_method_channel";

    @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");
                }
            });
    }
}

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

4. Get the user workflow result from SDK

To receive feedback from the SDK, you need to implement the messageHandler closure, which manages various responses from the ShareID process.

This closure is triggered when the ShareID SDK completes an operation, fails, or encounters an error.

Step 1: Connect the service to the message handler

This time we're going to use EventChannel.

  1. Add these lines to your shareid_service.dart file

class ShareIDService {
  static const EventChannel _eventChannel = EventChannel('shareid_sdk_event_channel');
  
  static Stream<Map<String, dynamic>> get events {
    return _eventChannel.receiveBroadcastStream().map((event) => Map<String, dynamic>.from(event));
  }
}
  1. Use initState to listen for events in your main.dart file

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

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

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

Step 2: Update the service to listen to all events

Connect the channel with your ShareID messageHandler by adding the following lines to your MainActivity.

Kotlin

import io.flutter.plugin.common.EventChannel

class MainActivity : FlutterActivity() {

    private val EVENT_CHANNEL = "shareid_sdk_event_channel"

    private var eventSink: EventChannel.EventSink? = null

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        /// Your Method channel

        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 io.flutter.plugin.common.EventChannel;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends FlutterActivity {
    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 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;
        }); 
    }
}

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