Migrating to the Scope SDKs (ConsolidatedSPM 1.1.1) — Flutter - scopetech/Mobile-Public GitHub Wiki
Migrating to the Scope SDKs (ConsolidatedSPM 1.1.1) — Flutter
Flutter analogue of the iOS migration guide, for teams integrating the SmartDrive / SDApiManager / TripWrapper SDKs in a Flutter app. Related wiki pages: Flutter Session & App Lifecycle Management, Flutter Diagnostic Logs and Export.
The SDKs are native iOS frameworks; in a Flutter app they live in ios/Runner.
This migration therefore touches only the native side — your Dart code, the
platform channel contract, and the Dart↔native call flow are unchanged. If your
Runner follows the lifecycle guide, this is a dependency bump plus at most three
one-line Swift fixes.
Target versions
Same as the iOS guide — update ios/Runner's package dependencies:
| Package | Version |
|---|---|
| ConsolidatedSPM-iOS | 1.1.1 (recommended — pins all of the below) |
| SCPSmartDriveSPM-iOS | 1.1.18 |
| TripWrapperSPM-iOS | 1.0.9 |
| SDApiManagerSPM-iOS | 1.0.7 |
| BLEFrameworkSPM-iOS | 1.0.5 |
| BiosenseSignalSPM-iOS | 1.0.0 |
| WellnessSPM-iOS | 1.0.1 |
[!IMPORTANT] SCPSmartDrive and TripWrapper are a matched pair — Consolidated 1.1.1 updates them together. Commit the updated
Package.resolvedunderios/.
Step 1 — Update the native dependency
Open ios/Runner.xcworkspace (or the Runner project) in Xcode, bump
ConsolidatedSPM-iOS to 1.1.1, then File → Packages → Reset Package Caches and
Clean Build Folder. Build the Runner once from Xcode before returning to
flutter build — Swift compile issues are far easier to fix there.
Step 2 — Fix what the Swift compiler flags (Runner only)
Three known items, all in ios/Runner Swift code (typically your AppDelegate or the
coordinator class it uses); each is mechanical:
APIManagerProtocol.isRealtimeSendingEnabled()— if your conformance is flagged as incomplete, add:func isRealtimeSendingEnabled() -> Bool { return false } // batch mode = previous behaviorCCTimeIntervalis no longer Optional — removeif let/guard letaround its initializer where the compiler flags "must have Optional type."didReceiveLogoptionality — if the Runner implements the SmartDrive log delegate:description text: String!→description text: String.
Nothing changes in Dart. The channel methods from the lifecycle guide
(isAuthorized, login, logout, refresh, enterBackground) and the log-export
flow are source- and behavior-compatible.
Step 3 — Behavior changes to review
Identical to the iOS guide, summarized — see it for detail:
- Stops longer than the trip-end threshold (default 300 s) end the trip, including long in-vehicle standstills; driving on starts a new trip.
- Map-based mode-of-transport skipping is capped at
kSettingsMOTSkipMaxDistance(new default 3000 m) — set explicitly if you relied on unlimited skipping. - Trip end times are the actual stop moment; notifications align with the recorded lifecycle.
- If your native
TripNotificationDelegateskips scheduling while foreground, stop doing that — always schedule; decide foreground presentation inuserNotificationCenter(_:willPresent:).
Step 4 — What you get automatically
- The full set of iOS 26 trip-reliability fixes (see the iOS guide).
- Health snapshots in the diagnostic log:
TRIPWRAPPER HEALTH SNAPSHOTblocks at initialization, trip start/end, and backgrounding — versions, permission states (with ⚠️ markers), SDK configuration, trip counts. They flow through the existing export path from the Flutter Diagnostic Logs and Export guide unchanged. If you render logs in a Dart UI one line per entry, note snapshots are multi-line — show them expandable, or read them in the exported file. - GPS startup diagnostics include the location authorization status — a wrong-permission device announces itself in the first screen of the log.
Step 5 — Verify
[!IMPORTANT] Fresh installs reset iOS location permission — and Flutter development cycles reinstall often. After any reinstall, confirm Location Always + Precise Location + Background App Refresh before test drives. The health snapshot flags all three.
Then run the drive-test checklist from the iOS guide (trip splits at long stops, no
duplicates on the portal, notifications matching real trips, corridor trips recorded)
plus the two Flutter-specific checks from the lifecycle guide: a background
autostart drive with the app killed (arming lives in native
didFinishLaunchingWithOptions, not the channel), and a screen-off drive (no
re-login, recording continues).
Note on the lifecycle guide's demo references
The lifecycle guide says to copy initializeFeatures / configureSmartDrive from the
SmartDriveDemo AppDelegate unchanged. The demo has since adopted the optional
simplified facade (ScopeSDK + AppScopeHost); both integration styles remain fully
supported. For this migration, keep your existing Runner code — only apply the
Step 2 fixes. If you later modernize, follow
iOS Simplified SDK Integration
(section 5 covers the Runner specifics — the two files to copy live on the
SmartDriveDemo feature/sdk_simplification branch); the channel contract is
unaffected either way.