Flutter SDK 1.0.0
LimeLink's public Flutter plugin bridges the LimeLink Android and iOS SDKs for deferred deep links and platform link handling.
Requirements
- Dart 3.12 or later
- Flutter 3.44 or later
- Android API 24 or later
- iOS 12 or later
Flutter 3.44 and later uses Swift Package Manager by default on iOS. Existing CocoaPods applications remain supported.
Install
flutter pub add limelink_flutter
Import the public API:
import 'package:limelink_flutter/limelink_flutter.dart';
Listen, then initialize
Use the canonical lowercase Project UUID from LimeLink Project settings, never an Organization API credential. In your app's long-lived bootstrap owner, register the event subscription before initialization. The helpers below (routeIfAllowed, continueNormalStartup, reportFailure) are app-owned placeholders, not SDK APIs.
// After WidgetsFlutterBinding.ensureInitialized() in a custom main bootstrap.
final subscription = LimeLink.events.listen(
(event) {
switch (event) {
case LimeLinkReceived(:final result):
routeIfAllowed(result.deeplinkUrl ?? result.originalUrl);
case LimeLinkDeferredNotFound():
continueNormalStartup();
case LimeLinkFailed(:final error):
reportFailure(error);
}
},
onError: (Object error, StackTrace stack) {
// Includes malformed event payloads (FormatException).
reportFailure(error);
},
);
try {
await LimeLink.initialize(
const LimeLinkConfig(
projectId: '550e8400-e29b-41d4-a716-446655440000',
loggingEnabled: false,
),
);
} catch (error) {
await subscription.cancel();
reportFailure(error);
}
Retain the subscription and cancel it when its owner is disposed. routeIfAllowed must reject null or non-allowlisted destinations and wait until your router is ready. Match parsed schemes and hosts exactly; only use originalUrl for an explicitly allowed browser fallback.
Deferred lookup is automatic for eligible installations and has no initialization toggle. Native SDKs buffer successful results, not errors or deferred not-found outcomes; register early rather than relying on every startup outcome being replayed.
Manual operations
final initialized = await LimeLink.isInitialized();
// Only for an explicit app-owned handoff, not native lifecycle URL replay.
await LimeLink.handleIncomingLink(Uri.parse('myapp://path'));
Manual deferred lookup returns Dart sealed classes, not a JavaScript-style status field. This example keeps the event stream above as the sole navigation owner:
try {
final outcome = await LimeLink.handleDeferredDeepLink();
switch (outcome) {
case DeferredDeepLinkMatched():
// Event stream owns routing; do not navigate again here.
break;
case DeferredDeepLinkNotFound():
// Normal terminal result; no routing here.
break;
case DeferredDeepLinkFailed(:final error):
// Update request UI if needed; the live stream also receives this failure.
reportFailure(error);
}
} catch (error) {
// PlatformException or malformed outcome (FormatException).
reportFailure(error);
}
If you choose the Future as the navigation owner instead, prevent the stream from also routing the manual deferred outcome.
Result Contract
Each received result contains nullable deeplinkUrl, source, nullable originalUrl, and isDeferred. A resolved app route uses deeplinkUrl. An unresolved Universal/App Link remains a successful result with deeplinkUrl == null, exact inbound HTTPS originalUrl, source == universalLink, and isDeferred == false. Use originalUrl only for an allowlisted browser fallback.
Manual outcomes are DeferredDeepLinkMatched, DeferredDeepLinkNotFound, or DeferredDeepLinkFailed. The native wire statuses are matched, notFound, and failed; the Dart API wraps them in these classes.
Platform Setup
Android
Configure Android App Links and custom schemes in the host manifest. Use the Android guide's intent filters, keeping your existing Flutter Application and Activity classes rather than replacing them with the native guide's MyApp. Verify the package name, SHA-256 signing fingerprint and each hostname's association file against the Project's active Android Application.
iOS
Configure Associated Domains and custom URL schemes in the host application using the iOS guide's capability setup. Verify the Bundle ID, app scheme, and domain entitlement match the active iOS Application and Link configuration. Do not copy the native guide's manual forwarding callbacks into a Flutter host that already delegates them to the plugin.
LimeLink forwards cold and warm native lifecycle links automatically; do not feed Flutter router or initial-link events back into LimeLink when native lifecycle forwarding is enabled.
The plugin uses Android SDK 1.0.1 and iOS SDK 1.0.1. Native and bridge failures surface through PlatformException, LimeLinkFailed, or DeferredDeepLinkFailed, depending on the operation.
Verify and Troubleshoot
- Confirm
await LimeLink.isInitialized()becomes true after initialization. - Test a direct custom-scheme URI.
- Test resolved and unresolved Universal/App Links on real platform association paths.
- Test an eligible install-before-open deferred journey.
- Cancel the broadcast subscription when its owner is disposed.
If no event arrives, confirm the listener was registered early, the Project UUID is canonical lowercase, the native package resolved at version 1.0.1, and the host owns lifecycle forwarding. PlatformException indicates native/bridge operation failure; malformed event payloads can surface as FormatException.