deeplink_x 1.3.6
deeplink_x: ^1.3.6 copied to clipboard
Type-safe Flutter deeplinks for WhatsApp, Telegram, Instagram, YouTube, Google Maps, Waze and app stores, with automatic store and web 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 is a Flutter plugin for launching typed external deeplinks β it launches deeplinks into other apps from your Flutter app. Open a chat in WhatsApp, a profile in Telegram or Instagram, a video on YouTube, or a location in Google Maps, Amap, Baidu Maps, Apple Maps, Waze, Sygic, Moovit, or Neshan with turn-by-turn directions β 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, Baidu Maps, Apple Maps, Waze, Sygic, Moovit, 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: 20 apps (Facebook, Instagram, LinkedIn, WhatsApp, Telegram, Twitter, Threads, YouTube, TikTok, Pinterest, Zoom, Slack, Google Maps, Amap, Baidu Maps, Waze, Apple Maps, Sygic, Moovit, 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? Under the hood, DeeplinkX opens apps with iOS custom URL schemes, Android Intents, and Android/iOS App Links β the same launch mechanics you'd otherwise hand-roll with url_launcher β rather than 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 another app from Flutter #
Launch a supported app without targeting a screen β no raw URLs, no Platform.isAndroid checks:
await deeplinkX.launchApp(
Instagram.open(fallbackToStore: true),
);
The same call shape works to open WhatsApp, Telegram, or any other supported app from your Flutter app.
Check whether an app is installed #
Check whether WhatsApp, Telegram, Google Maps, LinkedIn, or another supported app is installed before you launch it:
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, Baidu Maps, Apple Maps, Waze, Sygic, Moovit, 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),
BaiduMaps.view(coordinate: origin),
AppleMaps.view(coordinate: origin),
Waze.view(coordinate: origin),
Sygic.view(coordinate: origin),
Moovit.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'),
BaiduMaps.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'),
BaiduMaps.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),
BaiduMaps.directionsWithCoords(destination: destination),
AppleMaps.directionsWithCoords(destination: destination),
Waze.directionsWithCoords(destination: destination),
Sygic.directionsWithCoords(destination: destination),
Moovit.directionsWithCoords(destination: destination),
Neshan.directionsWithCoords(destination: destination),
],
);
| Method | Supported apps |
|---|---|
launchMapViewAction |
Google Maps, Amap, Baidu Maps, Apple Maps, Waze, Sygic, Moovit, Neshan |
launchMapSearchAction |
Google Maps, Amap, Baidu Maps, Apple Maps, Waze |
launchMapDirectionsAction |
Google Maps, Amap, Baidu Maps, Apple Maps, Waze |
launchMapDirectionsWithCoordsAction |
Google Maps, Amap, Baidu Maps, Apple Maps, Waze, Sygic, Moovit, 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 | |
| Baidu Maps | View map, search, nearby search, line, directions, coordinates, navigation | |
| Apple Maps | View map, search location, directions, directions with coordinates | |
| Waze | View map, search, directions, directions with coordinates | |
| Sygic | View map, directions with coordinates | |
| Moovit | 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 | β 20 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.
Compared to single-purpose alternatives: map_launcher opens a chosen maps app but doesn't cover social apps or store fallback; external_app_launcher opens an app or its store listing but has no typed map or social-app actions. DeeplinkX covers apps, maps, and stores from one typed API.
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 Β· Baidu Maps Β· Waze Β· Apple Maps Β· Sygic Β· Moovit Β· 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.
