What is url_launcher?
The url_launcher is Flutter's official plugin for launching URLs in external applications. It provides a unified API that works across multiple platforms, abstracting the platform-specific implementation details away from developers. With over 2.86 million downloads, it is one of the most widely used packages in the Flutter ecosystem.
When building cross-platform mobile applications, integrating with external services and native device capabilities is essential for creating seamless user experiences. The url_launcher package enables your Flutter app to interact with the device's native applications, keeping users within their preferred ecosystem while maintaining context within your application.
Key Capabilities
- Opening URLs in external web browsers
- Making phone calls directly from the app
- Sending SMS messages with pre-filled content
- Composing emails with recipients and subject lines
- Launching native map applications
- Opening files on desktop platforms
Supported Platforms
- Android: SDK 21+ (Android 5.0 Lollipop and higher)
- iOS: 12.0+
- Linux, macOS, Windows: Desktop platforms
- Web: Any modern browser
Installation and Configuration
Adding the Dependency
To add url_launcher to your Flutter project, run the following command:
flutter pub add url_launcher
Or manually add to your pubspec.yaml:
dependencies:
url_launcher: ^6.3.2
Then import the package:
import 'package:url_launcher/url_launcher.dart';
Platform-Specific Configuration
iOS Configuration
For iOS, add URL schemes to the LSApplicationQueriesSchemes array in your Info.plist file:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sms</string>
<string>tel</string>
<string>mailto</string>
<string>https</string>
</array>
This configuration is required because iOS restricts which URL schemes apps can query for availability. Without proper declaration, canLaunchUrl() will return false for schemes not listed.
Android Configuration
For Android 11 (API 30) and higher, declare URL schemes in AndroidManifest.xml:
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
</queries>
This requirement exists starting with Android 11 due to package visibility changes in the Android platform.
| Scheme | Example | Purpose |
|---|---|---|
| https: | https://flutter.dev | Open web URLs in browser |
| mailto: | mailto:[email protected]?subject=Hello | Open email client |
| tel: | tel:+1-555-010-999 | Make phone call |
| sms: | sms:5550101234 | Send SMS message |
| file: | file:/path/to/file | Open local files (desktop) |
Core API Methods
canLaunchUrl
The canLaunchUrl() method checks whether the device can handle a given URL:
final Uri url = Uri.parse('https://flutter.dev');
final bool canLaunch = await canLaunchUrl(url);
This method is useful for:
- Checking feature availability before attempting to launch
- Conditionally enabling UI elements based on capability
- Providing fallback behavior when launching isn't possible
launchUrl
The launchUrl() method attempts to launch the given URL:
final Uri url = Uri.parse('https://flutter.dev');
if (await launchUrl(url)) {
// URL launched successfully
} else {
// Failed to launch URL
}
The method accepts an optional LaunchMode parameter to control how the URL is opened.
Launch Modes
Understanding LaunchMode
The url_launcher package provides several LaunchMode options:
LaunchMode.externalApplication
Opens the URL in the default external application:
launchUrl(url, mode: LaunchMode.externalApplication);
Use when: You want to keep users in the native apps they prefer, opening external documents or files. This is ideal for mobile app development projects where users need access to full browser features or native applications.
LaunchMode.inAppWebView
Opens the URL within the application using an embedded web view:
launchUrl(url, mode: LaunchMode.inAppWebView);
Use when: You want to keep users engaged within your app while browsing lightweight content. This mode requires the Custom Tabs service to be available on Android.
LaunchMode.inAppBrowserView
Uses the in-app browser view pattern for a more integrated experience:
launchUrl(url, mode: LaunchMode.inAppBrowserView);
LaunchMode.platformDefault
Uses the platform's default behavior. This is the default mode when no mode is specified.
Practical Code Examples
Opening a Web Page
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class WebLauncherExample extends StatelessWidget {
final Uri _url = Uri.parse('https://flutter.dev');
Future<void> _launchUrl() async {
if (!await launchUrl(_url)) {
throw Exception('Could not launch $_url');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: _launchUrl,
child: const Text('Open Flutter Website'),
),
),
);
}
}
This pattern is commonly used in Flutter applications to link to documentation, privacy policies, or external resources. For building complete web-integrated mobile solutions, proper URL launching is essential for seamless user experiences.
Making a Phone Call
class PhoneCallerExample extends StatefulWidget {
const PhoneCallerExample({super.key});
@override
State<PhoneCallerExample> createState() => _PhoneCallerExampleState();
}
class _PhoneCallerExampleState extends State<PhoneCallerExample> {
bool _hasCallSupport = false;
String _phoneNumber = '';
@override
void initState() {
super.initState();
canLaunchUrl(Uri(scheme: 'tel', path: '123')).then((bool result) {
setState(() {
_hasCallSupport = result;
});
});
}
Future<void> _makePhoneCall(String phoneNumber) async {
final Uri launchUri = Uri(scheme: 'tel', path: phoneNumber);
await launchUrl(launchUri);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
onChanged: (String value) => _phoneNumber = value,
decoration: const InputDecoration(labelText: 'Phone number'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _hasCallSupport ? () => _makePhoneCall(_phoneNumber) : null,
child: _hasCallSupport
? const Text('Make Phone Call')
: const Text('Calling not supported'),
),
],
),
),
);
}
}
This implementation pattern is essential for business applications that need to provide direct customer contact options. Modern AI-powered mobile applications often integrate voice and communication features for enhanced customer engagement.
Sending an Email
String? encodeQueryParameters(Map<String, String> params) {
return params.entries
.map((e) => '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
.join('&');
}
Future<void> _sendEmail() async {
final Uri emailUri = Uri(
scheme: 'mailto',
path: '[email protected]',
query: encodeQueryParameters(<String, String>{
'subject': 'Support Request',
'body': 'Please describe your issue...',
}),
);
if (await canLaunchUrl(emailUri)) {
await launchUrl(emailUri);
}
}
Sending an SMS
Future<void> _sendSms(String phoneNumber, String message) async {
final Uri smsUri = Uri(
scheme: 'sms',
path: phoneNumber,
queryParameters: <String, String>{'body': message},
);
if (await canLaunchUrl(smsUri)) {
await launchUrl(smsUri);
}
}
These patterns are widely used in customer service features within mobile applications for businesses that need to provide multiple communication channels. Pairing these capabilities with intelligent automation workflows can create seamless customer support experiences.
Best Practices
Error Handling
Always handle potential errors when launching URLs:
Future<void> _safeLaunch(Uri url) async {
try {
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
debugPrint('Cannot launch URL: $url');
}
} catch (e) {
debugPrint('Error launching URL: $e');
}
}
User Experience Considerations
- Check capabilities first: Use
canLaunchUrlto determine if a feature is available before enabling UI elements - Provide fallbacks: When a URL scheme isn't available, offer alternative ways to accomplish the task
- Choose appropriate launch modes: Consider whether in-app or external launching better serves the user
- Handle errors gracefully: Provide clear feedback when URLs cannot be launched
Security Considerations
- Validate URLs: Ensure URLs are properly formatted and from trusted sources
- Prefer HTTPS: Use HTTPS URLs for web content to ensure secure connections
- Sanitize user input: Validate any URLs constructed from user input
- Be cautious with deep links: Ensure deep link actions are the user's intended action
Following these best practices ensures your cross-platform applications are both secure and user-friendly. For teams building enterprise-grade mobile solutions, proper URL handling is a critical component of app security.
Contact Pages
Enable users to contact you via phone, email, SMS, or social media with a single tap.
E-commerce
Open payment providers, shipping tracking, review platforms, and social sharing.
Content Sharing
Share content via social media, messaging apps, or email with pre-filled messages.
Navigation
Launch map applications with coordinates or addresses for directions.
Troubleshooting Common Issues
URL Not Launching
- Check platform configuration: Verify iOS Info.plist and AndroidManifest.xml include required schemes
- Use canLaunchUrl first: Confirm the URL scheme is recognized
- Check for installed apps: Some schemes require specific apps to be installed
- Verify URL format: Ensure URLs are properly formatted with Uri.parse()
- Test on physical devices: Simulators may not have all apps installed
iOS Simulator Limitations
iOS simulators do not have default email or phone apps installed, so URLs with mailto: or tel: schemes will not launch. Always test these features on physical iOS devices.
URL Encoding Issues
For URL schemes other than http and https, always use encodeQueryParameters() for query parameters to avoid encoding issues with spaces and special characters.
For more Flutter development tutorials, explore our guide on creating listviews in Flutter to build comprehensive mobile interfaces with proper navigation patterns.
Conclusion
The url_launcher package provides Flutter developers with a powerful, cross-platform solution for integrating external application launching into their apps. By following proper installation procedures, configuring platform-specific requirements, and implementing best practices for error handling and user experience, you can seamlessly connect your Flutter applications with external services and native device capabilities.
Whether you're building a contact page, implementing sharing functionality, or integrating with external services, url_launcher offers the flexibility and reliability needed to create polished, professional mobile applications.
For teams looking to implement robust URL launching and other native integrations in their Flutter projects, partnering with experienced mobile development specialists ensures clean implementation and adherence to platform best practices.
Sources
- Pub.dev - url_launcher package - Official Flutter package documentation with installation, API reference, and platform-specific configuration
- LogRocket Blog - Launching URLs in Flutter with url_launcher - Tutorial with practical examples for building contact pages with URL launching functionality
- Cybrosys - How to Install & Configure Flutter url_launcher - Detailed configuration guide with iOS and Android manifest updates