linksapp 0.2.0
linksapp: ^0.2.0 copied to clipboard
Flutter Universal Link and App Link handling for LinksApp.
LinksApp Flutter SDK #
Receive verified iOS Universal Links and Android App Links, resolve them through
LinksApp, and route users to the destination in your Flutter app. The package
also exposes LinksAppClient if your app already receives URLs another way.
LinksApp URLs have these forms:
https://<app-key>.linksapp.me
https://<app-key>.linksapp.me/<sublink-code>
Every app gets its own host. The domain in your app configuration must match
the host of the URL people tap, so for app key daily-pooja use
daily-pooja.linksapp.me on both iOS and Android. Your iOS Bundle ID is
not the applinks: domain; register the Bundle ID and Apple Team ID in the
LinksApp console so they appear in the association file served by your app's
host. Likewise, register your Android package name and signing
certificate SHA-256 fingerprint for Android verification. A customer-owned
domain would need its own association files and custom-domain support in the
LinksApp service and SDK; simply replacing linksapp.me in these snippets will
not make that domain work.
Upgrading from 0.1.x: links moved from
https://linksapp.me/a/<app-key>tohttps://<app-key>.linksapp.me. Update the Android intent filter and iOS Associated Domains below, then ship a new build: old path links are no longer served.
Install #
flutter pub add linksapp
Create an App Link in the LinksApp console, then copy its app key. Register your iOS Team ID and Bundle ID, or your Android package name and release SHA-256 signing fingerprint. The app key in the URL must match the key passed to the SDK.
The SDK does not claim the domain for your app. Complete the native setup below before testing an installed-app link.
Native setup #
Android #
Add an App Link filter to the activity that hosts Flutter. Replace
YOUR_APP_KEY with the app key from the LinksApp console:
<!-- android/app/src/main/AndroidManifest.xml, inside MainActivity -->
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="YOUR_APP_KEY.linksapp.me" />
</intent-filter>
The whole host belongs to your app, so no path is needed. LinksApp serves the
host's assetlinks.json using the package name and
release fingerprint you registered. Use the Play App Signing certificate
fingerprint for a Play-distributed app.
iOS #
Add Associated Domains to your app target in Xcode:
applinks:YOUR_APP_KEY.linksapp.me
Also disable Flutter's built-in deep-link handler so it does not compete with
the SDK's app_links receiver:
<!-- ios/Runner/Info.plist, inside dict -->
<key>FlutterDeepLinkingEnabled</key>
<false/>
LinksApp serves the host's Apple App Site Association file using the Team ID and Bundle ID you registered. After changing association settings, reinstall the app before testing; the operating system may cache the earlier file.
Check that https://YOUR_APP_KEY.linksapp.me/.well-known/apple-app-site-association
lists your TEAM_ID.BUNDLE_ID. The app target's Associated Domains capability
must contain applinks:YOUR_APP_KEY.linksapp.me (no https:// prefix and no
URL path).
Huawei phones (AppGallery) #
Huawei phones that run Android apps (EMUI, HarmonyOS 2–4) use the same Android setup above; no extra plugin is needed. Two things differ:
- Signing certificate. If AppGallery re-signs your app (AppGallery Connect → App signing), the copy installed from AppGallery has a different certificate from the Play copy. Add its SHA-256 to the app link's fingerprints in the LinksApp console, or App Link verification fails on those phones.
- Store fallback. Save your AppGallery app ID in the console. The browser
landing page then offers AppGallery (first on Huawei browsers), and the
resolver returns it as
result.huaweiFallback.
HarmonyOS NEXT (5.x) runs only native HarmonyOS apps and is not supported by this package.
Receive and route links #
Create one listener near your app router. Start it once and dispose it when its owner is torn down:
import 'package:linksapp/linksapp.dart';
late final LinksApp linksApp;
Future<void> startLinks() async {
linksApp = LinksApp(
appKey: 'your-app-key',
onResolved: (result) {
// Use your own router to open the destination inside the app.
router.open(result.deepLink, referral: result.ref);
},
onError: (error, stackTrace) {
// Display or log malformed links and resolver failures.
reportLinkError(error, stackTrace);
},
);
await linksApp.start();
}
Future<void> stopLinks() => linksApp.dispose();
start() handles both the initial URL and subsequent URL events, suppressing
the common duplicate initial delivery. result.deepLink is the destination
you should route to; result.ref contains optional referral context. The SDK
does not navigate automatically because each app has its own router.
See the example app for a complete Flutter widget.
Resolve a URL directly #
If your app already receives Universal Links or App Links, you can use the
resolver without LinksApp:
final client = LinksAppClient(expectedAppKey: 'your-app-key');
try {
final result = await client.resolve(incomingUri);
router.open(result.deepLink, referral: result.ref);
} finally {
client.close();
}
resolve() throws FormatException for an invalid URL or response. It throws
LinksAppException for an API error; check statusCode to distinguish an
unknown link (404) from a disabled, expired, or exhausted link (410). The
expected app key prevents your app from resolving another customer's link.
If you used LinksAppFlutter in an earlier release, it remains available as a
deprecated alias. Change the class name to LinksApp when convenient; the
constructor and behavior are the same.
Testing and limitations #
-
Test an installed iOS app by tapping a link from Notes or Messages. Typing it into Safari's address bar is not a Universal Link test.
-
Test an installed Android app with a tapped link, or run:
adb shell am start -a android.intent.action.VIEW \ -c android.intent.category.BROWSABLE \ -d 'https://YOUR_APP_KEY.linksapp.me' adb shell pm get-app-links YOUR_ANDROID_PACKAGEIf Android opens the browser, check the verification state, the registered signing fingerprint, and
https://YOUR_APP_KEY.linksapp.me/.well-known/assetlinks.json. -
An uninstalled app opens the LinksApp browser fallback with store buttons. Universal Links alone cannot automatically restore a link after a first-time iOS App Store install.
-
Do not put a sublink-creation API key in a mobile app. Create sublinks from a trusted server.
For dashboard setup, device testing, and API details, see the LinksApp integration guide.