接收信标消息

您的应用可以使用与订阅其他附近设备发布的消息相同的机制来订阅低功耗蓝牙 (BLE) Beacon 消息

默认情况下,只有当应用在前台运行时,信标订阅才会生效。 当应用进入后台时,订阅会自动停止扫描 Beacon。如需详细了解如何启用后台扫描,请参阅后台扫描

如需订阅 Beacon,请在订阅参数中将 deviceTypesToDiscover 参数设置为 kGNSDeviceBLEBeacon。以下代码段演示了如何执行此操作:

Objective-C

id<GNSSubscription> beaconSubscription = [messageManager
    subscriptionWithMessageFoundHandler:myMessageFoundHandler
                     messageLostHandler:myMessageLostHandler
                            paramsBlock:^(GNSSubscriptionParams *params) {
                              params.deviceTypesToDiscover = kGNSDeviceBLEBeacon;
                            }];

Swift

let beaconSubscription = messageManager.subscriptionWithMessageFoundHandler(
    myMessageFoundHandler, messageLostHandler: myMessageLostHandler,
    paramsBlock: { (params: GNSSubscriptionParams!) in
      params.deviceTypesToDiscover = .BLEBeacon
    })

上述订阅仅发现您的项目拥有的信标,并接收来自这些信标的所有消息。如果您想接收来自注册了其他命名空间的信标的消息,可以在订阅参数中传递命名空间。同样,如果您想要特定类型的消息,也可以传递消息类型以进行过滤。以下代码段展示了如何执行此操作:

Objective-C

id<GNSSubscription> beaconSubscription = [messageManager
    subscriptionWithMessageFoundHandler:myMessageFoundHandler
                     messageLostHandler:myMessageLostHandler
                            paramsBlock:^(GNSSubscriptionParams *params) {
                              params.deviceTypesToDiscover = kGNSDeviceBLEBeacon;
                              params.messageNamespace = @"com.mycompany.mybeaconservice";
                              params.type = @"mybeacontype";
                            }];

Swift

let beaconSubscription = messageManager.subscriptionWithMessageFoundHandler(
    myMessageFoundHandler, messageLostHandler: myMessageLostHandler,
    paramsBlock: { (params: GNSSubscriptionParams!) in
      params.deviceTypesToDiscover = .BLEBeacon
      params.messageNamespace = "com.mycompany.mybeaconservice"
      params.type = "mybeacontype"
    })

默认情况下,信标订阅会同时扫描 Eddystone 和 iBeacon 这两种类型的信标。启用 iBeacon 扫描后,系统会提示用户授予应用使用其位置数据的权限。应用的 Info.plist 必须包含 NSLocationWhenInUseUsageDescription 键,并简要说明使用位置信息的原因。如需了解详情,请参阅 Apple 的文档

如果您只想扫描 Eddystone 信标,可以在 GNSBeaconStrategy 中停用 iBeacon 扫描,这样 iOS 就不会要求用户授予位置信息使用权限。以下代码段展示了如何针对上述原始订阅停用 iBeacon 扫描:

Objective-C

id<GNSSubscription> beaconSubscription = [messageManager
    subscriptionWithMessageFoundHandler:myMessageFoundHandler
                     messageLostHandler:myMessageLostHandler
                            paramsBlock:^(GNSSubscriptionParams *params) {
                              params.deviceTypesToDiscover = kGNSDeviceBLEBeacon;
                              params.beaconStrategy =
                                  [GNSBeaconStrategy strategyWithParamsBlock:^(GNSBeaconStrategyParams *params) {
                                    params.includeIBeacons = NO;
                                  };
                            }];

Swift

let beaconSubscription = messageManager.subscriptionWithMessageFoundHandler(
    myMessageFoundHandler, messageLostHandler: myMessageLostHandler,
    paramsBlock: { (params: GNSSubscriptionParams!) in
      params.deviceTypesToDiscover = .BLEBeacon
      params.beaconStrategy =
          GNSBeaconStrategy(paramsBlock: { (params: GNSBeaconStrategyParams!) in
            params.includeIBeacons = false
          })
    })

默认情况下,系统会启用低功耗扫描,这有时会导致在查找 Eddystone 信标时出现较长的延迟。当低功耗模式处于停用状态时,系统会使用 iBeacon 扫描来帮助查找 Eddystone beacon,这有助于缩短这些延迟时间。不过,这会导致电池耗电量增加,并且 iOS 会询问用户是否允许使用位置信息。

以下代码段展示了如何在扫描 Eddystone 信标时停用低功耗模式。

Objective-C

id<GNSSubscription> beaconSubscription = [messageManager
    subscriptionWithMessageFoundHandler:myMessageFoundHandler
                     messageLostHandler:myMessageLostHandler
                            paramsBlock:^(GNSSubscriptionParams *params) {
                              params.deviceTypesToDiscover = kGNSDeviceBLEBeacon;
                              params.beaconStrategy =
                                  [GNSBeaconStrategy strategyWithParamsBlock:^(GNSBeaconStrategyParams *params) {
                                    params.includeIBeacons = NO;
                                    params.lowPowerPreferred = NO;
                                  };
                            }];

Swift

let beaconSubscription = messageManager.subscriptionWithMessageFoundHandler(
    myMessageFoundHandler, messageLostHandler: myMessageLostHandler,
    paramsBlock: { (params: GNSSubscriptionParams!) in
      params.deviceTypesToDiscover = .BLEBeacon
      params.beaconStrategy =
          GNSBeaconStrategy(paramsBlock: { (params: GNSBeaconStrategyParams!) in
            params.includeIBeacons = false
            params.lowPowerPreferred = false
          })
    })

在扫描 iBeacon 时,iOS 位置信息权限对话框之前会显示“附近”权限对话框。如果您想替换此对话框(例如,提供一个“预检”对话框来解释为何需要位置信息权限),请在订阅参数中将 permissionRequestHandler 设置为自定义块。以下代码段展示了如何执行此操作:

Objective-C

id<GNSSubscription> beaconSubscription = [messageManager
    subscriptionWithMessageFoundHandler:myMessageFoundHandler
                     messageLostHandler:myMessageLostHandler
                            paramsBlock:^(GNSSubscriptionParams *params) {
                              params.deviceTypesToDiscover = kGNSDeviceBLEBeacon;
                              params.permissionRequestHandler = ^(GNSPermissionHandler permissionHandler) {
                                // Show your custom dialog here, and don't forget to call permissionHandler after it is dismissed
                                permissionHandler(userGavePermission);
                              };
                            }];

Swift

let beaconSubscription = messageManager.subscriptionWithMessageFoundHandler(
    myMessageFoundHandler, messageLostHandler: myMessageLostHandler,
    paramsBlock: { (params: GNSSubscriptionParams!) in
      params.deviceTypesToDiscover = .BLEBeacon
      params.permissionRequestHandler = { (permissionHandler: GNSPermissionHandler!) in
        // Show your custom dialog here, and don't forget to call permissionHandler after it is dismissed
        permissionHandler(userGavePermission);
      }
    })

后台扫描

由于信标扫描使用 BLE,因此可以在后台运行。在决定使用后台模式时,您应注意以下事项:

  • 后台 BLE 会增加电池消耗。费用较低,但在决定使用后台模式之前,您应先进行衡量。
  • 如果 iBeacon 扫描已启用或低功耗模式已停用,iOS 会请求用户授予在后台使用位置信息的权限。

如需在后台启用信标扫描,请按以下额外步骤操作:

  • 通过传入配置正确的 GNSBeaconStrategy 对象,为订阅启用后台模式。以下代码段展示了如何执行此操作:

    Objective-C

    id<GNSSubscription> beaconSubscription = [messageManager
        subscriptionWithMessageFoundHandler:myMessageFoundHandler
                         messageLostHandler:myMessageLostHandler
                                paramsBlock:^(GNSSubscriptionParams *params) {
                                  params.deviceTypesToDiscover = kGNSDeviceBLEBeacon;
                                  params.beaconStrategy = [GNSBeaconStrategy
                                      strategyWithParamsBlock:^(GNSBeaconStrategyParams *params) {
                                        params.allowInBackground = YES;
                                      }];
                                }];
    

    Swift

    let beaconSubscription = messageManager.subscriptionWithMessageFoundHandler(
        myMessageFoundHandler, messageLostHandler: myMessageLostHandler,
        paramsBlock: { (params: GNSSubscriptionParams!) in
          params.deviceTypesToDiscover = .BLEBeacon
          params.beaconStrategy =
              GNSBeaconStrategy(paramsBlock: { (params: GNSBeaconStrategyParams!) in
                params.allowInBackground = true
              })
        })
    

  • 向应用的 Info.plist 添加所需条目:

    • UIBackgroundModes 个条目:

      • bluetooth-central 用于在后台进行 BLE 扫描。
      • location 用于在后台使用高功率模式扫描 iBeacon。 如果您仅对 Eddystone 信标进行低功耗扫描,则可以省略此参数。
    • NSLocationAlwaysUsageDescription 字符串,用于说明您将在后台跟踪用户位置信息的原因。例如,“我们需要您的位置信息才能在后台扫描信标。”如需了解详情,请参阅 Apple 的文档。如果您仅对 Eddystone 信标进行低功耗扫描,则可以省略此参数。

  • 用户是否可以在您的应用中启用或停用后台扫描?如果可以,您应将后台模式值保存到 NSUserDefaults,因为 iOS 可以在应用处于后台状态时随时终止该应用。您的应用应执行以下操作:

    • 每当用户更改后台模式值时,都将其保存到 NSUserDefaults
    • 在启动时,从 NSUserDefaults 读取该值,并在启用后台模式时恢复 beacon 订阅。

后台通知

如果您希望应用在后台发现 Beacon 时通知用户,可以使用本地通知。如需了解详情,请参阅后台通知