Aarambh SDK docs

This integration guide is shared with a username and password. Ask whoever sent you the link if you don't have them.

That username and password don't match. Double-check and try again.
Aarambh SDK / flutter-plugin

Flutter integration guide

How to embed the Aarambh SDK in a Flutter app via flutter-plugin/ (aarambh_sdk). The package is a thin pass-through — every Dart method forwards to com.aarambh.sdk.AarambhSDK over a single MethodChannel. No business logic lives in the Flutter or Kotlin layers.

Status

Validated end-to-end. The full call chain — from a Dart method call, through the plugin bridge, into the SDK's native layer, and on to either its own UI or a direct API call — has been built, installed, and run against a real device, including a live headless login call round-tripping to the backend.

Platform support

Android only. flutter-plugin/pubspec.yaml declares a single platform:

pubspec.yaml
flutter:
  plugin:
    platforms:
      android:
        package: com.aarambh.sdk.flutter
        pluginClass: AarambhSdkPlugin

There is no ios/ directory and no iOS SDK to bind against yet. A Flutter app that also ships iOS will need its own conditional handling (e.g. checking Platform.isAndroid) until an iOS binding exists.

Architecture

Every call takes the same route from Dart down to native, whether it opens the SDK's own UI or just fires a REST call.

  1. Flutter app (Dart)
  2. AarambhSdk
    lib/aarambh_sdk.dart
  3. MethodChannel('aarambh_sdk')
  4. AarambhSdkPlugin.kt
    flutter-plugin/android — implements FlutterPlugin + MethodCallHandler + ActivityAware. Every onMethodCall branch does nothing but unpack arguments and call the matching AarambhSDK method.
  5. AarambhSDK.getInstance()
    android/sdk — the real implementation.
  6. SDKActivity (the SDK's own UI) — or a direct REST call

Acquiring a session

Before your app calls login(), your own backend creates the agent and acquires a session token, using two REST endpoints on Aarambh's integrations API. These are server-to-server calls — call them from your backend, not from the mobile app.

Keep these credentials server-side

x-access-key and x-secret-key authenticate your backend to this API and must never ship inside your mobile app — anyone who extracts them from an APK could call these endpoints as you. Only the resulting session token ever reaches the app.

1. Create the user

Registers the agent against your subscriber account. Only needs to run once per agent.

curl · create_user
curl --location 'https://integrations.lsp.aarambh.cloud/api/v1/lsp/integrations/create_user' \
  --header 'subscriberid: {{subscriberid}}' \
  --header 'x-access-key: {{x-access-key}}' \
  --header 'x-secret-key: {{x-secret-key}}' \
  --header 'Content-Type: application/json' \
  --data '{
    "firstName": "shashank",
    "lastName": "rao",
    "profilePic": "",
    "gender": "male",
    "mobile": "7892506686",
    "addressDetails": {
      "location": { "type": "Point", "coordinates": [77.5946, 12.9716] },
      "pincode": "560001",
      "city": "Bangalore"
    },
    "verified": true,
    "enabled": 1
  }'

2. Acquire a session

Returns a session token for that mobile number — call this whenever your app needs a fresh authToken to hand to the SDK (e.g. on each login, not just once at registration).

curl · aquire_session
curl --location 'https://integrations.lsp.aarambh.cloud/api/v1/lsp/integrations/aquire_session' \
  --header 'subscriberid: {{subscriberid}}' \
  --header 'x-access-key: {{x-access-key}}' \
  --header 'x-secret-key: {{x-secret-key}}' \
  --header 'Content-Type: application/json' \
  --data '{
    "mobile": "7892506686",
    "notifyToken": "<FCM device token for push notifications>"
  }'

Hand the session token from the response to AarambhSdk.login(authToken: ...) in your Flutter app to route straight to the SDK's home screen, skipping its own OTP UI — see API reference below.

Prerequisites

Match these against your Flutter app's android/ config — the SDK module (android/sdk) is built with:

minSdkVersion
26
compileSdk / targetSdk
36
Java / Kotlin target
21
AGP
8.7.2
Kotlin
1.9.24

flutter-plugin/android/build.gradle itself is currently pinned to compileSdk 35 (one behind the SDK module's 36) — bump it to 36 if you hit a compileSdk mismatch warning or error when building against a Flutter app whose own compileSdk is 36.

Kotlin Gradle Plugin version

On a recent Flutter SDK (3.44+), the Flutter engine embedding requires kotlin-stdlib:2.2.20 across every module in your app's Gradle build, regardless of what a plugin subproject's own buildscript declares for its compiler version — flutter-plugin/android/build.gradle's kotlin-gradle-plugin classpath is set to 2.2.20 for this reason. Your Flutter app's own android/settings.gradle (or .kts) needs to declare a matching or newer org.jetbrains.kotlin.android version.

Your Flutter app also needs the standard Android embedding v2 (the default for any app created with a current Flutter SDK) — this plugin does not support the legacy v1 embedding.

1. Add the dependency

Not yet published to pub.dev. For local integration, point at it by path in your Flutter app's pubspec.yaml:

pubspec.yaml
dependencies:
  aarambh_sdk:
    path: <PATH_TO_SDK_REPO>/flutter-plugin

Resolving the native com.aarambh:sdk dependency

flutter-plugin/android/build.gradle depends on com.aarambh:sdk:0.1.0-local, which isn't published anywhere either. Your Flutter app's top-level android/settings.gradle needs a composite build that substitutes it with the real module from the SDK repo:

android/settings.gradle
includeBuild('<PATH_TO_SDK_REPO>/android') {
    dependencySubstitution {
        substitute module('com.aarambh:sdk') using project(':sdk')
    }
}

android/sdk/build.gradle in the SDK repo needs a group/version for that substitution to resolve — if they're not already present, add:

android/sdk/build.gradle
group = 'com.aarambh'
version = '0.1.0-local'

Then run:

terminal
# from your Flutter app
flutter pub get

Building your app

If your Flutter app's own Gradle/AGP/Kotlin versions are pinned down to match the SDK's android/ config (a recent flutter create scaffolds newer defaults than its AGP 8.7.2), Flutter will warn that support for those versions "will soon be dropped." Expected here, not a misconfiguration — pass a flag to suppress it:

terminal
flutter run --android-skip-build-dependency-validation
flutter build apk --android-skip-build-dependency-validation

The composite build resolves flutter-plugincom.aarambh:sdk → the SDK's own UI assets transitively.

Reference sample app

We maintain a reference Flutter sample app (and a native Kotlin equivalent) that demonstrates every step above end-to-end — a real Flutter app wired to flutter-plugin via a pubspec.yaml path dependency, exercising every AarambhSdk method from a UI, including the full headless OTP/onboarding wizard. Ask your integration contact for access if your own composite-build wiring isn't resolving.

2. Manifest, Firebase, and permissions

flutter-plugin/android/src/main/AndroidManifest.xml itself declares nothing but an empty <application /> — everything the SDK needs (SDKActivity, a FileProvider, an FCM MessagingService override) is declared in android/sdk's own manifest and merges in automatically through the Gradle module dependency. You shouldn't need to add any of that manually.

Manifest merge

Your app's merged manifest should contain SDKActivity, com.aarambh.plugins.background.OverlayService, MyFirebaseMessagingService, and the location/foreground-service permissions, pulled in transitively via capacitor-background-location. If any are missing, the composite build substitution didn't pick up the dependency correctly.

Firebase setup is required before calling launch()

The moment SDKActivity boots, it registers for push notifications, which requires a FirebaseApp to already exist in your app's process — without one, the process throws IllegalStateException: Default FirebaseApp is not initialized.

real push notifications. Add your own google-services.json (registered for your applicationId — ours is tied to a specific one and won't match yours) and apply both com.google.gms.google-services and com.google.firebase.crashlytics. The latter is needed because com.aarambh:sdk transitively pulls in @capacitor-firebase/crashlytics, whose registrar is always-eager and crashes with The Crashlytics build ID is missing the instant any FirebaseApp initializes, unless that plugin has run at build time to inject it. It's a separate plugin from google-services and needs no real Firebase project itself, just the classpath.

Runtime permissions

Manifest entries are necessary but not sufficient. Your Flutter app still needs to request location/notification/camera permissions at runtime (Android 6+) before the SDK's background tracking will actually start — either handle this yourself, or call requestPermissions() to trigger the SDK's own permission UI.

API reference — AarambhSdk

flutter-plugin exposes the same full surface as the native dummy app's MainActivity.kt — every public method on native AarambhSDK has a matching MethodChannel case and Dart method, split into two groups.

Pass-through / dispatch methods

Return Future<void>, resolve with null on success, throw PlatformException on failure (e.g. launch() called with no attached Activity throws code NO_ACTIVITY).

Dart method Native call Notes
initialize(config) AarambhSDK.initialize() Call once at startup, before any other call. See config keys below.
login({authToken, userDetails}) AarambhSDK.login() Hands over an existing session instead of driving the SDK's own OTP flow.
launch() AarambhSDK.launch(activity) Starts SDKActivity. Throws NO_ACTIVITY with no attached Flutter Activity.
close() AarambhSDK.close() Finishes the currently active SDKActivity, if any.
requestPermissions() AarambhSDK.requestPermissions() Triggers the SDK's step-by-step permission workflow. Starts SDKActivity if not already running.

Onboarding wizard methods

Direct REST calls, no WebView/SDKActivity/SDK UI ever shown. Return Future<Map<String, dynamic>> on success, throw PlatformException with code SDK_ERROR on failure. initialize() must be called first — every one of these reads clientUri/subscriberId from it. Your app is responsible for obtaining the OTP and the agent's agentId through your own backend before calling these.

Dart method Native call Notes
verifyOtp({mobile, otp}) AarambhSDK.verifyOtp() Verifies an OTP your app already obtained, establishing a real session; a later launch() picks it up automatically.
selectVehicle({agentId, vehicle, weight}) AarambhSDK.selectVehicle() Wizard step 2. weight is a host-app-owned lookup value.
uploadDocument({base64Data, mimeType, fileType}) AarambhSDK.uploadDocument() Shared upload for every wizard photo step. Response has location + echoed fileType.
submitVehicleInfo({agentId, fields, uploads}) AarambhSDK.submitVehicleInfo() Wizard step 3. uploads maps fileType → URL from uploadDocument().
submitBankDetails({agentId, fields}) AarambhSDK.submitBankDetails() Final step. On success, clears the native session — expect to need OTP again.

initialize() config keys

dart
await AarambhSdk.initialize({
  'environment': 'sandbox',   // 'sandbox' | 'live' — defaults to 'live' if omitted
  'subscriberId': 'my-subscriber-id',
  'appname': 'My Flutter Host App',
  // optional branding:
  // 'vendorCode': '...',
  // 'clientLogo': '...',
  // 'privacy': 'https://...',
  // 'terms': 'https://...',
  // 'overlayIconUrl': 'https://.../icon.png',
});
  • clientUri/sseUri are not accepted from the host app — resolved internally from environment, always overwriting anything passed under those keys. environment defaults to live if omitted, so a forgetful integration fails safe to production rather than silently landing on sandbox.
  • overlayIconUrl needs more than just being present in this config to actually show up — it only reaches the native overlay bubble once the SDK's UI reaches its home screen with a backend-accepted session (a fake/expired token that gets rejected never gets there). It's then fetched and cached lazily the first time the bubble is shown.
Dispatch is live-only

start(), stop(), setUser(), acceptOrder(), rejectOrder(), and login()/logout() all forward to whatever screen currently owns that logic inside SDKActivity. If SDKActivity isn't currently running when you call one of these, the call is silently dropped — not queued, no error. Call launch() first, or make sure SDKActivity is already visible.

Usage example

main.dart
import 'package:aarambh_sdk/aarambh_sdk.dart';
import 'package:flutter/services.dart';

Future<void> setupAarambhSdk() async {
  // Call once at startup — BEFORE login()/launch()/any other call.
  // Values are only read when SDKActivity starts up.
  await AarambhSdk.initialize({
    'environment': 'sandbox',
    'subscriberId': 'my-subscriber-id',
    'appname': 'My Flutter Host App',
  });
}

Future<void> loginExistingSession(String authToken) async {
  // Your app's own login/claim-session API already returned this
  // authToken - hand it to the SDK to route straight to home, skipping
  // its own OTP UI. userDetails is optional.
  await AarambhSdk.login(authToken: authToken);
}

Future<void> openSdkUi() async {
  try {
    await AarambhSdk.launch(); // starts the visible SDKActivity
  } on PlatformException catch (e) {
    if (e.code == 'NO_ACTIVITY') {
      // launch() needs a widget/screen context, not a background isolate.
    }
    rethrow;
  }
}

// Once SDKActivity is showing (e.g. triggered from elsewhere in your app):
Future<void> startTracking() => AarambhSdk.start();
Future<void> stopTracking() => AarambhSdk.stop();
Future<void> acceptOrder(String orderId) => AarambhSdk.acceptOrder(orderId);
Future<void> rejectOrder(String orderId) => AarambhSdk.rejectOrder(orderId);

Future<void> signOut() async {
  await AarambhSdk.close();  // finish SDKActivity first, if open
  await AarambhSdk.logout();
}

// Onboarding wizard - no SDK UI ever shown, runs over native HTTP. Your
// app owns 100% of its own login/onboarding screens; it's responsible
// for obtaining the OTP and the agentId itself (e.g. from your own
// backend) before calling into this wizard.
Future<void> onboardingExample(String mobile, String otp, String agentId) async {
  await AarambhSdk.verifyOtp(mobile: mobile, otp: otp);     // establishes a real session

  await AarambhSdk.selectVehicle(agentId: agentId, vehicle: 'bike', weight: 5.0);

  final upload = await AarambhSdk.uploadDocument(
    base64Data: '<base64-encoded-photo>',
    mimeType: 'image/jpeg',
    fileType: 'aadhaarProof',
  );
  final documentUrl = upload['location'] as String;

  await AarambhSdk.submitVehicleInfo(
    agentId: agentId,
    fields: {'vehicleNumber': 'KA01AB1234', 'brandName': 'Honda'},
    uploads: {'aadhaarProof': documentUrl},
  );

  // Final step — clears the session on success, so a real host app
  // would route back to login here.
  await AarambhSdk.submitBankDetails(
    agentId: agentId,
    fields: {
      'accountHolderName': 'Test Driver', 'accountNumber': '123456789012',
      'bankName': 'Test Bank', 'branchName': 'Test Branch',
      'IFSCcode': 'TEST0001234', 'bankStatement': documentUrl,
    },
  );
}
Aarambh SDK · Flutter integration guide. Questions about anything on this page? Reach out to your integration contact.