Nearby Messages API 是一種發布訂閱 API,可讓鄰近裝置交換小型資料酬載。裝置發布訊息後,附近的裝置就能收到訊息。訊息大小應盡可能精簡,以維持良好效能。這項服務不適用於交換大型物件,例如相片和影片。
附近的裝置組合取決於透過藍牙和近超音波 (無聲) 音訊交換小型權杖。當裝置偵測到鄰近裝置提供的權杖時,就會將權杖傳送至 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
})
探索媒介
根據預設,系統會使用音訊和藍牙 (音訊和藍牙) 偵測鄰近裝置,而這兩種媒介都會廣播及掃描。在某些情況下,您必須在應用程式的 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
})
})
啟用偵錯記錄功能
偵錯記錄功能會將重要的內部事件輸出到主控台,方便您追蹤在應用程式中整合 Nearby Messages 時可能會遇到的問題。如果您向我們尋求技術支援,我們就會詢問這些記錄。
請先啟用這項服務,再建立訊息管理員。下列程式碼片段說明如何啟用偵錯記錄功能:
Objective-C
[GNSMessageManager setDebugLoggingEnabled:YES];
Swift
GNSMessageManager.setDebugLoggingEnabled(true)
追蹤鄰近分享權限狀態
如要啟用裝置探索功能,您必須取得使用者同意。這是以「鄰近分享」權限狀態表示。第一次呼叫建立發布項目或訂閱項目時,系統會顯示同意聲明對話方塊。如果使用者未同意,裝置探索功能就無法運作。在此情況下,應用程式應顯示訊息,提醒使用者裝置探索功能已停用。權限狀態會儲存在 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 的作業正在阻礙。下列程式碼片段說明如何在建立訊息管理員時傳遞處理常式,以追蹤這些使用者設定的狀態:
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 在背景放送廣告。只有在探索模式包含廣播功能時才需要使用,預設為啟用。
NSBluetoothPeripheralUsageDescription
字串,說明您會在 BLE 上放送廣告的原因。例如:「已透過藍牙宣傳匿名權杖,以便探索鄰近裝置」。詳情請參閱 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... }