55
votes

I am trying to open google maps or maps in my react-native application, but when I run the app in my Iphone/simulator I receive the error "Don't know how to open URI:...". What I am doing wrong?

My code:

openGps() {
  var url = 'geo:37.484847,-122.148386'
  this.openExternalApp(url)
}

openExternalApp(url) {
  Linking.canOpenURL(url).then(supported => {
    if (supported) {
      Linking.openURL(url);
    } else {
      console.log('Don\'t know how to open URI: ' + url);
    }
  });
}
13
is there a similar way to open camera app?Sreevisakh

13 Answers

165
votes

To open url with custom label ios/android:

const scheme = Platform.select({ ios: 'maps:0,0?q=', android: 'geo:0,0?q=' });
const latLng = `${lat},${lng}`;
const label = 'Custom Label';
const url = Platform.select({
  ios: `${scheme}${label}@${latLng}`,
  android: `${scheme}${latLng}(${label})`
});

    
Linking.openURL(url);
18
votes

This is because iOS does not yet have support for geo: yet as mentioned in this SO answer. What you can do is detect the OS and:

  • use geo: on Android
  • handle iOS differently. Possibly use maps: as it will open up Apple Maps, though I'm unsure how to properly send the coordinates to it. Or maybe append it to a google maps HTTP URL and open it in the browser.

For example, your openGps function could look like this:

openGps = (lat, lng) => {
  var scheme = Platform.OS === 'ios' ? 'maps:' : 'geo:';
  var url = scheme + `${lat},${lng}`;
  Linking.openURL(url);
}
17
votes

you can do like this:

Android:

 <TouchableOpacity onPress={() => Linking.openURL('google.navigation:q=100+101')}>

where q is the destination lat + long

IOS:

  <TouchableOpacity onPress={() => Linking.openURL('maps://app?saddr=100+101&daddr=100+102')}>

where saddr is start address and daddr is destination address lat+long

12
votes
const url = Platform.select({
  ios: `maps:0,0?q=${fullAddress}`,
  android: `geo:0,0?q=${fullAddress}`,
})

Linking.openURL(url)
8
votes
const latitude = "40.7127753";
const longitude = "-74.0059728";
const label = "New York, NY, USA";

const url = Platform.select({
  ios: "maps:" + latitude + "," + longitude + "?q=" + label,
  android: "geo:" + latitude + "," + longitude + "?q=" + label
});
Linking.openURL(url);

or with checking if there's a google map app on device and if not open the location in browser

const latitude = "40.7127753";
const longitude = "-74.0059728";
const label = "New York, NY, USA";

const url = Platform.select({
  ios: "maps:" + latitude + "," + longitude + "?q=" + label,
  android: "geo:" + latitude + "," + longitude + "?q=" + label
});

Linking.canOpenURL(url).then(supported => {
  if (supported) {
    return Linking.openURL(url);
  } else {
    const browser_url =
      "https://www.google.de/maps/@" +
      latitude +
      "," +
      longitude +
      "?q=" +
      label;
    return Linking.openURL(browser_url);
  }
});
6
votes

Working on Android with an address using the following:

Linking.openURL('https://www.google.com/maps/search/?api=1&query=address');

Replace address with your favourite address.

3
votes

To complement other answers, here's a snippet of adding a marker on Android:

    const location = `${latitude},${longitude}`
    const url = Platform.select({
      ios: `maps:${location}`,
      android: `geo:${location}?center=${location}&q=${location}&z=16`,
    });
    Linking.openURL(url);

If you want more details about Android and google maps, here's the link for the documentation: https://developers.google.com/maps/documentation/urls/android-intents

2
votes

One solution is to use react-native-map-link lib. It opens a bottom sheet with desired options

import { showLocation } from 'react-native-map-link'

showLocation({
    latitude: 38.8976763,
    longitude: -77.0387185,
    sourceLatitude: -8.0870631,  // optionally specify starting location for directions
    sourceLongitude: -34.8941619,  // not optional if sourceLatitude is specified
    title: 'The White House',  // optional
    googleForceLatLon: false,  // optionally force GoogleMaps to use the latlon for the query instead of the title
    googlePlaceId: 'ChIJGVtI4by3t4kRr51d_Qm_x58',  // optionally specify the google-place-id
    alwaysIncludeGoogle: true, // optional, true will always add Google Maps to iOS and open in Safari, even if app is not installed (default: false)
    dialogTitle: 'This is the dialog Title', // optional (default: 'Open in Maps')
    dialogMessage: 'This is the amazing dialog Message', // optional (default: 'What app would you like to use?')
    cancelText: 'This is the cancel button text', // optional (default: 'Cancel')
    appsWhiteList: ['google-maps'] // optionally you can set which apps to show (default: will show all supported apps installed on device)
    // appTitles: { 'google-maps': 'My custom Google Maps title' } // optionally you can override default app titles
    // app: 'uber'  // optionally specify specific app to use
})
2
votes

I've tried this solution and it's working

const scheme = Platform.select({ ios: 'maps:0,0?q=', android: 'geo:0,0?q=' });
const latLng = `${lat},${lng}`;
const label = 'Custom Label';
const url = Platform.select({
  ios: `${scheme}${label}@${latLng}`,
  android: `${scheme}${latLng}(${label})`
});

Linking.openURL(url);

1
votes

From the documentation in Apple Map Links, a little changes from @Narek Ghazaryan's answer. This is due to apple maps will query on provided "label" first. If the label or store name do not exist, it will show nothing.

So we need to add a parameter as "ll" to specify current location with the provided label / store name.

const scheme = Platform.select({ ios: 'maps:0,0?q=', android: 'geo:0,0?q=' });
const latLng = `${lat},${lng}`;
const label = 'Custom Label';
const url = Platform.select({
  ios: `${scheme}${label}&ll=${latLng}`,
  android: `${scheme}${latLng}(${label})`
});
1
votes

With the help of oma's answer, I came up with this. For the ios version, I directly wrote googleMaps instead of maps because it did not work. This is given that Google Maps is installed on the device and I tested this with a physical device. If its not installed it will go into the store. It works perfectly while starting the navigation too.

<Button
  hasText
  transparent
  onPress={() =>
    Linking.openURL(
      Platform.OS === 'ios'
        ? 'googleMaps://app?saddr=6.931970+79.857750&daddr=6.909877+79.848521'
        : 'google.navigation:q=6.909877+79.848521',
    )
 }>
    <Text>Open Maps</Text>
 </Button>

FYI - Im using the Button component from the Native Base library.

1
votes

For google map/Map direction, you can use this code

const latitude = "30.3753";
const longitude = "69.3451";
const openMapDirection = () => {
    const url: any = Platform.select({
      ios: `comgooglemaps://?center=${latitude},${longitude}&q=${latitude},${longitude}&zoom=14&views=traffic"`,
      android: `geo://?q=${latitude},${longitude}`,
    });
    Linking.canOpenURL(url)
      .then((supported) => {
        if (supported) {
          return Linking.openURL(url);
        } else {
          const browser_url = `https://www.google.de/maps/@${latitude},${longitude}`;
          return Linking.openURL(browser_url);
        }
      })
      .catch(() => {
        if (Platform.OS === 'ios') {
          Linking.openURL(
            `maps://?q=${latitude},${longitude}`,
          );
        }
      });
  };

Note: For open google map on IOS you have to add this in info.plist

<key>LSApplicationQueriesSchemes</key>
  <array>
   <string>comgooglemaps</string>
  </array>
0
votes

I think react-native-launch-navigator module is a much cleaner way of doing this. Then it is simple as LaunchNavigator.navigate([50.279306, -5.163158], {start: "50.342847, -4.749904"}) .then(() => console.log("Launched navigator")) .catch((err) =>console.error("Error launching navigator: "+err));.