Отслеживаем местоположение устройства в мобильном приложении NativeScript Angular

Разработка /
Разработка: Отслеживаем местоположение устройства в мобильном приложении NativeScript Angular

Тема работы с GPS при создании мобильных приложений NativeScript часто встречается у начинающих разработчиков. И сегодня мы создадим такое приложение на NativeScript с Angular под Android и iOS.

Имейте в виду, что работа с таким приложением в эмуляторе абсолютно бессмысленна, хотя поддержка смены координат и есть в некоторых эмуляторах. Не потому, что плагин не идеальный, а потому, что эмуляторы не приспособлены для работы со сменой координат.
Используйте, по возможности, реальное устройство.

Создаём новый проект

Для начала создадим новый проект NativeScript с Angular, TypeScript и HTML.
Выполните в консоли следующие команды:

tns create GeoProject --ng
cd GeoProject
tns platform add ios
tns platform add android

Ключ --ng нужен для создания проекта именно с Angular. Также помните, что создать проект для iOS можно только на Mac с установленным Xcode.

Теперь установим плагин для геолокации:

tns plugin add nativescript-geolocation

Документация по плагину доступна здесь.

Разработка логики на TypeScript и интерфейса на HTML

Мы планируем разработать несложное приложение: на главном экране будет два текстовых поля, для вывода широты и долготы, и три кнопки. По нажатию на первую кнопку будет запрашиваться местоположение устройства и выводиться на экран. Две другие кнопки будут включать и выключать режим отслеживания, при котором текст на экране будет автоматически изменяться при смене координат устройства.

Откройте файл app/app.component.ts и добавьте туда следующий код:

import { Component, NgZone } from "@angular/core";
import * as Geolocation from "nativescript-geolocation";
 
@Component({
    selector: "my-app",
    templateUrl: "app.component.html",
})
export class AppComponent {
 
    public latitude: number;
    public longitude: number;
    private watchId: number;
 
    public constructor(private zone: NgZone) {
        this.latitude = 0;
        this.longitude = 0;
    }
 
    private getDeviceLocation(): Promise<any> {
        return new Promise((resolve, reject) => {
            Geolocation.enableLocationRequest().then(() => {
                Geolocation.getCurrentLocation({timeout: 10000}).then(location => {
                    resolve(location);
                }).catch(error => {
                    reject(error);
                });
            });
        });
    }
 
    public updateLocation() {
        this.getDeviceLocation().then(result => {
            this.latitude = result.latitude;
            this.longitude = result.longitude;
        }, error => {
            console.error(error);
        });
    }
 
    public startWatchingLocation() {
        this.watchId = Geolocation.watchLocation(location => {
            if(location) {
                this.zone.run(() => {
                    this.latitude = location.latitude;
                    this.longitude = location.longitude;
                });
            }
        }, error => {
            console.dump(error);
        }, { updateDistance: 1, minimumUpdateTime: 1000 });
    }
 
    public stopWatchingLocation() {
        if(this.watchId) {
            Geolocation.clearWatch(this.watchId);
            this.watchId = null;
        }
    }
 
}

Рассмотрим подробнее этот код. В методе constructor класса AppComponent инициализируются переменные и подключается служба NgZone из Angular. Нам она нужна для использования слушателей (listeners) и обновления интерфейса с их помощью.

В документации NativeScript говорится об использовании функции isEnabled компонента Geolocation для определения работоспособности копонентов геолокации устройства. Я не использую эту функцию, потому что она иногда возвращает странный результат. Вместо этого мы воспользуемся этим:

private getDeviceLocation(): Promise<any> {
    return new Promise((resolve, reject) => {
        Geolocation.enableLocationRequest().then(() => {
            Geolocation.getCurrentLocation({timeout: 10000}).then(location => {
                resolve(location);
            }).catch(error => {
                reject(error);
            });
        });
    });
}

Здесь мы вызываем метод enableLocationRequest, который проверит разрешение на доступ к компонентам и если такое разрешение будет получено, нам будет возвращены текущие координаты. Так как это происходит не сразу, мы и используем promise.

Функция getDeviceLocation не привязана к интерфейсу и она частная. А для обновления интерфейса мы будем использовать метод updateLocation.

А что нужно сделать, чтобы отслеживать изменения координат?
Для этого и нужны методы startWatchingLocation и stopWatchingLocation.

public startWatchingLocation() {
    this.watchId = Geolocation.watchLocation(location => {
        if(location) {
            this.zone.run(() => {
                this.latitude = location.latitude;
                this.longitude = location.longitude;
            });
        }
    }, error => {
        console.dump(error);
    }, { updateDistance: 1, minimumUpdateTime: 1000 });
}

Здесь создаём слушателя и обновляем интерфейс с Angular. Слушатель возвращает id, который мы будем использовать, когда захотим его остановить.

Свойство updateDistance показываем, что мы хотим обновлять показания координат только при изменениях более, чем на 1 метр, но свойство minimumUpdateTime указывает, что это обновление происходит только раз в секунду. Поиграйтесь с этими значениями, но помните — они влияют на срок работы от батареи!

Перейдём к интерфейсу. Откройте файл app/app.component.html и добавьте туда следующую разметку:

<ActionBar title="{N} Geolocation Example"></ActionBar>
<GridLayout>
    <StackLayout>
        <Label text="Latitude: {{ latitude }}"></Label>
        <Label text="Longitude: {{ longitude }}"></Label>
        <Button class="btn btn-primary btn-active" text="Update" (tap)="updateLocation()"></Button>
        <Button class="btn btn-primary btn-active" text="Watch Location" (tap)="startWatchingLocation()"></Button>
        <Button class="btn btn-primary btn-active" text="Stop Watching" (tap)="stopWatchingLocation()"></Button>
    </StackLayout>
</GridLayout>

Здесь у нас есть верхняя панель и три кнопки для управления геолокацией, которые привязаны к логике в TypeScript коде.

В этом простом примере мы рассмотрели только первые шаги по работе с геолокацией в NativeScript. Надеюсь, он вам поможет в работе.

По материалам «Track The Device Geolocation In A NativeScript Angular Mobile Application» by Nic Raboy
0 комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.