Tutorial
Launch Native URL Schemes in Flutter with the url_launcher Plugin
While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.
When developing mobile applications, there’s going to be times when you want to interact with apps outside of your own app. This could be something as simple as opening a web page in Safari, to deep-linking into another application with context.
If this is something you’re looking for, we’re able to do exactly that with the url_launcher
plugin! This plugin has 100 health rating on pub.dev and is made by the Google flutter.dev team.
Creating a new Flutter project
As always, we’ll start off by setting up a new project and adding the plugin:
# New Flutter project
$ flutter create flut_url_launcher
# Open this up inside of VS Code
$ cd flut_url_launcher && code .
Adding the URL Launcher plugin
Head over to your pubspec.yaml
and add the following plugin:
dependencies:
flutter:
sdk: flutter
url_launcher: ^5.2.5
Scaffolding our Project
Our application only requires one page. We’ll go ahead and create a HomePage
at home_page.dart
.
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("URL Launcher"),
),
body: Column(
children: <Widget>[
ListTile(
title: Text("Launch Web Page"),
onTap: () {},
),
],
),
);
}
}
Let’s add the HomePage
to main.dart
:
import 'package:flut_url_launcher/home.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'URL Launcher',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: HomePage(),
);
}
}
Using the URL Launcher plugin
The first thing that we’ll be doing is launching a web page, hence why we’ve got a placeholder ListTile
for that.
Web Pages
The web page we’ll be launching is google.com. Let’s update our ListTile
to be an async
function and do the following:
ListTile(
title: Text("Launch Web Page"),
onTap: () async {
const url = 'https://google.com';
if (await canLaunch(url)) {
await launch(url, forceSafariVC: false);
} else {
throw 'Could not launch $url';
}
},
),
Notice how we’re checking to see if the device canLaunch
a particular URL scheme prior to calling the launch
function.
In this case, we’re calling launch
with forceSafariVC
, as this makes it launch directly in the application on iOS.
If we wanted both iOS and Android to open the web page inside the application (as a WebView, for example), we’d do something like this:
const url = 'https://google.com';
if (await canLaunch(url)) {
await launch(url, forceWebView: true);
} else {
throw 'Could not launch $url';
}
This then gives us a WebView style:
Google Maps and Apple Maps
What about if you wanted to launch Google or Apple maps? Firstly, let’s define a lat
and lng
for wherever we want to open.
class HomePage extends StatelessWidget {
final String lat = "37.3230";
final String lng = "-122.0312";
// ...
}
If you want to do this in a real application, you may want to take advantage of the Geolocation, for which I wrote about recently: Flutter: Getting a User’s Location with the Geolocator Plugin
We can then create a new ListTile
that takes advantage of this:
ListTile(
title: Text("Launch Maps"),
onTap: () async {
final String googleMapsUrl = "comgooglemaps://?center=$lat,$lng";
final String appleMapsUrl = "https://maps.apple.com/?q=$lat,$lng";
if (await canLaunch(googleMapsUrl)) {
await launch(googleMapsUrl);
}
if (await canLaunch(appleMapsUrl)) {
await launch(appleMapsUrl, forceSafariVC: false);
} else {
throw "Couldn't launch URL";
}
},
),
Telephone
Ring ring. Let’s add the functionality to call a phone number from within our app.
Let’s add a telephoneNumber
:
class HomePage extends StatelessWidget {
final String lat = "37.3230";
final String lng = "-122.0312";
final String telephoneNumber = "01817658822";
// ...
}
We can then add a new ListTile
which can be used with the tel:
URL scheme:
ListTile(
title: Text("Telephone"),
onTap: () async {
String telephoneUrl = "tel:$telephoneNumber";
if (await canLaunch(telephoneUrl)) {
await launch(telephoneUrl);
} else {
throw "Can't phone that number.";
}
},
),
Wrap up
I hope you can see the potential with the url_launcher
plugin! We’re able to power up our Flutter app(s) by integrating native experiences across the board.