deeplink_x 1.3.4
deeplink_x: ^1.3.4 copied to clipboard
Type-safe Flutter deeplinks to open external apps, maps and stores — launch Google Maps, Waze or social apps with directions, navigation and smart store fallback.
DeeplinkX #
Type-safe deeplinks into external apps — with automatic store & web fallback, on every Flutter platform.
🌐 Live Demo · 📖 API Reference · ➕ Request an App
DeeplinkX launches deeplinks into other apps — open a location in Google Maps, Amap, Apple Maps, Waze, Sygic, or Neshan and get turn-by-turn directions, open an Instagram profile, start a Telegram chat, or play a YouTube video — with one strongly-typed call. When the target app isn't installed, it automatically falls back to the right app store, then to a web URL. No URL strings to maintain, no Platform.isAndroid branches to write.
What does the X stand for? External. DeeplinkX is built for launching links out to other apps — not for handling incoming links into your own. For inbound links, use
app_linksorgo_router.
Why DeeplinkX #
- Typed API — every supported app and action is a Dart call; the package owns the URL schemes, not you.
- Smart fallback — installed → open the app; not installed → open its store; no store → open the web URL.
- Installation check — ask
isAppInstalled()before you launch. - Cross-platform store redirect — point users at a store listing (your app, a promoted app, an ad CTA) and DeeplinkX picks the right store for the device.
- Maps & navigation — open a location, search a place, or launch turn-by-turn directions in Google Maps, Amap, Apple Maps, Waze, Sygic, or Neshan; list your preferred apps and DeeplinkX opens the first installed one, falling back to the web map otherwise.
- One package, every platform — iOS, Android, macOS, Windows, Linux, and Web.
Out of the box: 18 apps (Facebook, Instagram, LinkedIn, WhatsApp, Telegram, Twitter, Threads, YouTube, TikTok, Pinterest, Zoom, Slack, Google Maps, Amap, Waze, Apple Maps, Sygic, Neshan) and 7 stores (iOS App Store, Mac App Store, Microsoft Store, Google Play, Huawei AppGallery, Cafe Bazaar, Myket).
Install #
flutter pub add deeplink_x
import 'package:deeplink_x/deeplink_x.dart';
Requires Dart >=3.1.0 and Flutter >=3.13.0.
Quick Start #
Open a Telegram profile, and fall back to the App Store / Play Store if Telegram isn't installed:
final deeplinkX = DeeplinkX();
await deeplinkX.launchAction(
Telegram.openProfile(username: 'username', fallbackToStore: true),
);
On iOS, declare the schemes you query in ios/Runner/Info.plist (each app's doc page lists its exact values):
<key>LSApplicationQueriesSchemes</key>
<array>
<string>tg</string>
<string>itms-apps</string>
</array>
That's the whole flow — DeeplinkX resolves the platform, checks installation, and handles the fallback.
Demo #
Try the live web demo, or run the example on a real device for the full experience — installation checks need a native platform.
Instagram Profile
|
Telegram Profile
|
Facebook App
|
YouTube Video
|
Facebook Web Fallback
|
iOS App Store Page
|
How it works #
Every launch follows the same three-tier strategy, in order:
- Native deeplink — opens the app directly via a custom URL scheme, App Link, or Android Intent when it's installed.
- Store fallback — if
fallbackToStore: trueand the app is absent, redirects to the correct store for the current platform. - Web fallback — otherwise opens the action's web URL, when one exists.
Pass disableFallback: true to any launch method to attempt only the native path (skip ② and ③). Every launch method returns Future<bool> — see Return values.
Note: with
fallbackToStore: true, if a vendor changes or removes a custom scheme, DeeplinkX redirects to the store rather than the web URL. SetfallbackToStore: falsewhen you always want the web page as the fallback.
Why custom schemes instead of universal links? DeeplinkX prefers custom URL schemes, App Links, and Android Intents over plain HTTPS universal links because they:
- Launch directly, no browser flash — no redirect flicker before the app opens.
- Skip the "Open with…" dialog on Android — Intents target the exact package.
- Allow a real installation check — universal links return
trueeven when the app is missing (the browser would handle them), which breaks fallback logic; a scheme/package check does not. - Stay resilient — every scheme is paired with a web fallback, so a deprecated scheme still lands the user somewhere useful.
Use cases #
Open a screen inside an app #
Deep-link to a specific screen; fall back to the store if the app is missing:
final deeplinkX = DeeplinkX();
await deeplinkX.launchAction(
Telegram.openProfile(username: 'flutter', fallbackToStore: true),
);
await deeplinkX.launchAction(
YouTube.openVideo(videoId: 'dQw4w9WgXcQ', fallbackToStore: true),
);
await deeplinkX.launchAction(
WhatsApp.chat(phoneNumber: '1234567890', fallbackToStore: true),
);
Open an app #
Launch a supported app without targeting a screen:
await deeplinkX.launchApp(
Instagram.open(fallbackToStore: true),
);
Check whether an app is installed #
final isInstalled = await deeplinkX.isAppInstalled(LinkedIn());
if (isInstalled) {
await deeplinkX.launchAction(
LinkedIn.openProfile(profileId: 'johndoe'),
);
}
Send users to a store listing #
Send users to the right store page for any app you configure — your own app's install/update flow, a promoted app, or an ad CTA. Declare each platform's listing once; DeeplinkX opens the one matching the device. No Platform.isAndroid checks.
await deeplinkX.redirectToStore(
storeActions: [
IOSAppStore.openAppPage(appId: 'TARGET_APP_ID', appName: 'target-app'),
MacAppStore.openAppPage(appId: 'TARGET_APP_ID', appName: 'target-app'),
PlayStore.openAppPage(packageName: 'com.target.app'),
MicrosoftStore.openAppPage(productId: 'YOUR_PRODUCT_ID'),
HuaweiAppGalleryStore.openAppPage(
packageName: 'com.target.app',
appId: 'YOUR_HUAWEI_APP_ID',
),
CafeBazaarStore.openAppPage(packageName: 'com.target.app'),
MyketStore.openAppPage(packageName: 'com.target.app'),
],
);
For promoted apps or ad CTAs, pass tracking parameters on stores that support them:
await deeplinkX.redirectToStore(
storeActions: [
IOSAppStore.openAppPage(
appId: 'TARGET_APP_ID',
appName: 'target-app',
campaignToken: 'spring_sale',
providerToken: 'partner_network',
affiliateToken: 'affiliate_123',
uniqueOrigin: 'home_banner',
),
PlayStore.openAppPage(
packageName: 'com.target.app',
referrer: 'utm_source=deeplink_x&utm_medium=ad&utm_campaign=spring_sale',
),
HuaweiAppGalleryStore.openAppPage(
packageName: 'com.target.app',
appId: 'YOUR_HUAWEI_APP_ID',
referrer: 'utm_source=deeplink_x&utm_medium=ad&utm_campaign=spring_sale',
),
],
);
Open a map, search a place, or get directions #
Launch Google Maps, Amap, Apple Maps, Waze, Sygic, or Neshan for supported map actions — view a location, search a place, get directions (by address), or get directions with coordinates — on every platform, including web and desktop. For each, list the maps apps you prefer in priority order; DeeplinkX opens the first installed one and falls back to the web map if none are present. Need another provider? Request it — map support is actively expanding.
const origin = Coordinate(latitude: 35.6892, longitude: 51.3890);
const destination = Coordinate(latitude: 35.7000, longitude: 51.4000);
// View a location
await deeplinkX.launchMapViewAction(
actions: [
GoogleMaps.view(coordinate: origin),
Amap.view(coordinate: origin),
AppleMaps.view(coordinate: origin),
Waze.view(coordinate: origin),
Sygic.view(coordinate: origin),
Neshan.view(coordinate: origin),
],
);
// Search for a place
await deeplinkX.launchMapSearchAction(
actions: [
GoogleMaps.search(query: 'Central Park'),
Amap.search(query: 'Central Park'),
AppleMaps.search(query: 'Central Park'),
Waze.search(query: 'Central Park'),
],
);
// Directions by address
await deeplinkX.launchMapDirectionsAction(
actions: [
GoogleMaps.directions(destination: 'Eiffel Tower, Paris'),
Amap.directions(destination: 'Eiffel Tower, Paris'),
AppleMaps.directions(destination: 'Eiffel Tower, Paris'),
Waze.directions(destination: 'Eiffel Tower, Paris'),
],
);
// Directions by coordinates
await deeplinkX.launchMapDirectionsWithCoordsAction(
actions: [
GoogleMaps.directionsWithCoords(destination: destination),
Amap.directionsWithCoords(destination: destination),
AppleMaps.directionsWithCoords(destination: destination),
Waze.directionsWithCoords(destination: destination),
Sygic.directionsWithCoords(destination: destination),
Neshan.directionsWithCoords(destination: destination),
],
);
| Method | Supported apps |
|---|---|
launchMapViewAction |
Google Maps, Amap, Apple Maps, Waze, Sygic, Neshan |
launchMapSearchAction |
Google Maps, Amap, Apple Maps, Waze |
launchMapDirectionsAction |
Google Maps, Amap, Apple Maps, Waze |
launchMapDirectionsWithCoordsAction |
Google Maps, Amap, Apple Maps, Waze, Sygic, Neshan |
Supported apps and actions #
| Category | App | Actions |
|---|---|---|
| Stores | iOS App Store | Open app page, rate app |
| Mac App Store | Open app page, rate app | |
| Microsoft Store | Open app page, rate app | |
| Google Play Store | Open app page | |
| Huawei AppGallery | Open app page | |
| Cafe Bazaar | Open app page | |
| Myket | Open app page, rate app | |
| Social | Telegram | Open profile by username, open profile by phone number, send message |
| Open profile by username | ||
| Chat with phone number, share text content | ||
| Open profile by ID, open profile by username, open page, open group, open event | ||
| YouTube | Open video, open channel, open playlist, search | |
| Open profile by username, open tweet by ID, search | ||
| Threads | Open profile by username, open post, open comments, create post | |
| Open profile by username, open pin, open board by ID, search | ||
| TikTok | Open profile by username, open video, open tag | |
| Zoom | Join meeting by ID | |
| Slack | Open team, open channel, open user | |
| Open profile page, open company page | ||
| Navigation | Google Maps | View map, search location, directions, directions with coordinates |
| Amap | Open current location, view map, search, directions, directions with coordinates | |
| Apple Maps | View map, search location, directions, directions with coordinates | |
| Waze | View map, search, directions, directions with coordinates | |
| Sygic | View map, directions with coordinates | |
| Neshan | View map, directions with coordinates |
Platform configuration #
Some platforms require you to declare URL schemes or package visibility before the OS will allow installation checks.
| Platform | File | Required? |
|---|---|---|
| iOS | ios/Runner/Info.plist |
Yes |
| Android | android/app/src/main/AndroidManifest.xml |
Yes |
| macOS | macos/Runner/Info.plist |
Yes |
| Windows / Linux / Web | — | No config |
Each app's doc page lists the exact schemes and package names. For example, Telegram + App Store on iOS:
<!-- ios/Runner/Info.plist -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>tg</string>
<string>itms-apps</string>
</array>
…and Instagram on Android:
<!-- android/app/src/main/AndroidManifest.xml -->
<queries>
<package android:name="com.instagram.android" />
</queries>
DeeplinkX vs url_launcher #
url_launcher is a general-purpose URL opener. DeeplinkX is purpose-built for external app deeplinks:
| DeeplinkX | url_launcher |
|
|---|---|---|
| Typed API for popular apps | ✅ 18 apps, no URL maintenance | ❌ Raw URLs only |
| Automatic store / web fallback | ✅ Built in | ❌ Manual implementation required |
| Installation check | ✅ isAppInstalled() |
⚠️ canLaunchUrl() — unreliable for HTTPS schemes |
| Android Intent support | ✅ Advanced intent options | ⚠️ Basic intent launching only |
| macOS custom scheme check | ✅ Supported | ❌ Not supported |
| Map actions across apps | ✅ View / search / directions, first installed | ❌ Not available |
| Store listing redirect | ✅ One call, all platforms | ❌ Not available |
Redirecting to a store page with url_launcher means detecting the platform, looking up each store's URL format, and handling Huawei edge cases — everywhere you need it. DeeplinkX does it in one redirectToStore call.
Return values #
Every launch method returns a Future<bool>:
launchAction,launchApp—trueif the app launched or a fallback (store/web) succeeded;falseotherwise.isAppInstalled—trueif the app is installed.redirectToStore—trueif any matching store opened;falseif no store matched the platform or none launched.launchMap*Action—trueif any listed provider (or its fallback) launched.
DeeplinkX swallows platform errors internally and reports them through this boolean, so a launch never throws — branch on the result.
Missing an app? #
If DeeplinkX doesn't support the app, store, or navigation provider you need, open a new app request with the app name, target platforms, known schemes/App Link patterns, store links, and the actions you want.
Documentation #
Per-app pages (schemes, required config, fallback behavior) live in doc/apps. Full API reference: pub.dev.
Stores: iOS App Store · Mac App Store · Microsoft Store · Google Play · Huawei AppGallery · Cafe Bazaar · Myket
Apps: Facebook · Instagram · Telegram · WhatsApp · LinkedIn · YouTube · Twitter · Threads · Pinterest · TikTok · Zoom · Slack · Google Maps · Amap · Waze · Apple Maps · Sygic · Neshan
Contributing #
Contributions are welcome — fork, branch, and open a PR. Please check existing issues first. Found a rough edge or a gap? The feedback form directly shapes the API and docs.
License #
MIT — see LICENSE.