62

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?

Roc Boronat
  • 11,395
  • 5
  • 47
  • 59
FrederickCook
  • 3,018
  • 4
  • 24
  • 26

17 Answers17

64

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 canLaunch(googleUrl)) {
      await launch(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);
vanlooverenkoen
  • 2,121
  • 26
  • 50
Clairton Luz
  • 2,116
  • 19
  • 15
34

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);
},
  • how do I put multiple directions in such url? – MwBakker Jan 23 '23 at 10:20
  • I had to add this to the AndroidManifest: ``` ``` Also, the above is for navigation. There's another scheme for just opening the maps to that location (see [geo](https://developers.google.com/maps/documentation/urls/android-intents#display-a-map)) EDIT: hmm code blocks don't work in comments, but just grab the text between the ``` – chanban Jun 04 '23 at 20:45
33

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

FrederickCook
  • 3,018
  • 4
  • 24
  • 26
18

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.

Roc Boronat
  • 11,395
  • 5
  • 47
  • 59
15

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';
  }
}
Hazem Ashraf
  • 310
  • 2
  • 8
14
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';
      }
    }
}
Lalit Fauzdar
  • 5,953
  • 2
  • 26
  • 50
Bhargav Sejpal
  • 1,352
  • 16
  • 23
13

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);
Code Runner
  • 868
  • 16
  • 27
10
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/

Muhammad Tameem Rafay
  • 3,602
  • 2
  • 21
  • 32
  • 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. – cdaiga Jul 20 '21 at 06:59
  • 1
    I ran flutter clean then tried again then it worked. – cdaiga Jul 20 '21 at 19:30
  • 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. 'https://www.google.com/maps?' this URL work but suggest is 'https://www.google.com/maps/dir/'. – ViKi Vyas Mar 05 '22 at 12:14
7

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.

flutternoob
  • 296
  • 5
  • 8
5

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.
LazzyCoderr
  • 81
  • 1
  • 2
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.

Heshan Sandeepa
  • 3,388
  • 2
  • 35
  • 45
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

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

My Car
  • 4,198
  • 5
  • 17
  • 50
  • This is not working for me and throw error. Please enhance your answer. One morething, I think this won't work with iOS... – ViKi Vyas Mar 05 '22 at 12:00
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 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
}
Andras Kloczl
  • 8,415
  • 2
  • 21
  • 23
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.';
        }
    }
}
Aditya Patil
  • 1,287
  • 12
  • 19
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);
     }
    }
    
0

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
Adarsh Vijayan P
  • 2,964
  • 2
  • 16
  • 27