tracebird_flutter 0.1.0 copy "tracebird_flutter: ^0.1.0" to clipboard
tracebird_flutter: ^0.1.0 copied to clipboard

Tester feedback for Flutter apps: shake to report, annotate the screen, and every report ships with logs, failed requests and device context.

tracebird_flutter #

Tester feedback for Flutter apps, with the technical context already attached.

Your tester shakes the phone, circles what looks wrong, and writes one sentence. You receive a report carrying the console output, the failed requests, the route they walked, the device and the build, all in the same inbox as your web reports.

Future<void> main() async {
  await Tracebird.init(
    const TracebirdOptions(
      projectKey: 'pk_live_…',
      environment: 'staging',
    ),
  );
  runApp(const TracebirdWrapper(child: MyApp()));
}

That is the whole integration. Testers never need an account.

Add every bundle identifier your testers run (com.acme.app, com.acme.beta) to the project's allowlist in Settings. Reports from anywhere else are rejected, which is the mobile equivalent of the web SDK's allowed origins.

What ships with a report #

Automatically: console output (last 100 lines), HTTP calls you reported (method, URL, status, duration, never bodies), uncaught framework errors, the navigation trail, the device model, OS, app version and locale.

On demand: the annotated screenshot, and any metadata you attached.

Never: request or response bodies, headers, anything under a TracebirdMask, and anything the tester blurred: those pixels are destroyed on the device before the image is encoded.

Screenshots on screens with maps, WebViews or video #

This is the part most SDKs get wrong, so it is worth being precise.

A platform view (a WebView, a Google Map, a camera preview) is not drawn by Flutter. Measured on a real WebView on both platforms:

RepaintBoundary.toImage() native window capture
iOS leaves a hole where the view is captures it correctly
Android captures it correctly came back blank

Android composites platform views into the Flutter scene; iOS overlays them as UIViews. So the SDK uses Flutter's own capture everywhere, and pays for a native capture only on iOS, only on screens where it detects one. A platform that has no native path does not report a failure, because on Android the Flutter capture is the right answer rather than a degraded one. You configure none of it.

One caveat worth knowing: a WebView that has not finished painting is genuinely white, and no capture strategy can invent pixels the platform has not drawn. If a tester reports within a second of a screen appearing, the screenshot shows what was on screen at that moment, blank included.

Content protected by FLAG_SECURE still cannot be captured on Android: that is the platform's decision, and the report is sent without a screenshot.

Hiding sensitive widgets #

TracebirdMask(
  child: PatientCard(patient: patient),
)

Masked regions are painted over while the screenshot is still an in-memory buffer, so the real pixels never reach a file, let alone the network.

Triggers #

TracebirdOptions(
  projectKey: 'pk_live_…',
  trigger: TracebirdTrigger.shake, // shake · floatingButton · manual
)

shake keeps the UI clean during a usability test. On iOS it uses the system's own shake gesture, on Android an accelerometer detector that requires two jolts in a row so setting the phone down does not file a bug.

With manual, put feedback behind your own menu item:

await Tracebird.report(type: FeedbackType.bug);

Recording network calls #

The package ships no HTTP-client dependency, so it works with whatever you use. Report calls from one place:

// Dio
dio.interceptors.add(
  InterceptorsWrapper(
    onResponse: (response, handler) {
      Tracebird.recordHttp(
        method: response.requestOptions.method,
        url: response.requestOptions.uri.toString(),
        status: response.statusCode ?? 0,
        milliseconds: stopwatch.elapsedMilliseconds,
      );
      handler.next(response);
    },
  ),
);

Bodies and headers are deliberately not accepted by recordHttp.

MaterialApp(
  navigatorObservers: [TracebirdNavigatorObserver()],
)

The routes the tester walked become the first draft of your repro steps.

Offline testers #

Reports written in a lift are persisted, retried with a widening backoff, and resolved by an idempotency key, so a flaky connection never files the same shake of the phone twice. Tracebird.pendingReports tells you how many are waiting; Tracebird.flush() retries now.

Dependencies #

None at runtime, on purpose. Device details, the cache directory, shake detection, screen capture and JPEG encoding all go through this plugin's own platform channel rather than pulling in four packages your app would then have to keep in version lockstep.

Requirements #

Flutter 3.3+, iOS 13+, Android API 21+.

Full documentation: https://tracebird.dev/docs/flutter

License #

MIT © Tracebird

0
likes
150
points
0
downloads

Documentation

Documentation
API reference

Publisher

verified publishertracebird.dev

Weekly Downloads

Tester feedback for Flutter apps: shake to report, annotate the screen, and every report ships with logs, failed requests and device context.

Homepage
Repository (GitHub)
View/report issues

Topics

#feedback #bug-reporting #testing #qa

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on tracebird_flutter

Packages that implement tracebird_flutter