78

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?

0

19 Answers 19

80

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);
Sign up to request clarification or add additional context in comments.

4 Comments

This will pull the browser on iOS and not the app.
I'm sorry, I will try in iOS and after that I come back here and update the post to solve this problem, tks by your comment.
Which package includes 'MapUtils' ?
@sumitmehra this is not a package but a class you'll write yourself :)
39

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>

Docs: https://developers.google.com/maps/documentation/ios-sdk/start#step_7_declare_the_url_schemes_used_by_the_api

5 Comments

Iam recieving this error. Please Help. MissingPluginException(No implementation found for method canLaunch on channel plugins.flutter.io/url_launcher)
@RachitRawat Rebuild. FrederickCook did you have to configure anything for Android?
@RachitRawat, had the same issue. Try flutter clean
How you do to auto navigate?
@FilipeOS I doubt this is possible, as you could fool the user and navigate him/her into Nirvana.
39

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);
},

2 Comments

how do I put multiple directions in such url?
I had to add this to the AndroidManifest: ``` <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="google.navigation" /> </intent> ``` Also, the above is for navigation. There's another scheme for just opening the maps to that location (see geo) EDIT: hmm code blocks don't work in comments, but just grab the text between the ```
22

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.

Comments

22
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';
      }
    }
}

2 Comments

could you please add explanation instead of pasting only code, thanks.
The address for iOS/Android/Web is now universal: developers.google.com/maps/documentation/urls/get-started (no need to redifine the comgooglemaps:// url)
17

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';
  }
}

1 Comment

not working, throw error
14

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:

  1. Install url_launcher plugin

  2. 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);

1 Comment

This takes directly to the web view with maps, though I have Google Maps app installed.
12
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/

3 Comments

This is what I really want but for some reason I cannot launch the url even after setting up the queries in the android manifest file.
I ran flutter clean then tried again then it worked.
It suggested to add 'api=1', If api=1 is NOT present in the URL, all parameters are ignored and the default Google Maps app will launch, either in a browser or the Google Maps mobile app, depending on the platform in use. 'google.com/maps?' this URL work but suggest is 'google.com/maps/dir'.
10

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,

  • LaunchMode.platformDefault - This is the default mode and leaves the decision of launch the URL to the platform.
  • LaunchMode.inAppWebView - Loads the URL in an in-app webview.
  • LaunchMode.externalApplication - Passes the URL to the OS to be handled by another application.
  • LaunchMode.externalNonBrowserApplication - Passes the URL to the OS to be handled by another non-browser application
  1. Add url_launcher to your pubspec.yaml file

    url_launcher: LATEST_VERSION
    
  2. 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.';
         }
    }
    
  • You can see in the above function, the function has default launch mode as an external application so whenever the user clicks on the link it will open in the external google map app.
  • You can also customize this function base on your feature requirement.

1 Comment

This answer should be at the top. I wasted a lot of time before finding this.
8

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.

Comments

5

Opening Coordinates in Map Apps (Google Maps, Uber, Waze, etc.)

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.

Android:

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.

iOS

On iOS, it will try to launch Google Map with comgooglemaps: scheme.

Fallback to Web URL if failed to launch

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());
    }
  }

Android App Chooser

Comments

2

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.

Comments

2

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

Apple

q= query
saddr = starting point for directions
daddr = destination point for directions
dirflg = The transport type

1 Comment

btw no need to declare the schemes in info.plist if using GMaps universal links (like the one provided in the example)
1

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

Comments

0

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.';
        }
    }
}

Comments

0

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

1 Comment

This is not working for me and throw error. Please enhance your answer. One morething, I think this won't work with iOS...
0
  1. Install url_launcher package

  2. 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);
     }
    }
    

Comments

0

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 link 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
}

Comments

0

Check maps_launcher handles platform defaults. No need to check if Google Maps is installed it works with system defaults automatically.

import 'package:maps_launcher/maps_launcher.dart';

MapsLauncher.launchQuery('1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA');

MapsLauncher.launchCoordinates(37.4220041, -122.0862462);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.