Dashboard

Flutter SDK

sentriq_flutter is a thin MethodChannel plugin over the existing native iOS (Swift) and Android (Kotlin) Sentriq SDKs — it never reimplements transport, installation ID, session logic, or device-signal collection; every event still reaches POST /v1/events through the exact same native client the platform-specific SDKs use.

Requirements

  • Flutter 3.3.0+ (tested against the current stable, 3.47.4), Dart 3.13+
  • iOS 15.0+, Android minSdk 24
  • iOS and Android only — see Platform support

Install

Not yet published to pub.dev — install from a checked-out commit of this repository until a release process exists (a path dependency, or a local copy):

# pubspec.yaml
dependencies:
  sentriq_flutter:
    path: /path/to/sentriq/packages/flutter-sdk

Flutter's plugin registration handles the rest automatically — no manual native linking step. iOS additionally needs a pod install (cd ios && pod install) since this SDK ships a CocoaPods podspec, the current production-recommended mechanism for Flutter iOS plugins (Swift Package Manager plugin support remains experimental in Flutter itself and is not used here).

Configure

import 'package:sentriq_flutter/sentriq_flutter.dart';

await Sentriq.configure(SentriqOptions(publicKey: 'pub_test_xxx'));

Call this once, typically at app startup (before or inside runApp). Safe to call again later — the latest call wins, matching both native SDKs' own re-configure behavior.

Never embed a secret key in a mobile app
Anything inside a shipped app bundle is public. SentriqOptions has no secret-key field at all — Dart's static typing makes it a compile error to even try, and the underlying native SDK additionally rejects a sec_... value at runtime with a SentriqConfigurationException.

Track an event

import 'package:sentriq_flutter/sentriq_flutter.dart';

Future<void> handleLogin(String userId) async {
  try {
    final result = await Sentriq.track(
      SentriqEventType.login,
      account: SentriqAccountReference(id: userId),
      screenName: 'login_screen',
    );
    // result.risk.decision: allow | monitor | challenge | block
  } on SentriqException catch (e) {
    // e.g. SentriqValidationException, SentriqApiException, SentriqTimeoutException
  }
}

Account association

Pass account: SentriqAccountReference(id: ...) to track() once you know who the current user is — your own opaque reference, never a password or email. Omit it for anonymous events.

Installation ID and session — no Dart-side duplicate

This SDK has no Dart-side installation or session identifier of its own — the underlying native SDK (Keychain-backed on iOS, SharedPreferences-backed on Android) remains the sole authority, exactly as it is for a native-only integration. Sentriq.getInstallationId() reads it read-only, for debugging.

Native architecture

A thin platform-interface abstraction (SentriqPlatform) over a plain MethodChannel — the current standard mechanism a Flutter plugin this size uses (Pigeon-generated typed channels remain an option for a larger surface, but were not needed here). The channel is implemented by a thin Swift class (iOS) and a thin Kotlin class (Android), each doing nothing but validate/convert arguments, map native errors to a stable code, and delegate straight into the real native SentriqClient. See docs/architecture/FLUTTER_SDK.md in the repository for the full plugin design.

Error handling

Every failing call throws a typed SentriqException subclass, mapped consistently from the underlying native SDK's own typed error on both platforms:

SentriqConfigurationException | SentriqValidationException | SentriqNetworkException |
SentriqTimeoutException | SentriqCancelledException | SentriqDecodingException |
SentriqApiException | SentriqPlatformException

SentriqApiException/SentriqValidationException additionally carry status, code, requestId, and (validation only) fields. SentriqPlatformException is this package's own catch-all for a bridge-level failure not originating from the native client at all (e.g. no native implementation is registered for the current platform).

Custom API URL (local/dev)

await Sentriq.configure(SentriqOptions(
  publicKey: 'pub_test_xxx',
  apiUrl: Uri.parse('http://10.0.2.2:8000'), // Android emulator's alias for your host's localhost
));

Platform support

iOS and Android only. Web and every desktop target (macOS, Windows, Linux) are explicitly unsupported — calling any Sentriq method there throws a clear UnsupportedError naming the unsupported platform, rather than silently doing nothing. This package still compiles for every Flutter target (including web); only calling a method on an unsupported target throws.

A Flutter web app wanting Sentriq should use @sentriq/browser directly (e.g. via dart:js_interop) — this package deliberately does not build a second Dart-only HTTP implementation to fake web support.

Privacy

This plugin collects no data of its own — every signal (installation ID, session, device metadata) is owned entirely by the underlying native SDK, with the same privacy guarantees documented on the iOS and Android pages. No device-info Dart package (device_info_plus, package_info_plus, connectivity_plus) is used — everything track() needs is already collected natively.

Runtime verification limitations

  • iOS: plugin source is written and reasoned through carefully against the real, vendored native SDK source, but build/runtime is not verified — no Xcode/macOS was available in the environment this SDK was built in.
  • Android: the plugin builds for real, its own unit tests pass (including a real event sent to a real API, fully round-tripped through the plugin's own result serialization), and a real debug APK builds successfully for the example app. Full device/emulator UI-level runtime execution was not verified — no emulator/device was available.

Troubleshooting

  • Gradle can't resolve io.sentriq:sentriq-android — this SDK isn't published to Maven Central yet; run ./gradlew publishToMavenLocal from sdks/android, then add mavenLocal() to your app's own root android/build.gradle(.kts) allprojects { repositories { ... } } block — adding it only to a plugin's own build file is not enough, since your app resolves its own transitive dependencies using its own repository list.
  • UnsupportedError at runtime — you're running on web or a desktop target; see Platform support above.