Flutter
Getting started
In order to perform an Onboarding or an Authenticate, you should follow those steps:
- Set up the SDK: install and import the SDK
- Get a token: request a token using your business credentials
- 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
- 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.
- Add the following to your
build.gradle
- You can now synchronise and use the SDK in your project
Info
Make sure you update your various dependencies, distributionUrl, IDE, gradle version or anything else.
Warning
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.).
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
Warning
Mandatory app permission
The SDK uses the device's camera functionality.
You must add NSCameraUsageDescription
within your application's Info.plist
file (see Apple documentation).
1.2. Install SDK
ShareID supports CocoaPods with authenticate handled via a .netrc
file.
To securely manage your credentials, you’ll need to create a .netrc
file in your home directory with the necessary login details.
- Create and open
Type touch ~/.netrc & open ~/.netrc
- Add login details
- 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
)
- Add the following to your target
platform :ios, '15.0'
target '<your-app>' do
use_frameworks!
pod 'shareid-sdk-ios' # or specific version
end
- Run
pod install
to install the dependency - Now, you can import and use the SDK in your project
Important
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.
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.
- 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");
}
}
}
- 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
}
}
Warning
Make sure you use the same keys as shareid_service.dart
The service
specifies the service in the SDK:
onboarding
starts the onboarding processauthenticate
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.
4. 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.