DEV Community

Sávio Santos
Sávio Santos

Posted on • Updated on

Real-time geolocation using Ionic Framework and Google Spreadsheets

Alt Text

In this tutorial we will create a basic App using the Ionic Framework, where the user can activate/pause the sending of their location in real time using *Sheetson.

*Service that offers the integration of the Google Sheets API in a more practical and simple way.

1. Requirements

Tools Link
Node.js 12+ installed https://nodejs.org/
Ionic Framework 4+ installed https://ionicframework.com/
Logging into Sheetson using Google account to obtain API https://sheetson.com/

2. Frontend Structure

- Create a blank Ionic project:

$ ionic start trackingApp blank
Enter fullscreen mode Exit fullscreen mode

Install the following dependencies within the project:
- Geolocation: to pick up the user's location.

$ ionic cordova plugin add cordova-plugin-geolocation
$ npm install @ionic-native/geolocation
Enter fullscreen mode Exit fullscreen mode

- Leaflet map: open-source map that we will use to see the user's position.

$ npm install leaflet --save
$ npm install @types/leaflet
Enter fullscreen mode Exit fullscreen mode

Imports:
- In the file src/app/app.module.ts import the dependencies and add them to the providers and imports:

...
import { Geolocation } from '@ionic-native/geolocation/ngx';
import { HttpClientModule } from '@angular/common/http';
...
imports: [..., HttpClientModule, ...],
  providers: [
    Geolocation,
...
Enter fullscreen mode Exit fullscreen mode

- Add the link below within the head tag of the src/index.html file to add CSS files to the map:

...
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"
  integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
  crossorigin=""/>
...
Enter fullscreen mode Exit fullscreen mode

3. Backend Structure

- Go to the Google Drive website and create a new spreadsheet:
Alt Text
Rename the spreadsheet name to trackingApp (or whatever name you like);
Rename the name of the first table in the spreadsheet to Location;
Create 4 columns: timestamp (to mark the date and time), latitude, longitude (user coordinates) and tracking (tracking status).


Alt Text
- Go to the sharing part of the spreadsheet, choose the edit mode option and click done. After that, get the spreadsheet ID as in the image below. We will use it in the API implementation:
Alt Text
- Access the Sheetson website, go to the Go to Console screen and get the API access key as in the image below:
Alt Text

4. Implementation

At first we will create 2 services. One for the API and one for creating a custom alert.
- Create the services within the Ionic project by running the following commands:

$ ionic g service services/api
$ ionic g service services/alert
Enter fullscreen mode Exit fullscreen mode

- In the src/app/services/api.service.ts file add the following logic:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from "@angular/common/http";

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private url: string = "https://api.sheetson.com/v2/sheets";
  private headers: HttpHeaders = new HttpHeaders({
    "X-Spreadsheet-Id": "SHEET ID",
    "Authorization": "Bearer " + "KEY"
  });

  constructor(
    private http: HttpClient
  ) {

  }

  async updateUserLocation(latitude: number, longitude: number, tracking: boolean): Promise<any> {
    let body: any = {
      timestamp: new Date(),
      latitude: latitude,
      longitude: longitude,
      tracking: tracking,
    };
    return this.http.patch(`${this.url}/Location/2`, body, { headers: this.headers }).toPromise();
  }
}
Enter fullscreen mode Exit fullscreen mode

Note that we use the API key and spreadsheet ID in the request headers. We will use the patch method to send the location to the spreadsheet. For reasons I don't know the post and put method are in trouble, so for the rest of the tutorial to work add any values in each column in the 2nd row of the spreadsheet. We will only use the 2nd row of the table.


- In the src/app/services/alert.service.ts file, add the following logic:

import { Injectable } from '@angular/core';
import { AlertController } from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class AlertService {

  constructor(
    private alert: AlertController
  ) { }

  async presentCustomAlert(title, message): Promise<any>{
    let alert = await this.alert.create({
      header: title,
      message: message,
      buttons: ["Ok"]
    });
    alert.present();
  }
}
Enter fullscreen mode Exit fullscreen mode

We will use the alert to show mostly error messages that occur.

Map logic.

- In the src/app/home/home.page.ts file add the following logic to create and show the map:

import { Component } from '@angular/core';
import * as Leaflet from 'leaflet';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss']
})
export class HomePage {
  map: Leaflet.Map;

  constructor() {
  }

  private createMap(): void {
    this.map = Leaflet.map('mapId').setView([-9.002137, -36.325678], 15);
    Leaflet.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: 'App Valmir Motorista',
    }).addTo(this.map);
  }

  ionViewDidEnter(): void {
    this.createMap();
  }

  ionViewDidLeave(): void {
    this.map.remove();
  }
}
Enter fullscreen mode Exit fullscreen mode

- Now, in the src/app/home/home.page.html html file add the map:

<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>Tracking App</ion-title>
    </ion-toolbar>
  </ion-header>
  <ion-content>
    <div id="mapId" style="margin: auto; width: 90%; height: 60%"></div>
  </ion-content>
</ion-app>
Enter fullscreen mode Exit fullscreen mode

Tracking logic.

- Import and define the following classes in the constructor of the Home class at src/app/home/home.page.ts:

...
import { ApiService } from '../services/api.service';
import { AlertService } from '../services/alert.service';
import { Geolocation } from '@ionic-native/geolocation/ngx';
...

...
constructor(
    private geolocation: Geolocation,
    private api: ApiService,
    private alert: AlertService
  ) { }
...
Enter fullscreen mode Exit fullscreen mode

- Define the variables below in the Home class at src/app/home/home.page.ts and create the following function:

...
marker: any;
subscription: Subscription;
coords: any = [];
...

...
btnUpdateLocation(tracking){
  if (tracking){
    this.subscription = this.geolocation.watchPosition().subscribe(async(response: any)=>{
      this.coords = [response.coords.latitude, response.coords.longitude];
      this.api.updateDriverLocation(this.coords[0], this.coords[1], tracking)
      .then(()=>{
        if (this.marker != null){
          this.map.removeLayer(this.marker);
        }
        this.marker = Leaflet.marker(this.coords)
        .addTo(this.map).bindPopup("You are here.");
        this.map.setView(this.coords, 16);
      }).catch(()=>{
        this.alert.presentCustomAlert("Problem", "Check your internet connection.");
      });
    });
  }else{
    this.subscription.unsubscribe();
    this.api.updateDriverLocation(this.coords[0], this.coords[1], tracking)
    .then(()=>{
      this.alert.presentCustomAlert("Success", "Location paused.");
    }).catch(()=>{
      this.alert.presentCustomAlert("Problem", "Check your internet connection.");
    });
  } 
}
...
Enter fullscreen mode Exit fullscreen mode

- Finally, add the following tag to the src/app/home/home.page.ts file. We'll use a segment button:

...
<ion-segment>
      <ion-segment-button (click)="btnUpdateLocation(true)">Activate</ion-segment-button>
      <ion-segment-button (click)="btnUpdateLocation(false)">Pause</ion-segment-button>
</ion-segment>
...
Enter fullscreen mode Exit fullscreen mode
Stay tuned !!!
Add any values in the 2nd row of the spreadsheet in Google Sheets, as the patch method will report a CORS error if not, as it is a data update function.

Test and see the final result:

Alt Text
Alt Text
Repository link: https://github.com/SavioSantos0808/Tracking-App.

If you have encountered any problem please report me. Soon, I will publish the continuation of this tutorial so that it works correctly on all Android devices and with location accuracy.

Top comments (2)

Collapse
 
mezamoe profile image
mezamoe

Hello Santos.. thanks a million for this article! I tried and followed all the steps but in the end the google sheets are not getting any data. I believe all is configured fine, in fact if I modify the URL I get errors, so it's getting through normally. Also the subscription is working as I see the correct location is displayed on screen. I don't get any errors anywhere both on the page or in the dev tools console. I also ran it on my cell phone via Android Studio...nothing.. do you have an idea of what it could be ? I'm using Ionic 6 and Angular 10.

Collapse
 
savi8sant8s profile image
Sávio Santos • Edited

Hi mezamoe. How about explaining me better about the problem. Attach an image of the problem to this email: saviosa08@gmail.com or send me the source code. I am waiting. Forgiveness for the delay.