发布和订阅

Nearby Messages API 是一种发布-订阅 API,可让附近的设备 交换小负载的数据。设备发布消息后,就在附近 设备可以接收消息。邮件大小应尽可能小 保持良好性能此服务不支持换取更多 对象(例如照片和视频)。

附近的设备集取决于 蓝牙和近超声(听不到)音频。设备检测到令牌时 它就会将令牌发送到 Nearby Messages 服务器, 验证消息,并检查是否有消息需要传递至应用的 当前订阅的一组新订阅。

应用可以控制用于设备发现的媒介集,以及 媒介是否用于广播令牌和/或扫描令牌。 默认情况下,广播和扫描在所有媒介上都完成。待办事项 或媒介上的发现,以及控制是广播还是扫描, 您必须在创建发布内容时传递额外的参数, 订阅。

此库在 iOS 7 及更高版本上运行,并使用 iOS 8 SDK 构建。

创建消息管理器

此代码会创建一个消息管理器对象,让您可以发布和 订阅。邮件交换未通过身份验证,因此您必须提供一个 公共 API 密钥。您可以使用 Google Developers Console 条目 自己的项目

Objective-C

#import <GNSMessages.h>

GNSMessageManager *messageManager =
    [[GNSMessageManager alloc] initWithAPIKey:@"API_KEY"];

Swift

let messageManager = GNSMessageManager(APIKey: "API_KEY")

发布消息

以下代码段演示了如何发布包含名称的消息。 只要发布内容对象存在,发布内容便处于有效状态。停止 发布,则释放发布内容对象。

Objective-C

id<GNSPublication> publication =
    [messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]];

Swift

let publication =
    messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)))

订阅邮件

此代码段演示了如何订阅由 之前的发布内容摘要。只要 订阅对象已存在。如需停止订阅,请释放订阅 对象。

当附近正在发布设备的设备时,系统会调用“找到消息”处理程序 消息。当消息丢失时,系统会调用消息丢失处理程序。 (设备已超出有效范围或不再发布 消息)。

Objective-C

id<GNSSubscription> subscription =
    [messageManager subscriptionWithMessageFoundHandler:^(GNSMessage *message) {
      // Add the name to a list for display
    }
    messageLostHandler:^(GNSMessage *message) {
      // Remove the name from the list
    }];

Swift

let subscription =
    messageManager.subscription(messageFoundHandler: { (message: GNSMessage?) in
      // Add the name to a list for display
    },
    messageLostHandler: { (message: GNSMessage?) in
      // Remove the name from the list
    })

发现媒介

默认情况下,系统会使用这两种媒介(音频和蓝牙)来发现附近的设备 这两种媒介都会进行广播和扫描在某些情况下 将以下条目添加到应用的 Info.plist 中:

  • 如果您的应用使用音频进行扫描,请添加 NSMicrophoneUsageDescription, 说明您将使用麦克风的原因的字符串。例如,“ 麦克风会监听来自附近设备的匿名令牌。”

  • 如果您的应用使用 BLE 进行广播,请将 NSBluetoothPeripheralUsageDescription,这是一个字符串,用于说明您为何 将在 BLE 上进行广播。例如,“匿名令牌的 来发现附近的设备。”

在某些情况下,您的应用可能只需要使用其中一种媒介 可能不需要在该介质上同时进行广播和扫描。

例如,一款旨在连接到 音频广播只需扫描音频即可发现。以下 展示了如何只使用音频向该机顶盒发布消息 扫描发现:

Objective-C

id<GNSPublication> publication = [messageManager publicationWithMessage:message
    paramsBlock:^(GNSPublicationParams *params) {
      params.strategy = [GNSStrategy strategyWithParamsBlock:^(GNSStrategyParams *params) {
        params.discoveryMediums = kGNSDiscoveryMediumsAudio;
        params.discoveryMode = kGNSDiscoveryModeScan;
      }];
    }];

Swift

let publication = messageManager.publication(with: message,
    paramsBlock: { (params: GNSPublicationParams?) in
      guard let params = params else { return }
      params.strategy = GNSStrategy(paramsBlock: { (params: GNSStrategyParams?) in
        guard let params = params else { return }
        params.discoveryMediums = .audio
        params.discoveryMode = .scan
      })
    })

启用调试日志记录

调试日志记录会将重要的内部事件打印到控制台, 有助于您跟踪在集成“附近”功能时可能遇到的问题 消息发送到您的应用。如果您与我们联系,我们将要求您提供这些日志 获取技术支持。

您应在创建消息管理器之前启用它。此代码段显示了 如何启用调试日志记录:

Objective-C

[GNSMessageManager setDebugLoggingEnabled:YES];

Swift

GNSMessageManager.setDebugLoggingEnabled(true)

跟踪 Nearby 权限状态

需要征得用户同意才能启用设备发现功能。这由 “附近分享”权限状态。首次创建出版物的调用时,或 就会向用户显示意见征求对话框。如果用户没有 同意,设备发现功能将无法正常运行。在这种情况下,您的应用应显示 消息,提醒用户设备发现功能已停用。权限 状态存储在 NSUserDefaults 中。

以下代码段演示了如何订阅权限状态。通过 每当状态发生变化时,系统都会调用权限状态更改处理程序, 在用户授予或拒绝权限之前不会调用该函数。 释放权限对象以停止订阅。

Objective-C

GNSPermission *nearbyPermission = [[GNSPermission alloc] initWithChangedHandler:^(BOOL granted) {
  // Update the UI here
}];

Swift

let nearbyPermission = GNSPermission(changedHandler: { (granted: Bool) in
  // Update the UI here
})

您的应用可以提供一种方式,供用户更改权限状态;用于 例如使用设置页面上的切换开关。

以下示例展示了如何获取和设置权限状态。

Objective-C

BOOL permissionState = [GNSPermission isGranted];
[GNSPermission setGranted:!permissionState];  // toggle the state

Swift

let permissionState = GNSPermission.isGranted()
GNSPermission.setGranted(!permissionState)  // toggle the state

跟踪会影响“附近”功能的用户设置

如果用户已拒绝授予麦克风权限、拒绝了蓝牙权限或 已关闭蓝牙,“附近”功能将无法正常运行,或可能根本无法运行。 在这些情况下,您的应用应显示一条消息,提醒用户附近 运营受到限制。以下代码段展示了如何跟踪 用户设置的状态,即在创建消息时传递处理程序 经理:

Objective-C

GNSMessageManager *messageManager = [[GNSMessageManager alloc]
    initWithAPIKey:API_KEY
       paramsBlock:^(GNSMessageManagerParams *params) {
         params.microphonePermissionErrorHandler = ^(BOOL hasError) {
           // Update the UI for microphone permission
         };
         params.bluetoothPowerErrorHandler = ^(BOOL hasError) {
           // Update the UI for Bluetooth power
         };
         params.bluetoothPermissionErrorHandler = ^(BOOL hasError) {
           // Update the UI for Bluetooth permission
         };
}];

Swift

let messageManager = GNSMessageManager(
         APIKey: API_KEY,
    paramsBlock: { (params: GNSMessageManagerParams?) in
      guard let params = params else { return }
      params.microphonePermissionErrorHandler = { (hasError: Bool) in
        // Update the UI for microphone permission
      }
      params.bluetoothPowerErrorHandler = { (hasError: Bool) in
        // Update the UI for Bluetooth power
      }
      params.bluetoothPermissionErrorHandler = { (hasError: Bool) in
        // Update the UI for Bluetooth permission
      }
    })

替换“附近”权限对话框

根据您传递到发布内容和订阅的参数, 在允许“附近”功能运作之前,iOS 可能会请求各种权限。对于 默认策略会监听在近超声波材料上传输的数据 音频,因此 iOS 会请求您授予使用麦克风的权限。在这些情况下 “附近”功能将显示“预检”对话框,说明为何询问用户 来授予权限。

如果您想提供自定义“预检”对话框中,设置 将 permissionRequestHandler 参数添加到发布内容中的自定义组成块中,或 订阅参数。您的自定义代码块必须调用 permissionHandler 在用户响应后屏蔽。以下代码段展示了如何执行此操作 :

Objective-C

id<GNSPublication> publication =
    [messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]
                               paramsBlock:^(GNSPublicationParams *params) {
                                 params.permissionRequestHandler = ^(GNSPermissionHandler permissionHandler) {
                                   // Show your custom dialog here.
                                   // Don't forget to call permissionHandler() with YES or NO when the user dismisses it.
                                 };
                               }];

Swift

let publication =
    messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)),
        paramsBlock: { (params: GNSPublicationParams?) in
          guard let params = params else { return }
          params.permissionRequestHandler = { (permissionHandler: GNSPermissionHandler?) in
            // Show your custom dialog here.
            // Don't forget to call permissionHandler() with true or false when the user dismisses it.
          }
        })

后台操作

使用 BLE 实现设备发现的出版物和订阅可在 背景。在决定使用 后台模式:

  • 后台操作必须仅使用 BLE 媒介;音频。
  • 后台 BLE 会增加电池成本。费用不高,但是 先对此进行测量,然后再决定使用后台模式。
  • iOS 会请求用户授予在后台通过 BLE 进行通告的权限。

如需为发布内容或订阅添加后台模式,请按照这些额外 步骤:

  • 若想在您的发布内容或订阅中启用后台模式和仅限 BLE,请通过以下方式 传入正确配置的 GNSStrategy 对象。以下代码段 展示了如何对订阅执行此操作:

    Objective-C

    id<GNSSubscription> subscription =
        [messageManager subscriptionWithMessageFoundHandler:^(GNSMessage *message) {
          // Add the name to a list for display
        }
        messageLostHandler:^(GNSMessage *message) {
          // Remove the name from the list
        }
        paramsBlock:^(GNSSubscriptionParams *params) {
          params.strategy = [GNSStrategy strategyWithParamsBlock:^(GNSStrategyParams *params) {
            params.allowInBackground = YES;
            params.discoveryMediums = kGNSDiscoveryMediumsBLE;
          }];
        }];
    

    Swift

    let subscription =
        messageManager.subscription(messageFoundHandler: { (message: GNSMessage?) in
          // Add the name to a list for display
        },
        messageLostHandler: { (message: GNSMessage?) in
          // Remove the name from the list
        },
        paramsBlock:{ (params: GNSSubscriptionParams?) in
          guard let params = params else { return }
          params.strategy = GNSStrategy(paramsBlock: { (params: GNSStrategyParams?) in
            guard let params = params else { return }
            params.allowInBackground = true
            params.discoveryMediums = .BLE
          })
        })
    

  • 将以下条目添加到应用的 Info.plist 中:

    • UIBackgroundModes 个条目:

      • bluetooth-central,用于在后台进行 BLE 扫描。仅需要 当发现模式包括扫描时;默认情况。
      • bluetooth-peripheral,用于后台 BLE 广播。所需 仅当发现模式包括广播时;默认情况。
    • NSBluetoothPeripheralUsageDescription 字符串,用于说明原因 您将通过 BLE 进行广告宣传。例如,“匿名令牌是 通过蓝牙通告来发现附近的设备。”请参阅 Apple 文档 了解详情。

  • 在后台运行时,系统可能随时终止您的应用。如果 后台模式是一项设置,可以由用户、您的 应用应执行以下操作:

    • 无论何时用户,都将后台模式值保存到 NSUserDefaults 进行更改。
    • 启动时,从 NSUserDefaults 读取该读号并恢复“附近” 发布内容和/或订阅。

后台通知

如果您希望应用在订阅收到消息时通知用户 而在后台,您可以使用 本地通知

请按照以下步骤将其添加到应用中:

  • 注册启动时接收本地通知:

    Objective-C

    if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
      [[UIApplication sharedApplication] registerUserNotificationSettings:
          [UIUserNotificationSettings settingsForTypes:
              UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound
                                            categories:nil]];
    }
    

    Swift

    UIApplication.shared.registerUserNotificationSettings(
        UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil))
    

  • 在订阅的处理程序中发送本地通知:

    Objective-C

    GNSMessageHandler myMessageFoundHandler = ^(GNSMessage *message) {
        // Send a local notification if not in the foreground.
        if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
          UILocalNotification *localNotification = [[UILocalNotification alloc] init];
          localNotification.alertBody = @"Message received";
          [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
        }
        // Process the new message...
      };
    

    Swift

    let myMessageFoundHandler: GNSMessageHandler = { (message: GNSMessage?) in
      // Send a local notification if not in the foreground.
      if UIApplication.shared.applicationState != .active {
        let localNotification = UILocalNotification()
        localNotification.alertBody = "Message received"
        UIApplication.shared.presentLocalNotificationNow(localNotification)
      }
      // Process the new message...
    }