Flutter SDK
Handle links in your app
Route links with go_router, Navigator, GetX or your own app_links code.
Most apps already route links: go_router, Navigator, GetX, or their own app_links listener. The
SDK works next to all of them. The rule: each URL is handled once, by one place.
Pattern 1: the SDK routes Beck Links links, your code routes the rest#
The simplest change. Keep onLink as the entry for Beck Links links and make your own listener skip
them:
final appLinks = AppLinks();
appLinks.uriLinkStream.listen((uri) {
if (BeckLink.instance.isBeckLinkUri(uri)) return; // the SDK delivers it on onLink
router.go(uri.path); // your own links
});isBeckLinkUri is synchronous and side-effect free. It compares hosts exactly, so
https://evil.com/?x=acme.becklinks.com and https://acme.becklinks.com.evil.com/ do not count.
Pattern 2: you receive every URI, the SDK receives none from the system#
Turn the SDK's own link intake off and forward everything, so your listener stays the single entry:
await BeckLink.instance.configure(
apiKey: 'pk_live_YOUR_KEY',
handlePlatformLinks: false, // the SDK reads no launch or incoming link itself
);
Future<void> onUri(Uri uri) async {
if (await BeckLink.instance.handleUri(uri)) return; // a Beck Links URI: the SDK took it
router.go(uri.path); // your own links
}
final initial = await appLinks.getInitialLink();
if (initial != null) await onUri(initial);
appLinks.uriLinkStream.listen(onUri);handleUri returns true when it took the URI and delivers one LinkEvent on onLink. It never
throws, and the same URL arriving twice within ten seconds is delivered once. Deferred linking, the
first open, attribution and events work as before.
go_router#
Call handleUri in the listener that feeds router.go, not inside redirect (which must stay a
pure function). Map the link path to a route yourself and ignore anything you do not know:
void routeLink(LinkEvent link) {
final segments = Uri.tryParse(link.path)?.pathSegments;
final route = switch (segments) {
['product', final id] => '/product/${Uri.encodeComponent(id)}',
_ => null,
};
if (route != null) router.go(route);
}Navigator and GetX#
Use the same routeLink function and call Navigator.of(context).pushNamed(route) or
Get.toNamed(route) instead of router.go. Keep the list of accepted routes explicit.
Flutter's own deep linking#
FlutterDeepLinkingEnabled (iOS) and flutter_deeplinking_enabled (Android) only decide whether
Flutter's router also receives the URL. Turn both off unless your router can safely receive a Beck
Link URL as well; that is what the platform setup pages recommend for new apps.
Verify it works#
Use a debug build and debugOpenLink to handle a URL as if the system had opened the app with it:
await BeckLink.instance.debugOpenLink(Uri.parse('https://acme-test.becklinks.com/abc123'));The console shows one Delivering LinkEvent line and the screen opens once. Do the same with a link
from Notes (iOS) or adb (Android), because the real path through the system differs from the debug call.