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)))
メッセージへの登録
このコード スニペットは、以前のパブリケーション スニペットで共有されているすべての名前への登録を示しています。サブスクリプションは、サブスクリプション オブジェクトが存在する限りアクティブになります。サブスクライブを停止するには、subscription オブジェクトを解放します。
メッセージ検出ハンドラは、メッセージをパブリッシュしている付近のデバイスが検出されると呼び出されます。メッセージ損失ハンドラは、メッセージが観測されなくなると呼び出されます(デバイスが範囲外になったか、メッセージを公開しなくなったとき)。
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 経由で匿名トークンをアドバタイズします」などです。
場合によっては、メディアの一方だけをアプリで使用すればよく、そのメディアでブロードキャストとスキャンの両方を行う必要がない場合もあります。
たとえば、音声をブロードキャストするセットトップ ボックスに接続するように設計されたアプリは、音声をスキャンするだけで検出できます。次のスニペットは、検出のための音声スキャンのみを使用して、そのセットトップ ボックスにメッセージを公開する方法を示しています。
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
Nearby に影響するユーザー設定のトラッキング
ユーザーがマイクの権限または 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
}
})
Nearby 権限ダイアログのオーバーライド
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... }