Description
Required Reading
- Confirmed
Plugin Version
6.1.0
Mobile operating-system(s)
- iOS
- Android
What do you require assistance about?
Dear,
In September 2023 we purchased the Starter license for CAPACITOR BACKGROUND GEOLOCATION, and we are carrying out satisfactory tests, however we have not exactly achieved our goal.
Please let me give you some details;
We are implementing your library in an App programmed in IONIC.
The requirement is that a user who goes from point A to B and does so with our App closed (not in the background) can still collect his location.
Currently we use polygons, which we activate at point a and point b.
To make sure we don't lose any information, we activate a geofence at both points with a radius of 100m, and another one with a radius of 150m. In addition to those two geofences, we add 4 more geofences at a distance of 200m in the North, East, South and West, with a radius of 200m, so we have 6 geofences for point A and 6 for point B.
The result is that it collects location data when it is already about 100-150 meters away from point A.
Sometimes it captures the location between the two points, other times only the surroundings of A and B.
We would like to be able to make full use of this library to collect the location with the highest possible precision.
Can you help us with the library configuration?
Thank you so much.
[Optional] Plugin Code and/or Config
import { BehaviorSubject } from 'rxjs';
import { Injectable } from '@angular/core';
import Ubicacion from '@app/models/Ubicacion';
import BackgroundGeolocation, {
Location
} from "@transistorsoft/capacitor-background-geolocation";
import { AuthenticationService } from '@services/authentication/authentication.service';
import { Preferences } from '@capacitor/preferences';
import { environment } from '@envs';
import { CapacitorHttp } from "@capacitor/core";
import { throttle } from '@app/utils'
import { Capacitor } from '@capacitor/core';
import { MapGeocoder } from '@angular/google-maps';
declare type Coords = {
latitude: number;
longitude: number;
accuracy: number;
speed?: number;
};
declare type Geofence = {
identifier: string;
latitude: number;
longitude: number;
radius?: number;
notifyOnEntry?: boolean;
notifyOnExit?: boolean;
notifyOnDwell?: boolean;
loiteringDelay?: number;
}
@Injectable({
providedIn: 'root',
})
export class GeolocationService {
public location = new BehaviorSubject<Ubicacion | undefined>(null);
isNativePlatform = Capacitor.isNativePlatform();
userLocations = new BehaviorSubject<{
lat: number;
lng: number;
captured_at: string;
source: string;
}[]>([])
constructor(
private authentication: AuthenticationService,
private geocoder: MapGeocoder
) {
this.userLocations.subscribe(userLocations => {
if (userLocations.length > 0) {
throttle(() => this.sendUserLocations(), 60000)
}
})
this.watchBackgroundPosition()
}
locality: string;
address: string = "";
watchBackgroundPosition() {
if (!this.isNativePlatform) {
return
}
BackgroundGeolocation.onLocation((location: Location) => {
const existingLocation = this.userLocations.getValue().find(item => {
return location.sample || (item.lat === location.coords.latitude && item.lng === location.coords.longitude && item.captured_at === location.timestamp)
})
if (!existingLocation) {
this.userLocations.next([
...this.userLocations.getValue(),
{
lat: location.coords.latitude,
lng: location.coords.longitude,
captured_at: location.timestamp,
source: "background"
}
])
}
})
BackgroundGeolocation.onGeofence(geofence => {
const location = geofence?.location
const existingLocation = this.userLocations.getValue().find(item => {
return location?.sample || (item.lat === location?.coords?.latitude && item.lng === location?.coords?.longitude && item.captured_at === location?.timestamp)
})
if (!existingLocation) {
this.userLocations.next([
...this.userLocations.getValue(),
{
lat: location.coords.latitude,
lng: location.coords.longitude,
captured_at: location.timestamp,
source: `geofence/${geofence.action}`
}
])
this.sendUserLocations()
}
});
BackgroundGeolocation.onNotificationAction((buttonId: string) => {
console.warn('debug [onNotificationAction] buttonId:', buttonId);
// Handle the notification click here
// For example, navigate to a specific page in your app
});
BackgroundGeolocation.ready({
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 50,
stopTimeout: 5,
enableHeadless: true,
stopOnTerminate: false,
startOnBoot: true,
showsBackgroundLocationIndicator: false,
notification: {
sticky: true,
title: "Waiis",
text: "Seguimiento de la ubicación activado",
priority: BackgroundGeolocation.NOTIFICATION_PRIORITY_MIN,
layout: "location_tracking_layout",
strings: {
notificationButtonBar: "Desactivar notificación"
},
actions: [
'notificationButtonBar',
],
}
}).then((state) => {
BackgroundGeolocation.start()
});
}
async addGeofence(geofence: Geofence) {
if (!this.isNativePlatform) {
return
}
const existingGeofence = await BackgroundGeolocation.getGeofence(geofence.identifier)
if (!existingGeofence) {
BackgroundGeolocation.addGeofence({
...geofence,
radius: geofence.radius ?? 200,
notifyOnEntry: geofence.notifyOnEntry ?? true,
notifyOnExit: geofence.notifyOnExit ?? true,
notifyOnDwell: false,
loiteringDelay: geofence.loiteringDelay ?? 600000,
})
}
}
async updatePosition(position: Coords) {
const latLng = {
lat: position.latitude,
lng: position.longitude
}
this.geocoder
.geocode({ location: latLng })
.subscribe(res => {
if (res.results.length > 0) {
this.address = res.results[0].formatted_address
this.locality = res.results[0].address_components.find(address => address.types.includes('locality')).long_name
this.location.next({
nombre: "Your location",
nombre_largo: this.address,
locality: this.locality,
coords: {
lat: position.latitude,
lng: position.longitude,
precision: position.accuracy,
speed: position.speed
},
place_id: 'located'
});
}
})
}
sendUserLocations() {
try {
if (this.authentication.isAuthenticated.getValue()) {
Preferences.get({ key: 'token' }).then(async (token) => {
const options = {
url: environment.apiUrl + '/user-locations/bulk',
headers: {
Authorization: "Bearer " + token.value,
'Content-Type': 'application/json'
},
data: {
locations: this.userLocations.getValue()
},
};
const response = await CapacitorHttp.post(options);
this.userLocations.next([])
})
}
} catch (error) {
console.warn("error", error)
}
}
}