FrederickCook
FrederickCook

Reputation: 3258

Open Google Maps app if available with flutter

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

Answers (18)

Blue
Blue

Reputation: 465

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

Upvotes: 4

Clairton Luz
Clairton Luz

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

LazzyCoderr
LazzyCoderr

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,

  • 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.

Upvotes: 9

Firas Abd Alrahman
Firas Abd Alrahman

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

Adarsh Vijayan P
Adarsh Vijayan P

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

Apple

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

Upvotes: 2

Sandeep Sadhasivam
Sandeep Sadhasivam

Reputation: 1

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

Upvotes: 0

Ahmad Rehman
Ahmad Rehman

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

Aditya Patil
Aditya Patil

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

Bhargav Sejpal
Bhargav Sejpal

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

flutternoob
flutternoob

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

Code Runner
Code Runner

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:

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

Upvotes: 14

Heshan Sandeepa
Heshan Sandeepa

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

Andras Kloczl
Andras Kloczl

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

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

Muhammad Tameem Rafay
Muhammad Tameem Rafay

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

Roc Boronat
Roc Boronat

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

Hazem Ashraf
Hazem Ashraf

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

FrederickCook
FrederickCook

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>

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

Upvotes: 39

Related Questions