TesterPayKit class

Main SDK class for TesterPayKit

Properties

aggregator MetricsAggregator
Metrics aggregator
final
annotatedScreenshotService AnnotatedScreenshotService
Annotated screenshot service (Phase 2)
final
anonymousAuthReady Future<void>
Resolves once initial anonymous-tester-token acquisition has finished (success OR give-up). Always completes — never throws. Safe to await from a widget's initState before firing an authenticated GET, e.g. _updateRetestCount in TesterWrapper. Without this, the wrapper's initState calls raced the fire-and-forget token mint and 401-ed deterministically on every fresh launch (issue: web console retests → 401).
no setter
apiClient ApiClient
API client
final
Breadcrumb tracker (Phase 1)
final
bugReportUploadService BugReportUploadService
Bug report upload service (Phase 4)
final
config TesterPayKitConfig
Current configuration
final
connectivityMonitor → ConnectivityMonitor
Triggers drain on connectivity change.
final
database → TesterPayKitDatabase
Database instance
final
deviceId String
Device identifier (rotated every 30 days)
final
eventTracker EventTracker
Event tracker
final
hashCode int
The hash code for this object.
no setterinherited
isAuthenticated bool
Whether the SDK currently holds a usable tester token.
no setter
isTokenReady bool
Whether the anonymous tester token has been acquired. Host apps can use this to gate features that need auth, but it's OPTIONAL — the queue drains automatically once the token arrives.
no setter
A ready-made NavigatorObserver the host adds to its MaterialApp (navigatorObservers: [TesterPayKit.instance.navigatorObserver]) so route pushes are auto-counted as screen views — no per-screen trackScreenView instrumentation needed. See TpkNavigatorObserver for the why (under-counted navigation → under-paid testers).
no setter
networkCapture NetworkCaptureService
Network capture service
final
onTokenReady Future<void>
Resolves when the anonymous token is acquired (or all retries exhausted). Never throws — always completes.
no setter
outboxDao → OutboxDao
Outbox DAO — enqueue + query the outbox table.
final
outboxDepth int
Number of pending items in the outbox. Backed by an in-memory count the OutboxDao refreshes after every outbox mutation.
no setter
outboxDrainer → OutboxDrainer
Background queue processor.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
serverDeviceId String?
no setter
sessionManager SessionManager
Session manager
final
submissionService SubmissionService
Submission service
final
taskProgress → TaskProgressService
Tester checklist progress — drives the "X von Y erledigt" display and auto-completes tasks the tester demonstrably did (see TaskProgressService + the host-app TesterTaskRelevant annotations).
final

Methods

checkForUnreportedCrashes(BuildContext context) Future<void>
Check for unreported crashes (call this in your app's main widget)
completeTask(String taskId) Future<void>
Complete a task
createSubmission() Future<SubmissionResult>
Create a weekly submission. Now delegates to the non-blocking createSubmissionAsync — the submission is enqueued to the outbox and uploaded in background.
createSubmissionAsync() Future<String>
Create a weekly submission without blocking. The submission is enqueued to the outbox and uploaded in background. Returns a local UUID. Use getSubmissionStatus to track progress.
dispose() Future<void>
Dispose resources
flushAndEndSession({String endReason = 'lifecycle_flush'}) Future<void>
Drain in-memory breadcrumbs + local events to the server, then end the active session. Safe to call when no session is active (no-op) and idempotent within a single session.
flushCachedCrashes() Future<int>
Drain the local Drift crash_contexts table to the server as minimal bug-reports. Each unreported crash becomes one bug-report with title="Auto-reported crash: <error>", description=stackTrace, severity="medium", category="crash". Marks each row as reported only after a successful POST so a network hiccup doesn't lose data.
getAppMetadata() Future<AppMetadata>
Get app metadata.
getDeviceMetadata() Future<DeviceMetadata>
Get device metadata
getSubmissions({SubmissionStatus? status, int limit = 10}) Future<List<WeeklySummary>>
Get submissions
getSubmissionStatus(String localId) Future<OutboxItemStatus?>
Get the status of a previously submitted item. Returns null if the local UUID is unknown.
loginAnonymous({required String code, String? projectId}) Future<bool>
Runtime anonymous login — parity with the TS SDK's loginAnonymous(projectId, testerCode). Trades a {projectId, code} pair for a tester JWT, persists the code for auto-login next launch, and kicks off the same post-auth setup (device register + session sync + durability sweep) the build-time config.testerId path runs. Lets a host show an in-app invite-code screen instead of baking the code into the build.
logoutTester() Future<void>
Clear the tester token + persisted code ("log out" / switch tester). The next launch (or a wrapper re-check) prompts for a code again.
maybeRecordAnnotationTap(Offset globalPosition) → void
Translate a raw global tap position into a task interaction: if the tap landed on a widget the host annotated with TesterTaskRelevant, feed it to the interaction tracker (which auto-completes the task when its trigger condition is met). Fed by the wrapper's global tap listener. Best-effort + guarded — never interferes with the tap.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onAppDetached() Future<void>
Called when app is detached from engine — last chance to flush + END the session before the engine tears down (real termination).
onAppInactive() → void
Called when app becomes inactive (e.g., incoming call). We do NOT end the session here — inactive is too noisy on iOS (every notification banner fires this) and would shred otherwise-healthy sessions into 5-second slivers.
onAppPaused() Future<void>
Called when the app goes to the BACKGROUND. We PAUSE the session, we do NOT end it: freeze the foreground (paid-time) clock so background time isn't paid, and flush the at-risk in-memory breadcrumbs. The session spans background↔foreground cycles and is only ended by onAppDetached (real termination), an explicit "End Session", or the launch-time reconcile of a killed session. (Was: flushAndEndSession — which wrongly closed the session on every backgrounding, so coming back started a brand-new one.)
onAppResumed() Future<void>
Called when the app RESUMES to the foreground.
runDurabilitySweep() Future<void>
One durability pass for the payout pipeline. The data only earns money once it reaches the server, so this makes that resilient to hard-kills, network hiccups, and the host never calling createSubmission by hand. Safe to call anytime — every step is idempotent + best-effort:
savedTesterCode() Future<String?>
The invite code previously entered at runtime (persisted), or null. The wrapper reads this on startup to auto-restore a login before deciding whether to prompt for a code.
setTesterMode({required bool enabled}) Future<void>
Set tester mode enabled/disabled
showOnboardingIfNeeded(BuildContext context, {String? productName}) Future<void>
Show the TesterPayKit onboarding the first time after SDK init. Hosts should call this once their own onboarding is done and the app is mounted with a Navigator available (typically in the shell's initState post-frame callback).
showWelcomeSheetIfNeeded(BuildContext context, {required WelcomeBrief brief, required String productName, VoidCallback? onLater}) Future<void>
Show TesterWelcomeSheet once per app version. The host passes in a TesterBrief (release notes + concrete tasks); the sheet renders, the tester taps "Test starten" — we persist testerpaykit_welcome_shown_<version> so the same version doesn't re-prompt on the next launch.
submitBugReport({required String description, Map<String, dynamic>? metadata}) String
Submit a bug report. Returns a local UUID immediately. The report is enqueued to the outbox and uploaded in background. Use getSubmissionStatus to track progress.
submitFeedback({required String content, int? rating}) Future<void>
Submit feedback
syncSubmissions() Future<void>
Sync pending submissions with server
toString() String
A string representation of this object.
inherited
trackCrash(String error, StackTrace stackTrace) Future<void>
Track a crash
trackError(String error, {StackTrace? stackTrace}) Future<void>
Track an error
trackScreenView(String screenName) Future<void>
Track a screen view
trackTap({String? screenName}) Future<void>
Track a tap event

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Properties

instance TesterPayKit
Get the singleton instance
no setter
isInitialized bool
Check if SDK is initialized
no setter

Static Methods

initialize({required TesterPayKitConfig config, TesterPayKitDatabase? databaseOverride}) Future<TesterPayKit>
Initialize the SDK. Returns in <50ms. Token acquisition happens in background via TokenAcquirer. Safe to call multiple times; returns singleton.