Use Geolocation, Geocoding and Reverse Geocoding in Ionic Capacitor


Use Geolocation, Geocoding and Reverse Geocoding in Ionic Capacitor

Howdy coders ! We are going to discuss very basics of location based functionalities in Capacitor using Ionic. This is a simple, but very important post for early developers. In this post, you will learn how to

  • Implement Geolocation in Ionic Capacitor apps using Capacitor APIs
  • Convert map coordinates to location address (Reverse Geocoding) 
  • Convert location address to map coordinates (Geocoding)
  • Display the user location on Map
  • Track user location continuously

We will test the functionalities in Web and Android device. iOS works pretty similar to Android, except the permissions required in info.plist

Complete code for this tutorial is available on Github repo ionic-angular-capacitor-geolocation

Disclaimer

Since this post is a mix of three frameworks — Ionic, Angular and Capacitor, it is possible you landed here by mistake. If you are looking for Geolocation etc in

  • Ionic Angular (Cordova) apps — Please check this post
  • React Native — Please check this post
  • Ionic Angular (Capacitor) apps — Continue reading 😎

Following my blogging ritual, I’ll take you through the basics of each framework we are using, namely — Ionic, Angular and Capacitor. If you already know about these, feel free to skip to the main content.

What is Ionic 4?

You probably already know about Ionic, but I’m putting it here just for the sake of beginners. Ionic is a complete open-source SDK for hybrid mobile app development. Ionic provides tools and services for developing hybrid mobile apps using Web technologies like CSS, HTML5, and Sass. Apps can be built with these Web technologies and then distributed through native app stores to be installed on devices.

In other words — If you create native apps in Android, you code in Java. If you create native apps in iOS, you code in Obj-C or Swift. Both of these are powerful, but complex languages. With Cordova (and Ionic) you can write a single piece of code for your app that can run on both iOS and Android (and windows!), that too with the simplicity of HTML, CSS, and JS.

Capacitor — How is it different from Cordova ?

For quite some time, Cordova has been the only choice available for hybrid app developers. Cordova builds Ionic web app into a device installable app. But there are some limitations of Cordova, which Capacitor tries to overcome with a new App workflow.

Capacitor is a cross-platform app runtime that makes it easy to build web apps that run natively on iOS, Android, Electron, and the web. Ionic people call these apps “Native Progressive Web Apps” and they represent the next evolution beyond Hybrid apps.

Capacitor is very similar to Cordova, but with some key differences in the app workflow

Here are the differences between Cordova and Capacitor (You’ll appreciate these only if you have been using Cordova earlier, otherwise you can just skip)

  1. Capacitor considers each platform project a source asset instead of a build time asset. That means, Capacitor wants you to keep the platform source code in the repository, unlike Cordova which always assumes that you will generate the platform code on build time
  2. Because of the above, Capacitor does not use config.xml or a similar custom configuration for platform settings. Instead, configuration changes are made by editing AndroidManifest.xml for Android and Info.plist for Xcode
  3. Capacitor does not “run on device” or emulate through the command line. Instead, such operations occur through the platform-specific IDE. So you cannot run an Ionic-capacitor app using a command like ionic run ios . You will have to run iOS apps using Xcode, and Android apps using Android studio
  4. Since platform code is not a source asset, you can directly change the native code using Xcode or Android Studio. This give more flexibility to developers

In essence, Capacitor is like a fresh, more flexible version of Corodva.

Plugins

Cordova and Ionic Native plugins can be used in Capacitor environment. However, there are certain Cordova plugins which are known to be incompatible with Capacitor. For Geocoding functionality, we’ll use the Ionic Native Geocode Plugin.

What is Geolocation? 🗺

The most famous and familiar location feature — Geolocation, is the ability to track a device’s whereabouts using GPS, cell phone towers, WiFi access points or a combination of these. Both mobile and desktop devices can use geolocation. There are apps which use location once, and there are apps which continuously track your location as well (😱)

Some famous apps using Geolocation are

  • Uber / Lyft — Cab booking (one time and continuous tracking)
  • Google Maps (of course) — Map services
  • Swiggy / Zomato/ Uber Eats — Food delivery
  • Fitbit — Fitness app
  • Instagram / Facebook — For tagging photos

What is Geocoding and Reverse geocoding?

Geocoding is the process of transforming a street address or other description of a location into a (latitude, longitude) coordinate.
Reverse geocoding is the process of transforming a (latitude, longitude) coordinate into a (partial) address. The amount of detail in a reverse geocoded location description may vary, for example, one might contain the full street address of the closest building, while another might contain only a city name and postal code.

Post structure

We will go in a step-by-step manner to explore the location features. This is my break-down of the blog

STEPS

  1. Create a simple Ionic 4 app and integrate Capacitor 
  2. Implement Geolocation API and get current location
  3. Convert user Geolocation into an address (Reverse Geocoding)
  4. Display user location on Google Map
  5. Convert user entered address into Geocode (Geocoding)
  6. Track user location

So ….. let’s dive right in!



umm…. dive better

Step 1 — Create a simple Ionic 4 app with Capacitor

I have covered this topic in detail in this blog.

In short, the steps you need to take here are

  • Make sure you have node installed in the system (V10.16.0 at the time of this blog post)
  • Install ionic cli using npm
  • Create an Ionic app using ionic start ionic-capacitor-geolocation tabs

You can create a tabs starter for the sake of this tutorial. I’ll use one tab each for 

Tab 1 — Geolocation and reverse geocoding

Tab 2— Display location on Google Map and Geocoding

Tab 3— Tracking location continuously

Once the installation is done, run your app on browser using

$ ionic serve

You’ll see the default UI of Ionic starter. We’ll modify the UI as we go.

Integrate Capacitor

Capacitor can be attached to an existing Ionic app as well. To attach Capacitor to your existing Ionic app, run

$ ionic integrations enable capacitor

This will attach Capacitor to your Ionic app. After this, you have to init the Capacitor app with

$ npx cap init

It will ask you the app name and ID. Give app name whatever you want. App ID is the domain identifier of your app (ex: com.example.app). Note this ID as this will be required later when you create app in Facebook developer console.

Step 2 — Implement Geolocation API and get current location

Capacitor’s in-built Geolocation APIs can be used to get device location. This works for web, iOS and Android. This API provides information about the device’s location, such as latitude, longitude, speed, heading, altitude etc.

The code stays same for all types of devices. Just invoke the API from Capacitor in-built plugins and use it to get location.


Geolocation code in Capacitor Ionic

2.1 Web

When you run the app using ionic serve , the geolocation API will ask location permission the first time. Fire the locate function to get your device’s location.


Get device latitude and longitude in web — using Ionic Capacitor

Get device latitude and longitude in web — using Ionic Capacitor

The result from Geolocation API looks like this


Geolocation API result in Capacitor

Geolocation API result in Capacitor

Notice there are extra parameters such as altitude, heading, speed etc. in the result. These are provided by the API whenever available.

2.2 Android 

Build the app on Android using following commands

// Build web assets
$ ionic build
// Add android platform
$ npx cap add android
// Copy all changes to Android platform
$ npx cap sync
// Open the project in Android studio
$ npx cap open android

Geolocation API requires the following permissions be added to your AndroidManifest.xml:

<!-- Geolocation API -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />

Build the app from Android studio in your device and test.


Geolocation on Android — Ionic Capacitor

Geolocation on Android — Ionic Capacitor

Android quirk

There is one weird implementation issue in Capacitor Geolocation API in Android. Here are the steps to reproduce:

  • Turn off location services on your device
  • Open capacitor app that calls getCurrentPosition()- now it should fail because you turned off location services that’s okay so far
  • Turn on location services and switch back to your app and run getCurrentPosition() again - now the call STILL FAILS even though location services are turned back on

This is because the API tries to run getLastKnownLocation which returns null, because no other App has requested a Location since you turned Location services back on. If you switch to Google maps and request your current location, getCurrentPosition starts working again because the Android location service has another location in memory. You can track the issue on official Capacitor Github Repo here.

2.3 iOS

Apple requires privacy descriptions to be specified in Info.plist for location information. These two keys are important to be specified.

Name: Privacy - Location Always Usage Description 
Key: NSLocationAlwaysUsageDescription

Name: Privacy - Location When In Use Usage Description 
Key: NSLocationWhenInUseUsageDescription

Build the app on iOS using following commands

// Build web assets
$ ionic build
// Add android platform
$ npx cap add ios
// Copy all changes to Android platform
$ npx cap sync
// Open the project in Android studio
$ npx cap open ios

The Geolocation function runs smoothly on iOS, same as Android

Step — 3 Convert user Geolocation into an address — Reverse Geocoding

This will be implemented using Ionic Native-geocoder plugin (Yes, it works with Capacitor too ! 👻). Since this is a Cordova based plugin, it won’t work in web. Install the plugin using

$ ionic cordova plugin add cordova-plugin-nativegeocoder
$ npm install @ionic-native/native-geocoder

Add this plugin to your app’s module to Providers of your app like this


Now time to import this plugin in yourtab1.page.ts where we will convert user’s location to address.

First, we will import the plugin like this

import { NativeGeocoder, NativeGeocoderResult, NativeGeocoderOptions } from '@ionic-native/native-geocoder/ngx';

and inject it in our Constructor (Dependency injection) like this

constructor(private nativeGeocoder: NativeGeocoder) {}

And use this code for reverse-geocoding coordinates into address

let options: NativeGeocoderOptions = {
useLocale: true,
maxResults: 5
};
this.nativeGeocoder.reverseGeocode(latitude, longitude, options)
.then((result: NativeGeocoderResult[]) => console.log(JSON.stringify(result[0])))
.catch((error: any) => console.log(error));

Android

Here’s the reverse geocoding result of the current user’s location. 


Reverse geocoding in Capacitor

Reverse geocoding of coordinates in Capacitor

This is the result of reverse geocoding


Reverse geocoding in Capacitor

Reverse geocoding response in Capacitor

Step 4 — Display user location on Google Map

Let’s move on to next tab. Here, we will show user’s location fetched from Geolocation API on Google Map. We will also use this Google Map for Geocoding i.e. Show a user entered address as a marker on the map.

4.1 Integrate Google Map

Google Map can be easily integrated in an Angular Ionic app using Angular Google Maps. Install it using

$ npm install @agm/core

Import AgmCoreModule in app.module.ts 

import { AgmCoreModule } from '@agm/core';

and add the following to imports in same file app.module.ts

...
AgmCoreModule.forRoot({
apiKey: 'YOUR GOOGLE MAP API KEY',
libraries: ['places']
}),
...

After this, import AgmCoreModule in tab2.module.ts as well, and add AgmCoreModule in imports in same file.

AGM map can be easily displayed in Tab 2 using following small piece of code

<agm-map [latitude]="lat" [longitude]="lng" [zoom]="15" [disableDefaultUI]="false">
<agm-marker [latitude]="lat" [longitude]="lng" [markerDraggable]=true></agm-marker>
</agm-map>

where lat and lng are the map center, as well as, market location. 

4.2 Showing current location on Map

Similar to the first tab, we can get the current location from Capacitor Geolocation API. The latitude and longitude thus obtained can be used as center of the map, as well as, marker location. Here’s the result 


Showing current geolocation on AGM Google Map in Capacitor — Web

Showing current geolocation on AGM Google Map in Capacitor — Web

Code for this section can be found combined in next step.

STEP 5 —  Geocode and show Geocoded location on Map

Geocoding uses the same plugin as reverse geocoding — Ionic native-geocoder. 

Import the plugin in tab2.page.ts in the same fashion as Tab1. Connect the screen’s text input to a variable, and Geocode the variable with following code

this.nativeGeocoder.forwardGeocode(this.address, options)
.then((result: NativeGeocoderResult[]) => {
console.log('lat='+result[0].latitude+'long='+result[0].longitude);
})
.catch((error: any) => console.log(error));

Overall tab2.page.ts code will look like this, containing both current location display on map and geocoding


Geocoding and displaying current location on Google Map

Notice, I have used parseFloat(result[0].latitude) for coordinates. Some specific issues cause the AGM map not to re-center or change marker location if the coordinates are in string format. So make sure you convert them in number to see changes on map. 

Here’s how the geocoding and map re-centering looks like on Android



Geocode address and show location on Google Map — Android , in Capacitor app

Step 6 — Track user location

We’ll do the tracking stuff in Tab 3. If you want continuous tracking of the user location, you can use the Capacitor geolocation API itself for that

let watch = this.geolocation.watchPosition();
watch.subscribe((data) => {
// data is output only when position changes
this.lat = position.coords.latitude;
this.lng = position.coords.longitude;
});

So this function will give you user current location latitude and longitude. You can call clearWatch on any given watch to stop tracking user location. 

Generally, watchPosition will only give you results when there is a change in location. So if you are testing on a browser, you’ll have to fake change location to see the actual effect. If you are testing on mobile device, start running ! 🏃

Here’s the code for starting and stopping the watch — tab3.page.ts


Web Browser

Here’s my track user testing on browser



Track user location using Capacitor Geolocation API on browser

As you can see from the values, I’m clearly fake changing the browser geolocation using Chrome tools.

Android

Here’s the same code on Android device


Track user location using Capacitor Geolocation API on Android

Track user location using Capacitor Geolocation API on Android

Hooray ! That’s your geolocation application right there. 🎉

Conclusion

In this blog, we learned how to implement Geolocation in Capacitor apps with Ionic and Angular frameworks. We learnt how to convert coordinates into location address (Reverse Geocoding) and location address into coordinates (Geocoding) in a simple Ionic app and tested on Web and Android .

You can use these functionalities in a number of professional apps, be it food delivery, e-commerce, ticket booking or just a chat app.

Complete code for this tutorial is available on Github repo ionic-angular-capacitor-geolocation

Next Steps

Now that you have learned the implementation of Geolocation functionalities in Ionic Capacitor app with Angular, you can also try following blogs for other Ionic apps

Ionic Angular Capacitor

If you need a base to start your next Capacitor app, you can make your next awesome app using Capacitor Full App


Capacitor Full App with huge number of layouts and features

Capacitor Full App with huge number of layouts and features

Ionic React Capacitor

If you need a base to start your next Ionic 4 React app, you can make your next awesome app using Ionic React Full App



Ionic 4 React Full App with huge number of layouts and features

Ionic Angular Cordova

If you need a base to start your next Ionic 4 Angular app, you can make your next awesome app using Ionic 4 Full App



Ionic 4 Full App with huge number of layouts and features



Title
Subtitle
Kicker