Cross-Platform Geolocation in Capacitor: A Beginner-Friendly Guide to getCurrentPosition()

1. Why you should care about geolocation

Whether you’re building a ride-sharing app, a “find my charger” map, or simply pre-filling an address form, you need the device’s GPS coordinates. Capacitor gives you two main tools:

PlatformBest-practice API
Android & iOS@capacitor/geolocation plugin
Web (desktop / mobile browsers)navigator.geolocation

Using each one correctly—and waiting for the result before moving on—is the trick. (Capacitor)


2. The asynchronous puzzle (explained for total beginners)

JavaScript never blocks the main thread.
Both Capacitor’s plugin and the browser’s geolocation run asynchronously because the device might need a few seconds to talk to the GPS chip or the cell tower.

  • Plugin method (Geolocation.getCurrentPosition) already returns a Promise, so you can await it.
  • Browser method (navigator.geolocation.getCurrentPosition) is callback-based—no await possible until we wrap it in our own Promise. (WhatWebCanDo)

3. Quick setup checklist

  1. Install the plugin
    npm i @capacitor/geolocation
    npx cap sync
    
  2. Add permissions
    • Android: In android/app/src/main/AndroidManifest.xml
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      
    • iOS: In ios/App/App/Info.plist
      <key>NSLocationWhenInUseUsageDescription</key>
      <string>This app needs your location to show nearby chargers.</string>
      
  3. Enable HTTPS for web – Browsers deliver location only from secure origins.

4. Code you can copy-paste

const FALL_BACK_POSITION = { lat: 0, lng: 0 };

function browserGeolocation(
  opts?: PositionOptions
): Promise<{ lat: number; lng: number }> {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      pos =>
        resolve({
          lat: pos.coords.latitude,
          lng: pos.coords.longitude,
        }),
      reject,
      opts
    );
  });
}

export async function getCurrentPosition(): Promise<{
  lat: number;
  lng: number;
}> {
  try {
    // 1. Detect platform
    const platform = Capacitor.getPlatform();

    // 2. Pick the best API and await it
    const coords =
      platform === 'web'
        ? await browserGeolocation({ enableHighAccuracy: true, timeout: 10_000 })
        : (() => {
            const { coords } = await Geolocation.getCurrentPosition({
              enableHighAccuracy: true,
              timeout: 10_000,
            });
            return { lat: coords.latitude, lng: coords.longitude };
          })();

    // 3. Cache for later
    localStorage.setItem('coords', `${coords.lat}|${coords.lng}`);
    return coords;
  } catch (err) {
    console.error('Location error:', err);
    return FALL_BACK_POSITION;
  }
}

What this does

  1. Single exit point – you never return before a Promise resolves.
  2. Graceful fallback – if the user denies permission or the GPS times out, you still get predictable coordinates.
  3. No duplicated code – Android and iOS share the same plugin call; only the web uses the wrapper.

5. Common issues & quick fixes

SymptomCauseFix
iOS returns nothingMissing NSLocationWhenInUseUsageDescriptionAdd it to Info.plist.
Android instantly returns cached locationOld Google Play-services cachePass a small maximumAge or call watchPosition for fresh data.
Browser throws “Only secure origins are allowed”Serving over HTTPUse HTTPS or localhost.
Timeout despite good signalGPS cold startIncrease timeout to 15 000 ms and keep enableHighAccuracy: true.

6. Best practices for production

  • Ask permission at a “why” moment (e.g., when the user taps “Find chargers near me”) instead of on app launch.
  • Use reverse geocoding sparingly; it costs requests. Cache results keyed by lat/lng pairs.
  • Respect privacy – store coordinates only as long as truly needed and disclose usage in your privacy policy.
  • Provide a manual fallback – a text field or map picker for users who refuse location access.

7. Key takeaways

  1. Capacitor’s geolocation plugin is Promise-ready—await it.
  2. The browser API isn’t, so wrap it in a Promise.
  3. Unified, async/await-based code keeps your UI smooth across Android, iOS, and web.

Add these snippets to your own Ionic/Capacitor project and you’ll never fight geolocation race conditions again.


FAQs

Q: Can I use the Capacitor plugin on the web, too?
A: The plugin simply re-routes to navigator.geolocation, but it still returns a Promise, so you can avoid writing the wrapper twice. Performance is identical.

Q: How do I track movement instead of a single coordinate?
A: Use Geolocation.watchPosition (plugin) or navigator.geolocation.watchPosition. Remember to clearWatch when done to save battery.

Q: Does this work in the background?
A: Not out of the box. On Android you need a foreground service; on iOS you must enable the “Location updates” background mode and use significant-change or region monitoring.


Final words

That’s it! Copy the code, tweak your permission strings, and ship location-aware features with confidence. Happy coding! 🎉

This article is inspired by real-world challenges we tackle in our projects. If you're looking for expert solutions or need a team to bring your idea to life,

Let's talk!

    Please fill your details, and we will contact you back

      Please fill your details, and we will contact you back