Reputation: 3258
I'm trying to detect whether Google Maps app is installed on iOS, and if so, launch it, if not, launch Apple Maps. Here is what I have so far, but on my phone with Google Maps installed, it isn't detecting it and launching appropriately.
Any ideas?
import 'package:url_launcher/url_launcher.dart';
_launchMaps() async {
String googleUrl =
'comgooglemaps://?center=${trip.origLocationObj.lat},${trip.origLocationObj.lon}';
String appleUrl =
'https://maps.apple.com/?sll=${trip.origLocationObj.lat},${trip.origLocationObj.lon}';
if (await canLaunch("comgooglemaps://")) {
print('launching com googleUrl');
await launch(googleUrl);
} else if (await canLaunch(appleUrl)) {
print('launching apple url');
await launch(appleUrl);
} else {
throw 'Could not launch url';
}
}
I pulled the url scheme from here: How would I be able to open google maps when I press a button in my app?
Upvotes: 77
Views: 104786
Reputation: 465
For anyone who want to open coordinate with apps like Google Maps Uber, Waze or any other app that support google map uri, can follow my approach.
With my approach, if user is using android, it will use geo:
intent, so user can choose between app that support this google map url as shown in image below.
On iOS, it will try to launch Google Map with comgooglemaps:
scheme.
On both platform if the first uri cannot launch (no installed app support it), it will launch the fallback uri which open up map in browser.
Implementation Code:
Future<void> launchMap(double latitude, double longitude) async {
Uri uri;
if (Platform.isAndroid) {
uri = Uri.parse('geo:$latitude,$longitude?q=$latitude,$longitude');
} else {
uri = Uri.parse('comgooglemaps://?q=$latitude,$longitude');
}
final fallbackUri = Uri(
scheme: "https",
host: "maps.google.com",
queryParameters: {'q': '$latitude, $longitude'},
);
try {
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
} else {
await launchUrl(fallbackUri);
}
} catch (e) {
await launchUrl(fallbackUri);
debugPrint(e.toString());
}
}
Upvotes: 4
Reputation: 2364
you can install the packege url_launcher and use the code down below:
import 'package:url_launcher/url_launcher.dart';
class MapUtils {
MapUtils._();
static Future<void> openMap(double latitude, double longitude) async {
String googleUrl = 'https://www.google.com/maps/search/?api=1&query=$latitude,$longitude';
if (await canLaunchUrl(Uri.parse(googleUrl))) {
await launchUrl(Uri.parse(googleUrl));
} else {
throw 'Could not open the map.';
}
}
}
Now you can open google maps in your app just call this method:
MapUtils.openMap(-3.823216,-38.481700);
Upvotes: 80
Reputation: 166
If you want to open the map in an external app if available on your device, add a launch url property namely LaunchMode. LaunchMode has a few options you can choose from according to your app's needs. LaunchMode options are,
Add url_launcher to your pubspec.yaml file
url_launcher: LATEST_VERSION
Use the given below function,
Future<void> openMap(double latitude, double longitude, {LaunchMode linkLaunchMode = LaunchMode.externalApplication}) async {
String googleUrl = 'https://www.google.com/maps/search/?api=1&query=$latitude,$longitude';
if (await canLaunchUrl(Uri.parse(googleUrl))) {
await launchUrl(Uri.parse(googleUrl), mode: linkLaunchMode);
} else {
throw 'Could not open the map.';
}
}
Upvotes: 9
Reputation: 197
The following will work on the latest LaunchUrl package. mode: LaunchMode.externalApplication is important, otherwise it will open in internal browser in the app, which you don't want.
openMap(double lat, double lng) async {
String googleUrl =
'https://www.google.com/maps/search/?api=1&query=$lat,$lng';
if (await canLaunchUrlString(googleUrl)) {
await launchUrlString(googleUrl, mode: LaunchMode.externalApplication);
} else {
throw 'Unable open the map.';
}
}
Include the package: url_launcher: ^6.1.10
use the latest version: https://pub.dev/packages/url_launcher
Upvotes: 1
Reputation: 3114
Using url luncher with navigation open by default.
Sample code - if app installed it will open in app otherwise open in any browser
///launch map
Future<void> openMap(double latitude, double longitude) async {
String mapUrl = '';
if (Platform.isIOS) {
mapUrl =
'https://maps.apple.com/?daddr=$latitude,$longitude';
} else {
mapUrl =
'https://www.google.com/maps/dir/?api=1&destination=$latitude,$longitude&travelmode=driving';
}
if (await canLaunchUrl(Uri.parse(mapUrl))) {
await launchUrl(Uri.parse(mapUrl),mode: LaunchMode.externalApplication);
} else {
throw 'Could not open the map.';
}
}
if you like to open google map in apple devices add this code in info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
</array>
<key>LSApplicationQueriesSchemes</key>
For other queries
Google url params example
https://www.google.com/maps/dir/?api=1
&origin=$latitude,$longitude
&destination=$latitude,$longitude
&travelmode=driving
&dir_action=navigate
q= query
saddr = starting point for directions
daddr = destination point for directions
dirflg = The transport type
Upvotes: 2
Reputation: 1
Install url_launcher package
use the below function
void launchMap() async {
Uri googleUrl = Uri.parse('https://www.google.com/maps/search/?api=1&query=Googleplex');
if (await canLaunchUrl(googleUrl)) {
await launchUrl(googleUrl, mode:LaunchMode.externalApplication);
}
}
Upvotes: 0
Reputation: 22
Use plugin:
intent: ^1.4.0
Try the following code:
static void navigateTo(double lat, double lng) async {
var uri = Uri.parse("google.navigation:q=$lat,$lng&mode=c");
android_intent.Intent()
..setAction(android_action.Action.ACTION_VIEW)
..setData(uri)
..setPackage("com.google.android.apps.maps")
..startActivity().catchError((e) => print(e));
}
Note: Only works on Android devices
Upvotes: 0
Reputation: 1496
you can install the packege url_launcher and use the code down below:
This is the latest code as per
url_launcher: 6.1.6
canLaunch();
launch();
these methods has been deprecated now.
class GoogleMapUtils {
GoogleMapUtils._();
static Future<void> openMapApp(double latitude, double longitude) async {
Uri googleUrl = Uri.parse('https://www.google.com/maps/search/?api=1&query=$latitude,$longitude');
if (await canLaunchUrl(googleUrl)) {
await launchUrl(googleUrl);
} else {
throw 'Unable open the map.';
}
}
}
Upvotes: 0
Reputation: 1618
static Future<void> openMap(BuildContext context, double lat, double lng) async {
String url = '';
String urlAppleMaps = '';
if (Platform.isAndroid) {
url = 'https://www.google.com/maps/search/?api=1&query=$lat,$lng';
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
} else {
throw 'Could not launch $url';
}
} else {
urlAppleMaps = 'https://maps.apple.com/?q=$lat,$lng';
url = 'comgooglemaps://?saddr=&daddr=$lat,$lng&directionsmode=driving';
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
} else if (await canLaunchUrl(Uri.parse(urlAppleMaps))) {
await launchUrl(Uri.parse(urlAppleMaps));
} else {
throw 'Could not launch $url';
}
}
}
Upvotes: 22
Reputation: 346
As follow-up to Roc Boronat's post, the following code can be used for launching the platform specific map application.
Future<void> launchMapUrl(String address) async {
String encodedAddress = Uri.encodeComponent(address);
String googleMapUrl = "https://www.google.com/maps/search/?api=1&query=$encodedAddress";
String appleMapUrl = "http://maps.apple.com/?q=$encodedAddress";
if (Platform.isAndroid) {
try {
if (await canLaunch(googleMapUrl)) {
await launch(googleMapUrl);
}
} catch (error) {
throw("Cannot launch Google map");
}
}
if (Platform.isIOS) {
try {
if (await canLaunch(appleMapUrl)) {
await launch(appleMapUrl);
}
} catch (error) {
throw("Cannot launch Apple map");
}
}
For more information regarding the query parameters in Apple Maps URL, please visit this link.
Edit (7th Aug, 2022): This code will work upto version 6.0.20 of the url_launcher
plugin. I could not get it to work after this version as I was getting an ERR_UNKNOWN_URL_SCHEME
error when trying to launch Google Maps using canLaunchUrl
and launchUrl
methods using the versions of the plugin above 6.0.20 and 6.0.20. It works only with the deprecated methods (canLaunch
and launch
). Just a heads up if anyone wants to try this code snippet.
Upvotes: 8
Reputation: 1028
If you want to navigate with directions you can just create a url with source and destination co-ordinates and other coordinates to add as stops.
Steps:
Install url_launcher plugin
write a code like below.
_launchURL(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
const url ='https://www.google.com/maps/dir/?api=1&origin=43.7967876,-79.5331616&destination=43.5184049,-79.8473993&waypoints=43.1941283,-79.59179|43.7991083,-79.5339667|43.8387033,-79.3453417|43.836424,-79.3024487&travelmode=driving&dir_action=navigate';
_launchURL(url);
Upvotes: 14
Reputation: 3687
with 'url_launcher 6.1.0' + physical address instead of lat & lon,
void _pushMap(String address) async {
String query = Uri.encodeComponent(address);
String googleUrl = "google.navigation:q=$query";
Uri googleUri = Uri.parse(googleUrl);
if (await canLaunchUrl(googleUri)) {
await launchUrl(googleUri);
}
}
This will send an implicit Intent to open related apps including google maps. Haven't tested on iOS devices.
Upvotes: 2
Reputation: 8495
tldr: I think there's an error in the library and canLaunch sometimes returns false even if the url can be launched.
I was trying to open a google maps link (https://goo.gl/maps/mHGzrGUhUHrQByAm8) the same way I do for another link from my app, but for whatever reason canLaunch always returned false. So now I launch in a try catch block to make sure it doesn't crash my app, and it's working.
try {
launch(url);
} catch (error, stack) {
// log error
}
Upvotes: 0
Reputation: 2142
Do it this way
Full code is given below
static void navigateTo(double lat, double lng) async {
var uri = Uri.parse("google.navigation:q=$lat,$lng&mode=d");
if (await canLaunch(uri.toString())) {
await launch(uri.toString());
} else {
throw 'Could not launch ${uri.toString()}';
}
}
1) in pubspec.yaml
dependencies:
flutter:
sdk: flutter
...
url_launcher: ^5.7.8
2) Import wherever you want to use
import 'package:url_launcher/url_launcher.dart';
3) final you call
onPressed: () {
navigateTo(location.lat, location.lng);
},
Upvotes: 39
Reputation: 4585
import 'package:url_launcher/url_launcher.dart';
static void launchMapsUrl(
sourceLatitude,
sourceLongitude,
destinationLatitude,
destinationLongitude) async {
String mapOptions = [
'saddr=$sourceLatitude,$sourceLongitude',
'daddr=$destinationLatitude,$destinationLongitude',
'dir_action=navigate'
].join('&');
final url = 'https://www.google.com/maps?$mapOptions';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
} }
Here you can use this function directly and pass the required parameters and also import this package https://pub.dev/packages/url_launcher/
Upvotes: 12
Reputation: 12171
If you don't have the actual latlong, you can simply pass an address to Google Maps.
void launchMap(String address) async {
String query = Uri.encodeComponent(address);
String googleUrl = "https://www.google.com/maps/search/?api=1&query=$query";
if (await canLaunch(googleUrl)) {
await launch(googleUrl);
}
}
Of course, the more information you have in the address, the more accurate the search will be. Exactly the same as looking for something on the actual Google Maps page or app.
By the way, you need to url-encode the address before adding it to the URL, to support special characters like spaces. It's only needed for iOS, but hey, we want to develop for all environments out there.
Upvotes: 22
Reputation: 340
using url launcher
in yaml file: url_launcher: ^5.0.2 last
then you can use this method to open google maps centered to the provided lat and long
more info to maps intent from docs [here][2]
launchMap({String lat = "47.6", String long = "-122.3"}) async{
var mapSchema = 'geo:$lat,$long';
if (await canLaunch(mapSchema)) {
await launch(mapSchema);
} else {
throw 'Could not launch $mapSchema';
}
}
Upvotes: 17
Reputation: 3258
I found my issue: this needs to be in the plist file. The code in the question above is fine. (The SO answer referenced in the question only mentioned the "comgooglemaps" string.)
<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
</array>
Upvotes: 39