NativeScript是用于使用XML,CSS和JavaScript构建跨平台本机移动应用程序的框架。 在本系列中,我们将尝试使用NativeScript应用程序可以完成的一些很酷的事情:地理位置和Google Maps集成,SQLite数据库,Firebase集成和推送通知。 在此过程中,我们将构建一个具有实时功能的健身应用程序,以使用其中的每个功能。
在本教程中,您将学习如何在NativeScript应用程序中使用地理位置和Google Maps。
您将要创造的
您将使用地理位置和Google地图创建步行跟踪器。 它将向用户显示他们已经覆盖了多少距离以及他们为达到该距离所采取的步骤数。 还将有一张显示用户当前位置的地图。
为了让您有个主意,这是最终输出的样子:
设置项目
首先创建一个新的NativeScript应用程序:
tns create fitApp --appid "com.yourname.fitApp"
为了使设置应用程序的UI更加容易,我创建了一个GitHub存储库,其中包括项目的初始版本和最终版本。 您可以继续将app文件夹的内容复制到项目的app文件夹中。 我们将只使用两个文件: main-page.xml和main-page.js文件。 其余的只是NativeScript演示项目的样板。
运行应用
我们将使用Android Studio提供的Android模拟器来测试该应用。 这将使我们能够使用Android GPS模拟器从舒适的家中模拟位置的变化。 我也不太喜欢漫无目的地走到外面来测试地理位置! 但是,如果那是你的事,那么我不会阻止你。
如果执行tns run android
,它将自动调用Android模拟器(如果已安装)。 如果尚未安装,则可以通过启动Android Studio,单击配置 ,然后选择SDK Manager来安装它。 默认情况下,这将打开SDK平台 。 单击SDK Tools选项卡,并确保选择Android Emulator ,然后单击Apply进行安装。
要使用GPS仿真器,请从GitHub下载并运行可执行的war文件:
java -jar android-gps-emulator-0.2.war
完成后,您应该能够从浏览器访问http://localhost:8080/gpsemulator/
并连接到localhost
。 执行此操作时,请确保Android模拟器已在运行。 建立连接后,只需放大地图,然后单击要用作位置的任何位置。 该应用程序将检测到它并将其用作其当前位置。
使用地理位置
NativeScript中的地理位置类似于JavaScript中的Geolocation API 。 功能上的唯一区别是增加了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()
方法用于获取当前位置。
在这里,我们指定了三个选项: desiredAccuracy
, updateDistance
和timeout
。 desiredAccuracy
允许您以米为单位指定精度。 它有两个可能的值: Accuracy.high
(大约3米)和Accuracy.any
(大约300米)。 updateDistance
指定在更新之前的位置和当前位置之间必须有多少差异(以米为单位)。 最后, timeout
指定等待位置的毫秒数。
收到位置后,我们将其设置为start_location
并将其推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()
函数。 此函数类似于JavaScript中的setInterval()
函数,因为它还会重复执行回调函数,直到您使用geolocation.clearWatch()
函数将其停止为止。 根据updateDistance
和minimumUpdateTime
自动调用回调函数。
在下面的代码中,如果位置与之前获取的位置至少相差5米,则位置将被更新。 但是此更新仅每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模拟器开始测试该应用程序。 请注意,您需要在main-view-model.js文件上单击Save来触发应用程序重新加载。
然后在GPS模拟器中选择一个位置,以便应用加载后会获取一个新位置。 如果您不这样做,它将默认为加利福尼亚山景城的Googleplex位置。 这意味着下次您在模拟器上选择一个位置时,它将从该位置跳至您选择的位置。 如果距离很远,那么距离和步长会得到很大的数字。
或者,您可以在启用了Internet和GPS的真实设备上进行测试。 此时仅需要GPS,但是一旦我们添加了Google地图,该应用将需要互联网连接。
使用Google地图
现在,我们将使用Google Maps添加一个显示用户当前位置的地图。
安装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文件,然后添加您自己的Google Maps API密钥(服务器密钥):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="nativescript_google_maps_api_key">YOUR GOOGLE MAPS API KEY HERE</string>
</resources>
在尝试使用之前,请确保已从Google控制台启用了Google Maps Android API。
添加地图
对于地图,打开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
的成功回调函数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地图让用户查看其当前位置。 通过这样做,您已经了解了如何对NativeScript使用地理位置和Google Maps插件。
这只是开始! 在本系列的下一篇文章中,我们将向我们的应用添加本地数据库,推送通知和其他出色功能。
有关NativeScript的全面介绍,请尝试我们的视频课程“使用NativeScript编写移动应用程序” 。 在本课程中,Keyvan Kasaei将逐步向您展示如何构建简单的应用程序。 在此过程中,您将学习如何使用网络请求,MVVM架构以及一些最重要的NativeScript UI组件来实现简单的应用程序工作流程。 最后,您将了解为什么要在下一个移动应用程序项目中使用NativeScript。