Nearby Messages API là một API phát hành-đăng ký cho phép các thiết bị ở gần nhau trao đổi các tải trọng dữ liệu nhỏ. Sau khi một thiết bị phát hành một thông báo, các thiết bị lân cận có thể nhận được thông báo đó. Bạn nên giữ kích thước thông báo ở mức khá nhỏ để duy trì hiệu suất tốt. Dịch vụ này không dùng để trao đổi các đối tượng lớn hơn như ảnh và video.
Nhóm thiết bị ở gần được xác định bằng cách trao đổi mã thông báo nhỏ qua Bluetooth và âm thanh gần siêu âm (không nghe được). Khi phát hiện một mã thông báo từ một thiết bị ở gần, thiết bị sẽ gửi mã thông báo đó đến máy chủ Thông báo lân cận để xác thực và kiểm tra xem có thông báo nào cần gửi cho nhóm gói thuê bao hiện tại của ứng dụng hay không.
Ứng dụng có thể kiểm soát tập hợp các phương tiện dùng để khám phá thiết bị và liệu các phương tiện đó có được dùng để truyền phát mã thông báo và/hoặc quét mã thông báo hay không. Theo mặc định, việc truyền tin và quét được thực hiện trên tất cả các phương tiện. Để khám phá trên một tập hợp con hoặc phương tiện và để kiểm soát việc truyền tin hay quét, bạn phải truyền các tham số bổ sung khi tạo ấn bản và gói thuê bao.
Thư viện này chạy trên iOS 7 trở lên và xây dựng bằng SDK iOS 8.
Tạo trình quản lý thông báo
Mã này tạo một đối tượng trình quản lý thông báo, cho phép bạn phát hành và đăng ký. Việc trao đổi thông báo không được xác thực, vì vậy, bạn phải cung cấp khoá API công khai cho iOS. Bạn có thể tạo một ứng dụng bằng cách sử dụng mục nhập Google Developers Console cho dự án của mình.
Objective-C
#import <GNSMessages.h>
GNSMessageManager *messageManager =
[[GNSMessageManager alloc] initWithAPIKey:@"API_KEY"];
Swift
let messageManager = GNSMessageManager(APIKey: "API_KEY")
Xuất bản thông báo
Đoạn mã này minh hoạ việc phát hành một thông báo chứa tên. Ấn bản sẽ hoạt động miễn là đối tượng ấn bản tồn tại. Để ngừng phát hành, hãy giải phóng đối tượng ấn bản.
Objective-C
id<GNSPublication> publication =
[messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]];
Swift
let publication =
messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)))
Đăng ký nhận tin nhắn
Đoạn mã này minh hoạ việc đăng ký tất cả tên do đoạn mã xuất bản trước chia sẻ. Gói thuê bao sẽ hoạt động miễn là các đối tượng trong gói thuê bao vẫn tồn tại. Để ngừng đăng ký, hãy giải phóng đối tượng đăng ký.
Trình xử lý tin nhắn tìm thấy được gọi khi phát hiện các thiết bị lân cận đang phát hành tin nhắn. Trình xử lý thông báo bị mất được gọi khi không còn quan sát thấy thông báo nào (thiết bị đã hết phạm vi hoặc không còn phát hành thông báo).
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
})
Phương tiện khám phá
Theo mặc định, cả hai phương tiện (âm thanh và Bluetooth) sẽ được dùng để khám phá các thiết bị ở gần và cả hai phương tiện sẽ truyền tin và quét. Trong một số trường hợp, bạn bắt buộc phải thêm các mục sau vào Info.plist
của ứng dụng:
Nếu ứng dụng của bạn quét bằng âm thanh, hãy thêm
NSMicrophoneUsageDescription
. Đây là một chuỗi mô tả lý do bạn sẽ sử dụng micrô. Ví dụ: "Microphone sẽ nghe các mã thông báo ẩn danh từ các thiết bị lân cận".Nếu ứng dụng của bạn truyền tin bằng BLE, hãy thêm
NSBluetoothPeripheralUsageDescription
. Đây là một chuỗi mô tả lý do bạn sẽ quảng cáo trên BLE. Ví dụ: "Một mã thông báo ẩn danh được quảng cáo qua Bluetooth để khám phá các thiết bị ở gần".
Trong một số trường hợp, ứng dụng của bạn có thể chỉ cần sử dụng một trong các phương tiện và có thể không cần thực hiện cả việc truyền tin và quét trên phương tiện đó.
Ví dụ: một ứng dụng được thiết kế để kết nối với hộp giải mã truyền hình đang phát sóng qua âm thanh chỉ cần quét qua âm thanh để phát hiện hộp giải mã truyền hình đó. Đoạn mã sau đây cho biết cách phát hành thông báo đến hộp giải mã đó chỉ bằng cách quét âm thanh để khám phá:
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
})
})
Bật tính năng ghi nhật ký gỡ lỗi
Tính năng ghi nhật ký gỡ lỗi sẽ in các sự kiện nội bộ quan trọng vào bảng điều khiển. Tính năng này có thể giúp bạn theo dõi các vấn đề có thể gặp phải khi tích hợp Tin nhắn lân cận vào ứng dụng. Chúng tôi sẽ yêu cầu bạn cung cấp các nhật ký này nếu bạn liên hệ với chúng tôi để được hỗ trợ kỹ thuật.
Bạn nên bật tính năng này trước khi tạo trình quản lý thông báo. Đoạn mã này cho biết cách bật tính năng ghi nhật ký gỡ lỗi:
Objective-C
[GNSMessageManager setDebugLoggingEnabled:YES];
Swift
GNSMessageManager.setDebugLoggingEnabled(true)
Theo dõi trạng thái quyền truy cập Nearby
Bạn phải có sự đồng ý của người dùng để bật tính năng phát hiện thiết bị. Điều này được thể hiện bằng trạng thái quyền lân cận. Trong lệnh gọi đầu tiên để tạo ấn bản hoặc gói thuê bao, người dùng sẽ thấy một hộp thoại yêu cầu đồng ý. Nếu người dùng không đồng ý, tính năng phát hiện thiết bị sẽ không hoạt động. Trong trường hợp này, ứng dụng của bạn sẽ hiển thị thông báo nhắc người dùng rằng tính năng phát hiện thiết bị đã bị tắt. Trạng thái quyền được lưu trữ trong NSUserDefaults
.
Đoạn mã sau đây minh hoạ cách đăng ký trạng thái quyền. Trình xử lý thay đổi trạng thái quyền được gọi bất cứ khi nào trạng thái thay đổi và không được gọi lần đầu tiên cho đến khi người dùng cấp hoặc từ chối quyền. Giải phóng đối tượng quyền để ngừng đăng ký.
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
})
Ứng dụng của bạn có thể cung cấp cách để người dùng thay đổi trạng thái quyền; ví dụ: bằng cách sử dụng nút bật/tắt trên trang cài đặt.
Sau đây là ví dụ về cách lấy và đặt trạng thái quyền.
Objective-C
BOOL permissionState = [GNSPermission isGranted];
[GNSPermission setGranted:!permissionState]; // toggle the state
Swift
let permissionState = GNSPermission.isGranted()
GNSPermission.setGranted(!permissionState) // toggle the state
Theo dõi các chế độ cài đặt của người dùng ảnh hưởng đến tính năng Chia sẻ lân cận
Nếu người dùng từ chối cấp quyền truy cập micrô, từ chối cấp quyền truy cập Bluetooth hoặc tắt Bluetooth, thì tính năng Lân cận sẽ hoạt động kém hiệu quả hoặc có thể không hoạt động. Trong những trường hợp này, ứng dụng của bạn sẽ hiển thị thông báo để cảnh báo người dùng rằng các hoạt động của tính năng Gần đây đang bị cản trở. Đoạn mã sau đây cho biết cách theo dõi trạng thái của các chế độ cài đặt người dùng này bằng cách truyền trình xử lý khi tạo trình quản lý thông báo:
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
}
})
Ghi đè hộp thoại cấp quyền cho tính năng Thiết bị ở gần
Tuỳ thuộc vào các tham số mà bạn truyền vào ấn bản và gói thuê bao, iOS có thể yêu cầu nhiều quyền trước khi cho phép tính năng Gần đây hoạt động. Ví dụ: chiến lược mặc định sẽ theo dõi dữ liệu được truyền trên âm thanh gần siêu âm, vì vậy, iOS sẽ yêu cầu quyền sử dụng micrô. Trong những trường hợp này, tính năng Gần đây sẽ hiển thị hộp thoại "trước chuyến bay" giải thích lý do người dùng được yêu cầu cấp quyền.
Nếu bạn muốn cung cấp hộp thoại "trước chuyến bay" tuỳ chỉnh, hãy đặt thông số permissionRequestHandler
thành một khối tuỳ chỉnh trong thông số ấn bản hoặc thông số thuê bao. Khối tuỳ chỉnh của bạn phải gọi khối permissionHandler
sau khi người dùng phản hồi. Đoạn mã sau đây cho biết cách thực hiện việc này cho một ấn bản:
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.
}
})
Thao tác ở chế độ nền
Các ấn bản và gói thuê bao sử dụng BLE để khám phá thiết bị có thể hoạt động ở chế độ nền. Dưới đây là một số điều bạn cần lưu ý khi quyết định sử dụng chế độ nền:
- Các thao tác trong nền chỉ được sử dụng phương tiện BLE; không hỗ trợ âm thanh.
- Có thêm chi phí pin cho BLE ở chế độ nền. Chi phí này thấp, nhưng bạn nên đo lường trước khi quyết định sử dụng chế độ nền.
- iOS sẽ yêu cầu người dùng cấp quyền để quảng cáo qua BLE ở chế độ nền.
Để thêm chế độ nền vào một ấn bản hoặc gói thuê bao, hãy làm theo các bước bổ sung sau:
Bật chế độ nền và chỉ BLE trong ấn bản hoặc gói thuê bao bằng cách truyền vào một đối tượng
GNSStrategy
được định cấu hình đúng cách. Đoạn mã sau đây cho biết cách thực hiện việc này cho một gói thuê bao: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 }) })
Thêm các mục này vào
Info.plist
của ứng dụng:Mục
UIBackgroundModes
:bluetooth-central
để quét BLE ở chế độ nền. Chỉ cần thiết khi chế độ khám phá bao gồm cả tính năng quét; tính năng này được bật theo mặc định.bluetooth-peripheral
để quảng cáo BLE ở chế độ nền. Chỉ cần thiết khi chế độ khám phá bao gồm cả tính năng truyền tin; theo mặc định, chế độ này sẽ bao gồm tính năng truyền tin.
Chuỗi
NSBluetoothPeripheralUsageDescription
mô tả lý do bạn sẽ quảng cáo trên BLE. Ví dụ: "Một mã thông báo ẩn danh được quảng cáo qua Bluetooth để khám phá các thiết bị ở gần". Hãy xem tài liệu của Apple để biết thông tin chi tiết.
Hệ thống có thể huỷ bỏ ứng dụng của bạn bất cứ lúc nào khi ứng dụng đang chạy ở chế độ nền. Nếu chế độ nền là chế độ cài đặt mà người dùng có thể bật hoặc tắt, thì ứng dụng của bạn sẽ thực hiện những việc sau:
- Lưu giá trị chế độ nền vào
NSUserDefaults
bất cứ khi nào người dùng thay đổi giá trị đó. - Khi khởi động, hãy đọc tệp này từ
NSUserDefaults
và khôi phục các ấn bản và/hoặc gói thuê bao Nearby nếu chế độ nền được bật.
- Lưu giá trị chế độ nền vào
Thông báo ở chế độ nền
Nếu muốn ứng dụng thông báo cho người dùng khi một gói thuê bao nhận được thông báo trong nền, bạn có thể sử dụng thông báo cục bộ.
Hãy làm theo các bước sau để thêm các thành phần này vào ứng dụng:
Đăng ký nhận thông báo cục bộ khi khởi động:
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))
Gửi thông báo cục bộ trong trình xử lý tìm thấy tin nhắn của gói thuê bao:
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... }