转载

使用 Bluemix 在云中创建移动地理围栏应用程序

您是否曾经遇到过这样的场景:在进入或经过一家商店时,收到特价优惠消息,并想知道这是如何实现的?该技术称为 地理围栏 ,越来越多的公司正在使用这些基于位置的服务,在其商店的邻近区域吸引当地购物者。

知道客户就在附近,使公司能够创建针对性的消息和当地促销信息。将这些基于位置的服务与分析技术相结合,就能让业务人员了解某条促销信息是否成功给商店带来了客户。

本文将介绍如何创建一个移动应用程序,以便使用移动操作系统地理位置功能和 IBM Bluemix 服务来监视大量的地理围栏。

移动操作系统可检测设备何时进入或离开特定的地理区域。这些圆形区域被称为地理围栏。本文将介绍如何创建一个移动应用程序,以便使用移动操作系统地理位置功能和 IBM Bluemix™ 服务来监视大量的地理围栏。文中的示例实现包含两部分:用于地理围栏检测的 iOS 和 Android 客户端代码,以及利用多项 IBM Bluemix 服务来定义和存储地理围栏的服务器端代码。

在本文中,您将学习如何使用 Android 和 iOS 中提供的各种技术,以及 IBM Bluemix 云平台,实现一个地理围栏解决方案。本文还会通过一个全功能代码示例演示该解决方案的主要架构元素,您可以单击下面的 获取代码 按钮获取代码示例。

获取代码

需要做的准备工作

  • 一个IBM Bluemix 帐户
  • 一个 IBM Bluemix DevOps Services 帐户
  • 熟悉 iOS(可选)
  • 熟悉 Android(可选)
  • 熟悉 Node.js(可选)

地理围栏的工作原理

移动应用程序如何检测到设备在一个特定的关注区域内?实际检测由移动设备的操作系统本身完成。因此,甚至在移动应用程序未运行时也能执行监视。

这个监视系统(iOS 和 Android 中都存在)结合使用蜂窝数据和附近的 Wi-Fi 网络来定位设备,而且还会使用 GPS,但只有在设备上的另一个应用程序使用 GPS 时才使用。这有助于执行省电的监视。检测的准确性取决于地理围栏周围的可用传感器类型。一般而言,推荐最小半径为 200 米。

下图给出了这个示例应用程序中使用的总体解决方案:

使用 Bluemix 在云中创建移动地理围栏应用程序

使用 Bluemix 在云中创建移动地理围栏应用程序

在服务器端,解决方案包含一个托管在 IBM Bluemix 平台上的 Node.js 应用程序。还使用了一些 Bluemix 服务来支持该解决方案,包括:

  • Cloudant® NoSQL DB 存储地理围栏的定义
  • IBM MQ Light service 发布地理围栏事件

Node.js 应用程序包含两部分:

  • REST API 允许创建和更新要监视的地理围栏列表,在模式上显示为 管理 API
  • 事件处理 组件接收来自设备自身的事件。

在客户端,移动设备首先需要知道要监视哪个地理围栏列表。设备从管理 API 抓取此列表,然后开始监视在后台使用 iOS 或 Android 监视 API 监视设备的进入或离开。本文后面将进一步解释此过程。

当设备进入或离开一个区域时,设备使用事件处理部分的 REST 端点。然后,事件通过 MQ Light 服务发送。另一个服务(本文没有介绍)可以监听 MQ Light 队列并使用此信息。例如,商店可使用这个存在检测功能来将 “特价优惠” 通知发送到设备。

因为地理围栏列表可能发生更改,所以移动设备通过定期抓取更新的未来列表来确保该列表是最新的。

事件进入 MQ Light 队列中后会发生什么?在本文的示例代码中,什么都不会发生。但在实际应用程序中,会有一个或多个服务将订阅此队列,以获知设备在某个关注区域中的存在情况。此信息可立即用于触发推送通知,或者存储供未来使用。

运行代码示例

上面已经提到,Bluemix DevOps Services 上提供了一个 全功能的示例 。

  1. 要运行该示例,可使用以下命令克隆示例代码:
    git clone https://hub.jazz.net/git/Tissandier/geofencing-sample
  2. 更改到包含 Node.js 应用程序的示例应用程序目录:
    cd geofencing-sample/app
  3. 更新 manifest.yml 文件,将 namehost 参数替换为您的示例应用程序实例的唯一值。您为 host 参数选择的值定义了将托管示例应用程序的 URL (http:// host .mybluemix.net),因此需要一个唯一值。
    declared-services:
     GeofenceDatabase:
     label: cloudantNoSQLDB
     plan: Shared
     GeofenceMQLight:
     label: mqlight
     plan: standard
    applications:
    - disk_quota: 1024M
      host: my-geofencing-sample
      name: my-geofencing-sample
      command: node app.js
      path: .
      domain: mybluemix.net
      services:
      - GeofenceDatabase
      - GeofenceMQLight
  4. 根据 manifest.yml 文件中的声明,Node.js 应用程序需要实例化两个服务:Cloudant 数据库和 MQ Light 服务。您可以从 Bluemix 控制台创建这两个服务。确保 Cloudant 数据库服务被命名为 GeofenceDatabase ,MQ Light 服务被命名为 GeofenceMQLight
  5. 也可以使用以下 Cloud Foundry 命令创建这些服务。(下载和安装 Cloud Foundry 命令行接口的操作说明可在 此处 找到。)
    cf api https://api.ng.bluemix.net
    cf login -u <your-user-ID> -p <your-password> -o <your-org> -s <your-space>
    cf create-service cloudantNoSQLDB Shared GeofenceDatabase
    cf create-service mqlight standard GeofenceMQLight
  6. 创建这些服务并修改 manifest.yml 文件后,可以使用 cf push 命令将该应用程序部署到 Bluemix:
    cf push
  7. 该应用程序现在已启动并运行。Bluemix 控制台还应显示运行的 Node.js 应用程序和关联的服务,如下图所示: 使用 Bluemix 在云中创建移动地理围栏应用程序
    使用 Bluemix 在云中创建移动地理围栏应用程序

创建地理围栏

下一步是使用上面选择的主机名,打开 https://<hostname>.mybluemix.net/ 上的地理围栏仪表板。此操作类似于:

使用 Bluemix 在云中创建移动地理围栏应用程序

使用 Bluemix 在云中创建移动地理围栏应用程序

要创建新地理围栏,请单击 Add geofence 。另一种快速开始的方式是导入现有的 GeoJSon 文件。可在 此处 找到一个可导入为 GeoJSon 的包含大量兴趣点的数据库。

运行移动应用程序

运行该后端应用程序后,可以运行移动应用程序了。存储库会区分表示监视地理围栏和向后端发送信息的类的 SDK,以及用于 iOS 和 Android 且使用该 SDK 的移动应用程序。

iOS 应用程序位于 geofencing-sample/client-sdks/ios/MFGeofenceSample 目录中。Android 应用程序位于 geofencing-sample/client-sdks/android/geofence-demo 目录中。

运行 iOS 应用程序

示例应用程序需要安装 iOS 9.x 或更高版本,以及最新的 Xcode 和 CocoaPods 版本。

  1. 在目录 geofencing-sample/client-sdks/ios

    中,输入下列命令:

    pod install

    您会看到以下结果:

    使用 Bluemix 在云中创建移动地理围栏应用程序

    使用 Bluemix 在云中创建移动地理围栏应用程序

  2. 对于 Xcode,请打开以下工作区文件:
    geofencing-sample/client-sdks/ios/MFGeofenceSample/MFGeofence.xcworkspace
  3. MFGeofenceSample/AppDelegate.swift 文件内,将 baseUrl 变量更改为指向您在部署到 Bluemix 时选择的主机: 使用 Bluemix 在云中创建移动地理围栏应用程序
    使用 Bluemix 在云中创建移动地理围栏应用程序
  4. 您现在可以编译、部署和运行该应用程序。这个示例应用程序仅监视地理围栏,所以该应用程序将显示一个空白屏幕。随着您进入或离开一个地理围栏,您会在电话上看到一条本地通知。
  5. 如果想在部署到真实设备之前,模拟设备进入或离开一个区域,可以使用 Debug/Location/Custom Location… 下的 iOS 模拟器菜单,在模拟器上设置一个自定义位置。 使用 Bluemix 在云中创建移动地理围栏应用程序
    使用 Bluemix 在云中创建移动地理围栏应用程序
  6. 该移动应用程序显示一个本地通知弹出窗口,如下图所示: 使用 Bluemix 在云中创建移动地理围栏应用程序
  7. 要完成该图,要需要确认 Bluemix 端的 MQ Light 服务收到了这些事件。为此,请打开 MQ Light 服务控制台。进入和离开事件应显示在 Messages 仪表板中。 使用 Bluemix 在云中创建移动地理围栏应用程序
    使用 Bluemix 在云中创建移动地理围栏应用程序

运行 Android 应用程序

  1. 要运行该应用程序的 Android 版本,可打开 Android Studio 并导入以下项目: geofencing-sample/clientsdks/android
  2. geofence-demo module 中,打开文件 src/main/java/com/ibm/mf/geofence/demo/MapsActivity.java
  3. 根据您的设置,更改 SERVER_URL 常量的值: 使用 Bluemix 在云中创建移动地理围栏应用程序
    使用 Bluemix 在云中创建移动地理围栏应用程序
  4. 重新构建该应用程序。生成的 APK 现在已准备好安装在设备上。

定义和存储地理围栏

每个地理围栏表示一个要监视的圆形区域,因此由一个经纬度和围绕该点的圆圈的半径来定义。Node.js 应用程序包含存储、修改和检测地理围栏的所有必要的 REST API。

使用 GeoJSON(地图数据的 JSON 标准)来利用列出了兴趣点的现有网站和数据库。因为在 GeoJSON 格式中,您可以添加特定于应用程序的属性,所以您可以扩展该格式来存储自己的自定义属性,比如地理围栏的名称和描述。

要注意的一点是,GeoJSON 目前没有定义 圆圈 的概念。它使用了 Point 的概念,表示地球上的一个点,使用 radius 作为该对象的属性。

这是一个表示为 GeoJSON Feature 对象的地理围栏示例:

{
   "type": "Feature",
   "geometry": {
      "type": "Point",
      "coordinates": [ 2.3488, 48.85341 ]
   },
   "properties":{
      "name": "Center of Paris",
      "description": "A geofence of 1 kilometer meter in the center of Paris",
      "radius": 1000
   }
}

因为 GeoJSON 是一种 JSON 格式,所以地理围栏的解构可直接存储在部署到 Bluemix 上的 NoSQL Cloudant 数据库中。不需要转换数据。

Cloudant 将向数据库中存储的每个对象分配一个新 ID,可使用该 ID 来识别每个地理围栏。您然后会获得一个非常简单的 REST API:

端点 HTTP 方法 描述
/geofences GET 获取所有地理围栏
/geofences POST 创建一个地理围栏 (Feature) 或一组地理围栏 (FeatureCollection)
/geofences/:id GET 获取具有指定 ID 的地理围栏
/geofences/:id PUT 更新具有指定 ID 的地理围栏
/geofences/:id DELETE 删除指定地理围栏

使用 Node.js 的 Express Web 框架,可以用非常简洁的代码表达 GET REST 动词的实现。

var router = express.Router();

var sanitize = function (doc) {
    doc.properties['@code'] = doc._id;
   ['_rev',  '_id'].forEach(function (val) {  delete doc[val];  });
   return doc;
};

router.get(function (req, res) {
   db.get(req.params.id, function (err, data) {
       if (err) {
           res.status(err.status || err.statusCode || 500).send(err);
       } else {
           res.json(sanitize(data));
       }
   });
})

假设 db 表示 Cloudant 数据库客户端,此代码仅从请求参数中指定的 id 获取地理围栏,通过删除 _id_rev 属性来清除地理围栏 JSON 对象(这两个属性表示 Cloudant 中的 JSON 对象身份和修订版),然后返回结果 JSON。其他动词的实现同样简单。

使用应用程序用户界面

示例应用程序还提供了一个简单的用户界面,该用户界面利用 AngularJS 和 Leaflet (一个用于交互式地图的开源包)来创建、更新和删除地图上的地理围栏。

使用 Bluemix 在云中创建移动地理围栏应用程序

使用 Bluemix 在云中创建移动地理围栏应用程序

Leaflet 提供了这个示例应用程序中使用的多个有趣功能。其中一项功能是,Leaflet 能轻松地显示来自多个地图服务器(本示例中使用 OpenStreetMap)的数据,并支持在地图上显示各种不同的围栏。

Leaflet 的 标记 概念还使得添加地理围栏编辑功能变得非常简单。本示例定义了表示 5 个 手柄 的标记,如上图所示。这些手柄使您能交互式地将地理围栏移动到准确的位置,并更改圆圈的大小。

Leaflet 还能够定义地理围栏 集群 。在给定的缩放级别上,当地理围栏太多而无法区分它们时,可使用一个表明所包含地理围栏数量的集群来表示多个地理围栏。这可确保无论缩放级别是多少,地图仍可以看清楚,而不会被过多标记覆盖。

在移动端监视地理围栏

从理论上讲,检测设备进入和离开特定区域可在客户端上完成,或者可将设备位置发送到服务器,在服务器端执行检测。但是,因为地理围栏监视的主要考虑因素是操作时不会耗尽电量,所以这两种方法都不是很好的选择。不能不断要求该应用程序发送设备位置信息,因为这需要启动设备 GPS,可能会耗尽电池电量,而且服务器端解决方案需要大量计算。

实际上,检测进入和离开事件要高效得多,因为移动操作系统本身会执行检测。iOS 和 Android 都拥有一个特定的地理围栏监视 API,允许开发人员监视设备进入和离开一组区域。

  • 有关使用 iOS CoreLocation API 监视区域的信息可在 此处 找到。
  • 对于 Android,有关区域监视的信息可在 此处 找到。

iOS 和 Android 解决方案都很省电。这使开发人员能够注册一组要监视的区域(在 iOS 上最多 20 个区域,在 Android 上最多 100 个区域),并在设备进入或离开一个区域时获得通知。在两种系统上,监视都在后台执行,因此可在应用程序未运行时完成。

这些省电的监视特征非常适合像本文中描述的示例应用程序这样的应用,邀请用户进入商店和利用特价优惠。如果监视过程不省电,用户会卸载该应用程序。

在 iOS 上监视地理围栏

前面已经提到,iOS 开发人员可为一个应用程序注册最多 20 个要监视的区域,对大多数应用程序而言,该数量相对较少。要支持监视更大量的区域,解决方案是在设个更改位置时切换监视的区域,删除远离的区域并添加设备正在接近的区域。

这是如何实现的?在示例应用程序中, MFGeofencingManager 是遵循监视地理围栏的模式的主要 Swift 类。 MFGeofencingManager 利用 iOS SDK 的 CCLocationManager 类来监视基于位置的事件,比如:

  • 进入或离开一个监视区域
  • 设备位置发生重大变化

当设备进入或离开一个监视区域时,此事件会发送到 Node.js 应用程序,iOS 位置管理器会告知该应用程序,设备已明显更改了位置。同样地,此监视过程也很省电。有关该实现的细节,请参阅 MFGeofencingManager+CCLocationManagerDelegate.swift 文件。

当检测到显著的位置变化时, MFGeofencingManager 做两件事:

  • 更新监视的地理围栏列表
  • 检查是否有必要更新服务器上的地理围栏列表

使用 iOS Core Data 来存储地理围栏。更新监视的地理围栏列表的过程包括,根据离当前位置的距离按升序对 Core Data 中的地理围栏记录排序,然后检查要在当前监视列表中添加或删除的围栏,确保同时监视的区域不超过 20 个。(请参阅 MFGeofencingManager+UpdateMonitoredGeofences.swift 文件了解有关的细节。)

要监视的地理围栏列表是在服务器上定义的,必须由设备定期更新。这里需要考虑一些因素。随着设备数量增加,必须仍然保持对服务器的调用次数是合理的,所以将同步调用限制到每天一次。另外,用户应不需要等待数据下载,所以下载在后台进行。这通过使用 iOS Background Transfer Service 来完成。

得益于 Background Transfer Service,操作系统会负责执行下载流程,执行后台线程中的所有操作。该服务还会向应用程序告知下载进度。

在 Android 上监视地理围栏

在 Android 端,系统非常相似,但 Android 在构建在后台运行的服务时更加灵活。Android 解决方案也在 Java 中定义了一个 MFGeofencingManager 类。

这个 MFGeofencingManager 类将地理围栏列表存储在 Android 上的一个 SQL Lite 数据库中。在这里,地理围栏监视通过 Android Geofencing API 完成。(请参阅 Geofencing API 参考手册 了解细节。)

这个 API 用于与 iOS 中类似的限制,所以在本例中,每个用户监视的区域不得超过 100 个。用于 iOS 的相同类型的解决方案也必须能够用于 Android。

Android 位置管理器( 此处 有介绍)用于设置设备位置显著变化的通知。

确保以省电的方式配置位置管理器很重要。位置管理器结合使用一些提供程序来获取设备的位置。使用 NETWORK_PROVIDER (根据网络信号塔和 Wi-Fi 检测位置变化)和 PASSIVE_PROVIDER (一个使应用程序能够让数据被其他应用程序使用的特殊提供程序)。通常,如果某个设备上运行着 GPS 导航应用程序,您的应用程序将利用此位置数据,但它本身对 GPS 精度没有要求。

然后,Android 后台服务实现与 iOS 相同的逻辑:

  • 监听 geofencing API 的进入和离开事件,并告知 Node.js 后端应用程序。
  • 监听位置更新,确定监视的地理围栏列表是否需要更新。

在 Android 中,当设备关闭时,会删除所有监视的地理围栏。Android SDK 然后通过专用的广播接收器监听设备重启事件,然后重新注册被删除的地理围栏。

结束语

在本文中,学习了如何将一个地理围栏监视服务托管在 Bluemix 上,并考虑了服务器和客户端上的各种不同元素。此刻您可能会问,“此解决方案能否随设备数量增加而扩展?”

该示例应用程序仅是一种概念证明和起点,但改进该解决方案的可伸缩性并不是很难。首先,很容易在 Bluemix 中运行 Node.js 应用程序的多个实例。这种水平扩展有助于增加 Node.js 应用程序的事件处理功能的容量。并行运行的 Node.js 应用程序越多,系统可处理的进入和离开事件就越多。Bluemix 负责在 Node.js 实例之间进行负载平衡。

同样需要注意的是,管理 API 和事件处理功能不需要以相同级别扩展。具体地讲,与调用服务器的设备数量相比,更改地理围栏的人很少。所以,改进该解决方案的另一种快速方式是将 Node.js 应用程序分解为多个微服务,进而能够独立地扩展和监视它们。

另外,还可以通过一些方式改进设备上的地理围栏列表的更新。举例而言,一种简单方式是对此列表使用内存型缓存,这样就不必在每次调用设备时都从数据库检索它。

使用 MQ Light 也实现了可伸缩性,它可充当一个缓冲区,使应用程序的中使用进入和离开通知的剩余部分可按自己的节奏使用这些事件。

可以看到,地理围栏为移动应用程序提供了许多激动人心的新机会,而且使用 IBM Bluemix 可大大简化开发流程。

原文  http://www.ibm.com/developerworks/cn/mobile/mo-mobile-geofencing-apps-cloud-bluemix-trs/index.html?ca=drs-
正文到此结束
Loading...