loading...

Real-time geolocation using Ionic Framework and Google Spreadsheets

saviosantos0808 profile image SavioSantos0808 Updated on ・5 min read

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

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

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

$ npm install leaflet --save
$ npm install @types/leaflet

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

- 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=""/>
...

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

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

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

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

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

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
  ) { }
...

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

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

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.

Posted on by:

saviosantos0808 profile

SavioSantos0808

@saviosantos0808

I like Linux and I admire indie and retro games due to the wonders accomplished using little storage space.

Discussion

pic
Editor guide