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

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

- Access the Sheetson website, go to the Go to Console screen and get the API access key as in the image below:

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>
...
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:
Repository link: https://github.com/SavioSantos0808/Tracking-App.
Top comments (2)
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.
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.