Nearby Messages API は、近くのデバイス間で小さなペイロードのデータを交換できるパブリッシュ / サブスクライブ API です。デバイスがメッセージを公開すると、近くのデバイスがそのメッセージを受信できます。良好なパフォーマンスを維持するには、メッセージのサイズをかなり小さくする必要があります。このサービスは、写真や動画などの大きなオブジェクトの交換を目的としたものではありません。
近くにあるデバイスのセットは、Bluetooth と超音波近傍(不可聴)オーディオを介した小さなトークンの交換によって決定されます。デバイスが近くのデバイスのトークンを検出すると、そのトークンを Nearby Messages サーバーに送信して検証し、アプリケーションの現在のサブスクリプション セットに配信するメッセージがあるかどうかを確認します。
アプリは、デバイス検出に使用されるメディアのセットと、トークンのブロードキャストやトークンのスキャンにメディアを使用するかどうかを制御できます。デフォルトでは、ブロードキャストとスキャンはすべてのメディアで実行されます。サブセットまたはメディアで検出を行う場合や、ブロードキャストまたはスキャンのどちらを行うかを制御する場合は、パブリケーションとサブスクリプションを作成するときに追加のパラメータを渡す必要があります。
このライブラリは iOS 7 以降で動作し、iOS 8 SDK でビルドされます。
メッセージ マネージャーを作成する
このコードは、パブリッシュとサブスクライブを可能にするメッセージ マネージャー オブジェクトを作成します。メッセージ交換は認証されていないため、iOS 用の公開 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
})
発見メディア
デフォルトでは、両方のメディア(音声と Bluetooth)を使用して近くのデバイスを検出し、両方のメディアがブロードキャストおよびスキャンを行います。特定のケースでは、アプリの Info.plist
に次のエントリを追加する必要があります。
アプリが音声を使用してスキャンする場合は、
NSMicrophoneUsageDescription
を追加します。これは、マイクを利用する理由を説明する文字列です。たとえば、「マイクは近くのデバイスからの匿名トークンをリッスンします」などです。アプリが BLE を使用してブロードキャストする場合は、
NSBluetoothPeripheralUsageDescription
を追加します。これは、BLE でアドバタイズする理由を説明する文字列です。たとえば、「匿名トークンが Bluetooth 経由でアドバタイズされ、近くのデバイスが検出されます」などです。
アプリで使用するメディアが 1 つだけの場合や、そのメディアでブロードキャストとスキャンの両方を行う必要がない場合があります。
たとえば、音声でブロードキャストしているセットトップ ボックスに接続するように設計されたアプリは、音声でスキャンするだけで検出できます。次のスニペットは、検出に音声スキャンのみを使用して、そのセットトップ ボックスにメッセージをパブリッシュする方法を示しています。
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
})
})
デバッグ ロギングの有効化
デバッグ ロギングでは、重要な内部イベントがコンソールに出力されます。これは、Nearby Messages をアプリに統合する際に発生する可能性のある問題の追跡に役立ちます。技術サポートにお問い合わせいただいた場合は、これらのログをお知らせください。
メッセージ マネージャーを作成する前に有効にする必要があります。次のコード スニペットは、デバッグ ロギングを有効にする方法を示しています。
Objective-C
[GNSMessageManager setDebugLoggingEnabled:YES];
Swift
GNSMessageManager.setDebugLoggingEnabled(true)
Nearby 権限の状態のトラッキング
デバイスの検出を有効にするには、ユーザーの同意が必要です。これは、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
ニアバイシェアに影響するユーザー設定の追跡
ユーザーがマイク権限を拒否した場合、Bluetooth 権限を拒否した場合、または Bluetooth をオフにしている場合、Nearby は正常に機能しないか、まったく機能しない可能性があります。このような場合は、Nearby の動作が妨げられていることをユーザーに警告するメッセージをアプリに表示する必要があります。次のスニペットは、メッセージ マネージャーの作成時にハンドラを渡して、これらのユーザー設定のステータスを追跡する方法を示しています。
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 が Nearby の機能の使用を許可する前に、さまざまな権限をリクエストすることがあります。たとえば、デフォルトの戦略では超音波に近い音声で送信されるデータをリッスンするため、iOS はマイクを使用する権限を要求します。このような場合、Nearby には、ユーザーに権限を付与するよう求める理由を説明する「プリフライト」ダイアログが表示されます。
カスタムの「プリフライト」ダイアログを表示する場合は、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 経由でアドバタイズするための権限をユーザーに求めます。
バックグラウンド モードをパブリケーションまたは定期購入に追加するには、次の追加手順を行います。
適切に構成された
GNSStrategy
オブジェクトを渡して、パブリケーションまたはサブスクリプションでバックグラウンド モードと BLE のみを有効にします。次のスニペットは、サブスクリプションでこれを行う方法を示しています。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 アドバタイズ。検出モードにブロードキャストを含む場合にのみ必要です。デフォルトではブロードキャストを含みます。
BLE で広告を配信する理由を説明する文字列。
NSBluetoothPeripheralUsageDescription
たとえば、「匿名トークンが Bluetooth 経由でアドバタイズされ、近くのデバイスが検出されます」などです。詳しくは、Apple のドキュメントをご覧ください。
アプリはバックグラウンドで実行されているときに、システムによっていつでも強制終了される可能性があります。バックグラウンド モードがユーザーが有効または無効にできる設定である場合、アプリは次のように動作する必要があります。
- ユーザーが変更するたびに、バックグラウンド モードの値を
NSUserDefaults
に保存します。 - 起動時に
NSUserDefaults
から読み取り、バックグラウンド モードが有効になっている場合は、Nearby のパブリケーションや定期購入を復元します。
- ユーザーが変更するたびに、バックグラウンド モードの値を
バックグラウンド通知
定期購入がバックグラウンドでメッセージを受信したときにアプリでユーザーに通知する場合は、ローカル通知を使用できます。
アプリに追加する手順は次のとおりです。
起動時にローカル通知を登録します。
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... }