In many real-world mobile applications, you may need to open another Flutter app from your Flutter app and then return back to the original app. This is common in scenarios like:
- Payment apps (open UPI / wallet app)
- Authentication apps
- Partner apps integration
- Deep linking between multiple company apps
In this complete guide, you will learn:
✅ How to open another Flutter app
✅ How to pass data between apps
✅ How to return back to the first app
✅ How to handle Android & iOS
✅ Best practices and common issues
1. Concepts You Must Know
To redirect between two Flutter apps, you mainly use:
- URL Schemes (iOS & Android)
- Android Intents
- Deep Linking
- Universal Links (iOS)
- App Links (Android)
Flutter provides plugins to make this easy:
url_launcheruni_linksapp_links
2. Use Case Example
We will assume:
- App A (Sender App) → Opens App B
- App B (Receiver App) → Does some work → Returns back to App A
3. Step 1: Setup Deep Linking in App B (Receiver App)
App B must expose a custom URL scheme so App A can open it.
Android Setup (App B)
Edit android/app/src/main/AndroidManifest.xml
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<!-- Custom Scheme -->
<data
android:scheme="appb"
android:host="open"/>
</intent-filter>
</activity>
This creates a link like:
appb://open
iOS Setup (App B)
Edit ios/Runner/Info.plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>appb</string>
</array>
</dict>
</array>
4. Step 2: Open App B from App A
Install plugin in App A:
dependencies:
url_launcher: ^6.2.4
Flutter Code (App A)
import 'package:url_launcher/url_launcher.dart';
Future<void> openAppB() async {
final Uri uri = Uri.parse('appb://open?from=appA&userId=123');
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
} else {
throw 'Could not open App B';
}
}
This will:
✅ Open App B
✅ Pass parameters (from, userId)
5. Step 3: Receive Data in App B
Use uni_links to listen for incoming deep links.
Install in App B
dependencies:
uni_links: ^0.5.1
Handle Incoming Link in App B
import 'package:uni_links/uni_links.dart';
void initDeepLinks() {
uriLinkStream.listen((Uri? uri) {
if (uri != null) {
final from = uri.queryParameters['from'];
final userId = uri.queryParameters['userId'];
print('Opened from: $from');
print('UserId: $userId');
}
});
}
Call initDeepLinks() in initState().
6. Step 4: Return Back to App A from App B
Now App A must also support deep links.
Setup Deep Link in App A
Use a scheme for App A:
appa://open
AndroidManifest.xml (App A)
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="appa"
android:host="open"/>
</intent-filter>
Info.plist (App A)
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>appa</string>
</array>
</dict>
</array>
Flutter Code (App B → Back to App A)
Future<void> returnToAppA() async {
final Uri uri = Uri.parse('appa://open?status=success&txId=999');
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
}
7. Handle Return Data in App A
void initDeepLinks() {
uriLinkStream.listen((Uri? uri) {
if (uri != null) {
final status = uri.queryParameters['status'];
final txId = uri.queryParameters['txId'];
print('Status: $status');
print('Transaction ID: $txId');
}
});
}
8. Flow Diagram (High Level)
App A ---> appb://open ---> App B
App B ---> appa://open ---> App A
9. Best Practices
✅ Use unique URL schemes
✅ Always validate incoming parameters
✅ Handle app not installed case (redirect to Play Store / App Store)
✅ Use App Links / Universal Links for production
✅ Secure sensitive data (don’t pass tokens in URL)
10. Common Issues & Fixes
| Problem | Solution |
|---|---|
| App not opening | Check scheme & host |
| iOS not working | Add URL Types in Info.plist |
| Android opens browser | Fix intent-filter |
| App opens but no data | Check uni_links listener |
| Multiple instances | Use launchMode=”singleTask” |
11. Advanced (Recommended for Production)
For large apps, use:
- Android App Links
- iOS Universal Links
- Firebase Dynamic Links
These are more secure and reliable than custom schemes.
Conclusion
Redirecting between two Flutter apps is very useful for:
- Payments
- Authentication
- Partner integrations
- Modular app ecosystems
By using deep links + url_launcher + uni_links, you can easily:
✅ Open another Flutter app
✅ Pass data
✅ Return back with result
