Пишем приложение реального времени на NativeScript: геолокация и Google Карты
Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)
NativeScript - это среда для создания кросс-платформенных родных мобильных приложений с использованием XML, CSS и JavaScript. В этой серии мы рассмотрим некоторые интересные вещи, которые вы можете сделать в приложении NativeScript: геолокация и интеграция с Google Maps, база данных SQLite, интеграция с Firebase и push-уведомления. По ходу дела мы построим фитнес-приложение с возможностями реального времени, которые будут использовать каждую из этих функций.
В этом уроке вы узнаете, как работать с геолокацией и Google Maps в приложениях NativeScript.
Я предполагаю, что вы уже знаете, как создавать приложения в NativeScript. Если вы новичок в NativeScript, я рекомендую сначала ознакомится с одним из более ранних руководств в NativeScript, прежде чем пытаться следовать этому руководству.
Введение в NativeScript
Создайте свое первое приложение NativeScript
Создание приложения Погоды с помощью TypeScript и NativeScript
Что вы будете создавать
Вы будете создавать трекер ходьбы с использованием геолокации и Google Maps. Оно покажет пользователю, какое расстояние он прошел, и количество шагов, которое понадобилось для покрытия этого расстояния. Будет также доступна карта, которая покажет текущее местоположение пользователя.
Чтобы дать вам представление, вот как будет выглядеть конечный результат:



Настройка проекта
Начните с создания нового приложения NativeScript:
tns create fitApp --appid "com.yourname.fitApp"
Чтобы упростить настройку пользовательского интерфейса приложения, я создал репозиторий GitHub, который включает как стартовую, так и финальную версию проекта. Вы можете продолжить дальше и скопировать содержимое папки app в папку app вашего проекта. Мы будем работать только с двумя файлами: main-page.xml и main-page.js. Остальное - только шаблон из демонстрационного проекта NativeScript.
Запуск приложения
Мы будем использовать эмулятор Android от Android Studio для тестирования приложения. Это позволит нам использовать Android GPS Emulator для имитации смены местоположения. Мне не очень нравится бесцельно ходить вокруг, чтобы проверить геолокацию! Но если вас вдруг это устраивает, то я не стану вас останавливать.
Если вы выполните команду tns run android
, она будет автоматически вызывать эмулятор Android, если он уже установлен. Если он еще не установлен, вы можете установить его, запустив Android Studio, щелкнув configure и выбрав SDK Manager. Это откроет платформу SDK по умолчанию. Перейдите на вкладку «Инструменты SDK» и убедитесь, что выбрали Android-эмулятор и нажмите «Применить», чтобы установить его.
Чтобы использовать эмулятор GPS, загрузите его из GitHub и запустите исполняемый файл war:
java -jar android-gps-emulator-0.2.war
Как только это будет сделано, вы сможете получить доступ к http://localhost:8080/gpsemulator/
из своего браузера и подключиться к localhost
. Убедитесь, что эмулятор Android уже запущен, когда вы это делаете. Как только вы подключитесь, просто увеличьте масштаб карты и щелкните по любому месту, которое вы хотите использовать в качестве местоположения. Приложение обнаружит это и будет использовать его в качестве своего текущего местоположения.



Работа с геолокацией
Геолокация в NativeScript похожа на API геолокации в JavaScript. Единственная разница в функциональности - это добавление функции distance()
, которая используется для вычисления расстояния между двумя местоположениями.
Установка плагина геолокации
Чтобы работать с геолокацией, сначала необходимо установить плагин геолокации:
tns plugin add nativescript-geolocation
Как только это будет сделано, теперь вы можете включить его из своих файлов сценариев:
var geolocation = require("nativescript-geolocation");
Получение текущего местоположения пользователя
Плагин геолокации NativeScript включает три функции, которые можно использовать для работы с текущим местоположением пользователя. Мы будем использовать каждый из них в этом приложении:
getCurrentLocation
watchLocation
distance
Откройте файл main-view-model.js и добавьте следующий код внутри функции createViewModel()
. Здесь мы инициализируем переменные, которые мы будем использовать позже, для хранения различных значений, необходимых для отслеживания местоположения пользователя.
Я добавил несколько комментариев в код, чтобы вы знали, что происходит. Есть также некоторые строки кода, которые закомментированы; Это для интеграции с Google Maps. Я уже закомментировал их для простоты. Как только мы перейдем к интеграции с Google Maps, вам нужно будет удалить эти комментарии.
function createViewModel() { var viewModel = new Observable(); var watchId; // stores the ID of the location watcher so we can stop it later var start_location; // stores the location of the user when they first started tracking var current_location; // stores the current location of the user viewModel.is_tracking = false; // whether the user's location is currently being tracked or not //viewModel.latitude = 15.447819409392789; //viewModel.longitude = 120.93888133764267; //viewModel.zoom = 20; var total_distance = 0; var total_steps = 0; var locations = []; // array which will store the locations //var mapView; //var marker = new mapsModule.Marker(); if (!geolocation.isEnabled()) { // check if geolocation is not enabled geolocation.enableLocationRequest(); // request for the user to enable it } // next: add code for getting the user's current location }
Затем добавьте код для получения текущего местоположения пользователя. Этот код выполняется, когда пользователь нажимает кнопку для запуска и остановки отслеживания местоположения. Метод geolocation.getCurrentLocation()
используется для получения текущего местоположения.
Здесь мы указали три варианта: wishAccuracy
, updateDistance
и timeout
. WishAccuracy
позволяет указать точность в метрах. Метод имеет два возможных значения: Accuracy.high
, что составляет около 3 метров, и Accuracy.any
, что составляет около 300 метров. updateDistance
указывает, какая разница (в метрах) должна быть между предыдущим местоположением и текущим местоположением до его обновления. Наконец, timeout
указывает, сколько миллисекунд следует ждать до изменения локации.
После получения местоположения мы устанавливаем его как start_location
и добавляем его в массив locations
. Позже это место будет использоваться вместе с первым местоположением, которое будет извлечено из просмотра текущего местоположения пользователя, чтобы определить пройденное расстояние.
viewModel.toggleTracking = function() { if (geolocation.isEnabled()) { this.set('is_tracking', !viewModel.is_tracking); // flip the toggle for tracking if (viewModel.is_tracking) { geolocation.getCurrentLocation( { desiredAccuracy: Accuracy.high, // 3 meter accuracy updateDistance: 5, // 5 meters timeout: 2000 // 2 seconds } ). then(function(loc) { if (loc) { start_location = loc; locations.push(start_location); //viewModel.set('latitude', loc.latitude); //viewModel.set('longitude', loc.longitude); } }, function(e){ dialogs.alert(e.message); }); // next: add code for watching user's current location } else { // next: add code to stop watching the user's current location } } else { dialogs.alert("Please enable Geolocation"); } }
Просмотр текущего местоположения пользователя
Чтобы получить текущее местоположение, мы используем функцию geolocation.watchLocation()
. Эта функция аналогична функции setInterval()
в JavaScript, поскольку она также повторно выполняет функцию обратного вызова, пока вы не остановите ее с помощью функции geolocation.clearWatch(
). Функция обратного вызова автоматически вызывается исходя из updateDistance
и minimumUpdateTime
.
В приведенном ниже коде местоположение будет обновляться, если оно не менее чем на 5 метров отличается от предыдущего местоположения, которое было выбрано. Но это обновление произойдет каждые 5 секунд. Это означает, что если пользователь не прошел 5 метров и более в течение 5 секунд, местоположение не будет обновляться.
watchId = geolocation.watchLocation( function (loc) { if (loc) { current_location = loc; // next: add code for getting the distance between two locations } }, function(e){ dialogs.alert(e.message); }, { desiredAccuracy: Accuracy.high, updateDistance: 5, // 5 meters minimumUpdateTime : 5000 // update every 5 seconds } );
Как только пользователь указывает, что они хотят остановить отслеживание, вам нужно вызвать функцию geolocation.clearWatch()
. Вам также необходимо сбросить остальные значения, которые обновляются каждый раз при изменении местоположения.
geolocation.clearWatch(watchId); // stop watching the user's location total_distance = 0; total_steps = 0; locations = []; viewModel.set('distance', "distance travelled: " + total_distance + " meters"); viewModel.set('steps', "steps: " + total_steps);
Получение расстояния между двумя локациями
Теперь мы готовы пройти дистанцию. Это можно сделать, вызвав функцию geolocation.distance()
. Эта функция принимает два объекта location
в качестве своих аргументов, поэтому мы будем использовать последние два местоположения, которые были перенесены в массив locations
, чтобы определить расстояние (в метрах), пройденное пользователем от ранее записанного местоположения до текущего. Оттуда мы можем использовать приблизительное преобразование от счетчиков к числу шагов - я говорю приблизительное, потому что не все люди будут перемещаться на одинаковое расстояние за один шаг.
После этого мы можем просто добавить результирующее distance
и steps
к total_distance
и total_steps
, чтобы мы могли отслеживать общее расстояние и шаги, которые они прошли с тех пор, как начали отслеживать свое местоположение.
locations.push(loc); //viewModel.set('latitude', loc.latitude); //viewModel.set('longitude', loc.longitude); //marker.position = mapsModule.Position.positionFromLatLng(viewModel.latitude, viewModel.longitude); location_count = locations.length; if (location_count >= 2) { var distance = Math.round(geolocation.distance(locations[location_count - 2], locations[location_count - 1])); // get the distance between the last two locations var steps = Math.round(distance * 1.3123); // determine the approximate number of steps // add the current distance to the overall distance travelled total_distance = total_distance + distance; total_steps = total_steps + steps; // update the UI viewModel.set('distance', "distance travelled: " + total_distance + " meters"); viewModel.set('steps', "steps: " + total_steps); }
На этом этапе вы можете начать тестирование приложения с помощью эмулятора GPS, о котором я упоминал ранее. Обратите внимание, что вам нужно нажать save в файле main-view-model.js, чтобы вызвать перезагрузку приложения.
Затем выберите место в эмуляторе GPS, чтобы приложение сразу же загрузило новое место. Если вы этого не сделаете, приложение по умолчанию будет находиться в Googleplex в Маунтин-Вью, Калифорния. Это означает, что в следующий раз, когда вы выберете место на эмуляторе, оно переместится из этого местоположения в выбранное вами место. Если это далеко, вы получите действительно большую дистанцию и большое количество шагов.
В качестве альтернативы вы можете протестировать на реальном устройстве с доступом в Интернет и GPS. На данный момент требуется только GPS, но как только мы добавим Карты Google, для приложения потребуется подключение к Интернету.
Работа с Google Maps
Теперь мы будем использовать Карты Google, чтобы добавить карту, отображающую текущее местоположение пользователя.
Установка плагина Google Maps
tns plugin add nativescript-google-maps-sdk
После установки вам нужно скопировать файлы ресурсов для Android:
cp -r node_modules/nativescript-google-maps-sdk/platforms/android/res/values app/App_Resources/Android/
Затем откройте файл app/App_Resources/Android/values/nativescript_google_maps_api.xml и добавьте свой собственный ключ API Google Карт (ключ сервера):
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="nativescript_google_maps_api_key">YOUR GOOGLE MAPS API KEY HERE</string> </resources>
Перед тем, как попытаться использовать его, убедитесь, что вы включили Google Maps Android API в Google Console.
Добавление карт
Для карты откройте файл main-page.xml, и вы увидите следующее:
<maps:mapView latitude="{{ latitude }}" longitude="{{ longitude }}" zoom="{{ zoom }}" mapReady="{{ onMapReady }}" />
Здесь мы указали три опции (longitude
, latitude
и zoom
и функцию, выполняемую после того, как карта будет готова. longitude
и latitude
определяют местоположение, которое вы хотите отобразить на карте. zoom
определяет масштаб изображения на карте. mapReady
- это где мы указываем функцию для добавления маркера на карту. Этот маркер представляет текущее местоположение пользователя, поэтому оно будет отображаться в центре карты.
По умолчанию это не будет работать, поскольку вы еще не добавили определение схемы для карт. Поэтому в элементе Page
добавьте определение для элемента maps
:
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:maps="nativescript-google-maps-sdk" > </Page>
Как только это будет сделано, экземпляр карты Google должен быть отображен прямо под кнопкой для отслеживания местоположения. У него пока нет карт, поскольку latitude
и longitude
еще не определены. Для этого вернитесь к файлу main-view-model.js и удалите комментарии со строк кода для работы с Google Maps:
// default coordinates viewModel.latitude = 15.447819409392789; viewModel.longitude = 120.93888133764267; viewModel.zoom = 20; // default map zoom level var mapView; // variable for storing the current map instance var marker = new mapsModule.Marker(); // variable for storing the marker instance
Добавление маркера
Поскольку мы уже объявили координаты по умолчанию для маркера, мы можем на самом деле построить маркер после того, как карта будет готова:
viewModel.onMapReady = function(args) { mapView = args.object; // get the map view marker.position = mapsModule.Position.positionFromLatLng(viewModel.latitude, viewModel.longitude); // set the marker's position on the map mapView.addMarker(marker); // add the marker to the map }
Затем нам нужно обновить позицию маркера, как только пользователь начнет отслеживать свое местоположение. Вы можете сделать это в функции обратного вызова успеха для функции getCurrentLocation()
:
locations.push(start_location); // remove the comments for these: //viewModel.set('latitude', loc.latitude); //viewModel.set('longitude', loc.longitude); //marker.position = mapsModule.Position.positionFromLatLng(viewModel.latitude, viewModel.longitude);
Нам также нужно обновить его, когда местоположение пользователя изменится (внутри функции обратного вызова успеха для watchLocation
):
current_location = loc; locations.push(loc); // remove the comments for these: //viewModel.set('latitude', loc.latitude); //viewModel.set('longitude', loc.longitude); //marker.position = mapsModule.Position.positionFromLatLng(viewModel.latitude, viewModel.longitude);
Как только это будет сделано, карта, которая отображает местоположение по умолчанию, должна отображаться в приложении.
Вывод
В этом учебном пособии вы создали приложение NativeScript, которое позволяет пользователю отслеживать, какое расстояние он прошел, и приблизительное количество шагов, которые были сделаны для покрытия этого расстояния. Вы также использовали Карты Google, чтобы пользователь мог просматривать свое текущее местоположение. Благодаря этому вы узнали, как использовать плагины геолокации и Google Maps для NativeScript.
Это только начало! В следующих статьях этой серии мы добавим свою локальную базу данных, push-уведомления и другие интересные возможности.
Тем временем ознакомьтесь с некоторыми другими нашими статьями о NativeScript и кросс-платформенной мобильной разработке.
- Мобильная разработкаСоздание приложения Погода с помощью TypeScript и NativeScriptВернер-Бел-Анчета
- Мобильная разработкаПредставляем Vue и Weex для нативных мобильных приложенийЛоуренс Тертон
- IonicНачинаем работь с сервисами Ionic: AuthВернер-Бел-Анчета
Для полного ознакомления с NativeScript, ознакомьтесь с нашим видео курсом по мобильной разработке с помощью NativeScript. В этом курсе Keyvan Kasaei покажет вам шаг за шагом, как создать простое приложение. В этом курсе вы узнаете, как реализовать простой рабочий процесс приложения с сетевыми запросами, архитектурой MVVM и некоторыми из наиболее важных компонентов пользовательского интерфейса NativeScript. К концу курса вы поймете, почему вы должны рассмотреть NativeScript для своего следующего проекта мобильных приложений.
