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
})
})
啟用偵錯記錄功能
偵錯記錄會將重要內部事件列印到控制台,這有助於追蹤在將附近訊息整合至應用程式時可能遇到的問題。如果您向我們洽詢技術支援,我們會要求提供這些記錄。
您應先啟用這項功能,再建立訊息管理工具。以下程式碼片段說明如何啟用偵錯記錄:
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-only。下列程式碼片段說明如何為訂閱項目執行這項操作: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... }