This guide explains how to build a Flutter plugin - prism_capture - that wraps the body-scan capture experience only of PrismSDK for both iOS and Android behind one unified Dart API. The plugin presents the full-screen capture UX, receives the output zip, and performs a direct PUT upload to an S3 presigned URL that your backend obtains from the Prism API. No Prism API credentials are needed on the device; all REST calls (user management, scan records, measurements, health reports) remain on the backend and are out of scope for this plugin.
Wraps:
.zip file written to local storage.Content-Type: application/zip).Does NOT wrap:
PrismSDK-Info.plist on iOS and no API credentials on Android.Dart Layer
└── PrismCapture (lib/prism_capture.dart)
├── MethodChannel "tech.prismlabs.prism_capture/methods" ← commands
└── EventChannel "tech.prismlabs.prism_capture/events" ← typed event stream
├── iOS: PrismCapturePlugin.swift
│ FlutterPlugin + FlutterStreamHandler
│ presents PrismSessionViewController via UIHostingController
│ FileUploader (PrismLink) for background S3 PUT
└── Android: PrismCapturePlugin.kt
FlutterPlugin + MethodCallHandler + StreamHandler + ActivityAware
launches PrismCaptureActivity (ComponentActivity + Compose)
PrismSessionView Composable wraps PrismSession controller
Ktor client for S3 PUT
The plugin uses the present native full-screen via method channel + stream events back model: startCaptureSession instructs the native side to present a new full-screen VC (iOS) or launch a new Activity (Android); the Future returned by startCaptureSession completes when the command is accepted, not when the UI finishes presenting. Events - status changes, archive delivery, upload progress - flow back through the EventChannel stream as typed maps. This gives the capture surface full access to camera hardware and native animations without embedding a PlatformView.
PlatformView alternative: If your app needs the capture surface inline (e.g., inside a tab layout), you can host it as a UiKitView (iOS) or AndroidView (Android) instead. That requires the native plugin class to register a FlutterPlatformViewFactory and is more complex to size and lifecycle-manage. The method-channel + full-screen model is strongly preferred for capture.
| Dart Method | What it does | Platform notes |
|---|---|---|
startCaptureSession({CaptureOptions? options}) |
Presents the full-screen capture flow. Returns Future<void> when the command is accepted (not when the UI finishes presenting). |
Both platforms |
dismissCaptureSession() |
Programmatically dismisses the capture UI. Returns Future<void>. |
Both platforms |
uploadCapture(String filePath, String presignedUrl) |
Uploads the zip at filePath via HTTP PUT to presignedUrl. Returns Future<void>. |
Both; see platform differences |
setupUploader() |
Resumes interrupted background uploads from a previous app session. Returns Future<void>. |
iOS only. On Android this is a documented no-op. |