اولین کرش فلاتر را ثبت و با نمادها بخوانید
پیش از شروع
- یک اپ فلاتر (Dart 3.8.1+، Android API 19+، iOS 12+)
- کلید پروژه ab_live_…
In this guide you add Abrova Trace to a Flutter app, crash it on purpose, and read the result in Abrova Console: the stack trace, the screen the user was on and the button they tapped just before. The last step makes release builds just as readable on mobile and on the web.
Install the SDK from Abrova Center#
The package comes from Abrova Center, so you need no other package registry. Add it with the Abrova registry as its hosted source:
# pubspec.yaml
dependencies:
abrova_trace_flutter_sdk:
hosted: https://center.abrova.ir/api/packages/abrova/pub
version: ^0.2.6The plugin uses the native Android and iOS SDKs for native crash capture, so point those builds at Abrova too.
Android: add the Abrova Maven repository in android/build.gradle (or android/settings.gradle, wherever your project lists repositories):
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://center.abrova.ir/api/packages/abrova/maven" }
}
}iOS: add this inside the app target in ios/Podfile:
pod 'AbrovaTrace', :git => 'https://center.abrova.ir/abrova/abrova-trace-ios-sdk.git', :tag => '0.2.4'
Then install:
flutter pub get
You need Dart 3.8.1 or newer, Android API 19 or newer, and iOS 12 or newer (built with Xcode 15.3+).
Initialise with your project key#
Copy the public key (ab_live_…) from Abrova Console → Project settings → Keys. It is safe inside an app. Never put the server secret (ab_srv_…) in an app.
Start Trace with initWithZone before WidgetsFlutterBinding.ensureInitialized(), and move the rest of your start-up into its callback. That way async errors are caught too.
import 'package:flutter/material.dart';
import 'package:abrova_trace_flutter_sdk/abrova_trace_flutter_sdk.dart';
void main() async {
await AbrovaTrace.initWithZone(
AbrovaTraceConfig(
apiKey: 'ab_live_your_api_key',
release: '1.0.0', // match the version in pubspec.yaml
),
() async {
WidgetsFlutterBinding.ensureInitialized();
// Every tap on a button becomes a breadcrumb.
AbrovaTrace.enableGestureBreadcrumbs();
runApp(const MyApp());
},
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
// Records screen changes as breadcrumbs and fills in the route of each tap.
navigatorObservers: [AbrovaTraceNavigatorObserver()],
home: const HomeScreen(),
);
}
}release is how Trace pairs an error with the source maps and symbols you upload for that version (step 6). Use the same string everywhere, for example the version from pubspec.yaml.
Throw a test error#
Add a button that throws, and one that reports an error you caught yourself:
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Trace test')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Uncaught: Trace reports it on its own.
ElevatedButton(
key: const ValueKey('crash-button'),
onPressed: () => throw StateError('Abrova test crash'),
child: const Text('Crash'),
),
// Caught: you report it, with extra data.
ElevatedButton(
onPressed: () async {
try {
throw const FormatException('Abrova handled test');
} catch (e, stackTrace) {
await AbrovaTrace.captureException(
e,
stackTrace: stackTrace,
extra: {'screen': 'HomeScreen'},
);
}
},
child: const Text('Report a handled error'),
),
],
),
),
);
}
}Run the app (flutter run) and tap both buttons. Always pass stackTrace when you report a caught error; without it the issue has no stack trace.
Read it in Abrova Console#
Open Abrova Console → Trace → Issues. Within a few seconds you see two issues: StateError: Abrova test crash and FormatException: Abrova handled test. Open the first one:
- Stack trace: the frames of your own code, with
.dartfiles and line numbers. The top frame is where the error happened. - Breadcrumbs: what happened before the error, ending with
Tap on ElevatedButton: "Crash"and the route the user was on. - Context: device, OS and app version, and under Extra data anything you attached (
screenon the second issue). - Release
1.0.0and Environmentproduction(the default).
Tap the button again: the event count of the same issue goes up instead of a new issue appearing, because repeats of one cause are grouped. Each event still counts toward your free 50,000 error events a month — grouping only keeps the list readable.
Native crashes come on the next launch#
Dart errors are sent as they happen. A native crash on Android or iOS (for example a crash inside a plugin's native code, or the system killing the app) ends the process before anything can be sent. The bundled native SDK writes the report to disk, and Trace sends it the next time the app starts. So after a native crash, open the app again, then look in Trace → Issues.
On the web, Dart errors, messages and logs work; native crash capture is Android and iOS only.
Make release builds readable#
What you need depends on the platform you ship:
| Build | What to do |
|---|---|
| Android and iOS release (flutter build apk / appbundle / ipa) | Nothing for Dart errors: method names and line numbers stay in the stack trace. Build without --obfuscate; Abrova Trace does not read the symbol files of --split-debug-info, so obfuscated Dart frames stay unreadable. |
| iOS native crashes | Upload the dSYMs of the release in Abrova Console → Trace → Source maps & symbols → iOS dSYMs (a .zip, up to 10 MB). |
| Flutter web | Build with source maps and upload main.dart.js.map with the same release. |
For Flutter web, build with source maps:
flutter build web --source-maps --release
The map is at build/web/main.dart.js.map. Upload it in Abrova Console → Trace → Source maps & symbols (set the release to 1.0.0), or from CI with the Abrova Trace CLI (add the Abrova npm registry and install @abrova-trace/cli first, as that page shows):
npx abrova-trace sourcemaps upload build/web --release "1.0.0"
Only errors captured after the upload are shown with your .dart files. In --release web builds the compiler inlines a lot, so some frames still point at framework files; the tap breadcrumbs from step 2 usually fill the gap. See Stack traces.
Troubleshooting#
Nothing shows up in Trace → Issues
Check that the key starts with ab_live_ and belongs to the project you are looking at, and that Abrova Trace is on for the project. Set debug: true in AbrovaTraceConfig to see the SDK's own log lines in the console while you test. Also check that the time range filter on the Issues page includes the last hour.
The async error is missing, the tap error is there
Use AbrovaTrace.initWithZone, and call WidgetsFlutterBinding.ensureInitialized() inside its callback, not before it. Errors from futures nobody awaits are only caught inside the zone.
A native crash never arrives
Native crashes are sent on the next launch: open the app again after the crash. Check that the Android Maven repository and the iOS pod line from step 1 are in place, and that you ran the app on a device or emulator, not on the web.
The web stack trace is still minified
The release you uploaded the map with must match the release in AbrovaTraceConfig exactly, and the error must happen after the upload. Check the release on the issue page and upload again with that exact string.
'Failed to initialize offline storage: Binding has not yet been initialized' at start
Versions before 0.2.6 can print this with initWithZone. It is harmless; update to 0.2.6, which no longer prints it.
Stack frames show short random names on Android or iOS
The build was made with --obfuscate. Build without it to get readable Dart frames in Trace.
- source map فلاتر وب و dSYM آیاواس فقط روی خطاهایی اعمال میشوند که همان نام ریلیزِ آپلود را دارند.
- بیلدهایی که با --obfuscate ساخته شوند خوانا نمیشوند: ابرووا تریس فایلهای نماد Dart را نمیخواند.
- کرشهای نیتیو در اجرای بعدی اپ میرسند، نه همان لحظه.
بعدی: مرجع SDK فلاتر