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.
To install the SDK, you'll need to add the dependency in your app module.
Add the following to your build.gradle
implementation("ai.shareid:sdk:+") // or specific version
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.
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
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.
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
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.
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.
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;
});
}
}
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
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.
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