Nearby Messages API הוא ממשק API להרשמה לפרסום שמאפשר למכשירים בקרבת מקום ממירים מטענים ייעודיים (payloads) קטנים של נתונים. לאחר שמכשיר מפרסם הודעה, בקרבת מקום מכשירים יוכלו לקבל את ההודעה. גודל ההודעה צריך להיות קטן יחסית, עד לשמור על ביצועים טובים. שירות זה לא נועד להחלפת נתונים כמו תמונות וסרטונים.
קבוצת המכשירים בקרבת מקום נקבעת לפי החלפת אסימונים קטנים מעל Bluetooth ואודיו כמעט על-קולי (ללא קול). כשמכשיר מזהה אסימון ממכשיר בקרבת מקום, האסימון נשלח לשרת הודעות בקרבת מקום לאמת אותו ולבדוק אם יש הודעות כלשהן שאפשר לשלוח עבור קבוצת המינויים הנוכחית.
אפליקציה יכולה לשלוט בקבוצה של אמצעי המדיה המשמשים לגילוי מכשירים, וגם אם אמצעי ההגעה לאתר משמשים לשידור אסימונים ו/או לסריקת אסימונים. כברירת מחדל, השידור והסריקה נעשים בכל אמצעי המדיה. לבצע בקבוצת משנה או אמצעי הגעה לאתר, ולקבוע אם לשדר או לסרוק, חייבים להעביר פרמטרים נוספים כשיוצרים אתרי חדשות למינויים.
הספרייה הזו פועלת ב-iOS 7 ואילך, והיא מבוססת על iOS 8 SDK.
יצירת מנהל הודעות
הקוד הזה יוצר אובייקט של מנהל הודעות, שמאפשר לפרסם להירשם חילופי ההודעות לא מאומתים, ולכן עליך לספק מפתח API ציבורי ל-iOS. אפשר ליצור חשבון ב-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)))
הרשמה להודעות
קטע הקוד הזה מראה הרשמה לכל השמות ששותפו על ידי קטע הקוד של אתר החדשות הקודם. המינוי פעיל כל עוד קיימים אובייקטים מהמנויים. כדי להפסיק את ההרשמה, צריך לשחרר את המינוי לאובייקט.
ה-handler של ההודעה שנמצאה מופעל כשמכשירים בקרבת מקום מפרסמים הודעות מתגלות. מתבצעת קריאה ל-handler של ההודעה שאבדה כשההודעה היא לא מזוהה יותר (המכשיר יצא מהטווח או לא מפרסם יותר את הודעה).
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
})
אמצעי הגעה לאתר מסוג Discovery
כברירת מחדל, המערכת תשתמש בשני אמצעי ההגעה לאתר (אודיו ו-Bluetooth) כדי לאתר מכשירים בקרבת מקום.
ושני אמצעי המדיה ישודרו ויסרקו. במקרים מסוימים,
שנדרשת כדי להוסיף את הרשומות הבאות לInfo.plist
של האפליקציה:
אם האפליקציה סורקת באמצעות אודיו, צריך להוסיף את
NSMicrophoneUsageDescription
, כלומר מחרוזת שמתארת את הסיבה לשימוש במיקרופון. לדוגמה, "The המיקרופון מאזין לאסימונים אנונימיים ממכשירים קרובים."אם האפליקציה משדרת באמצעות 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 הודעות באפליקציה. נבקש את היומנים האלה אם תיצור איתנו קשר תמיכה טכנית.
צריך להפעיל אותו לפני שיוצרים מנהל הודעות. קטע הקוד מראה איך מפעילים רישום ביומן של ניפוי באגים:
Objective-C
[GNSMessageManager setDebugLoggingEnabled:YES];
Swift
GNSMessageManager.setDebugLoggingEnabled(true)
מעקב אחר מצב ההרשאה בקרבת מקום
נדרשת הסכמת המשתמשים כדי להפעיל גילוי מכשירים. הערך הזה מצוין באמצעות
מצב ההרשאה בקרבת מקום. בשיחה הראשונה ליצירת אתר חדשות או
של המינוי, מוצגת למשתמש תיבת דו-שיח להבעת הסכמה. אם המשתמש לא
הסכמה, גילוי המכשיר לא יפעל. במקרה כזה, האפליקציה צריכה להציג
כדי להזכיר למשתמש שגילוי המכשיר מושבת. ההרשאה
המצב מאוחסן בNSUserDefaults
.
קטע הקוד הבא מראה הרשמה למצב ההרשאה. ה-handler של שינוי מצב ההרשאה נקרא בכל פעם שהמצב משתנה, לא נשלחה קריאה בפעם הראשונה עד שהמשתמש נתן או דחה הרשאה. כדי להפסיק את ההרשמה, צריך לשחרר את אובייקט ההרשאה.
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, אם הוא לא יפעל כמו שצריך, או שהוא לא יפעל כלל. במקרים כאלה אמורה להופיע הודעה באפליקציה, להתריע למשתמש על הפעילות נפגעת. קטע הקוד הבא מראה איך לעקוב הסטטוס של הגדרות המשתמש האלה על ידי העברת handlers במהלך יצירת ההודעה Manager:
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 תבקש הרשאה להשתמש במיקרופון. במקרים כאלה, בקרבת מקום תוצג 'preflight' תיבת דו-שיח שמסבירה למה שואלים את המשתמש כדי להעניק הרשאה.
אם רוצים לספק 'קדם-הפעלה' בהתאמה אישית בתיבת הדו-שיח,
הפרמטר 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 ברקע.
כדי להוסיף מצב רקע לאתר חדשות או למינוי, פועלים לפי השלבים הנוספים הבאים שלבים:
הפעלת מצב רקע ו-BLE בלבד באתר החדשות או במינוי שלך עד העברת אובייקט
GNSStrategy
שהוגדר כראוי. קטע הקוד הבא מראים איך לעשות את זה למינוי: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. לדוגמה, "אסימון אנונימי הוא שפורסם באמצעות Bluetooth כדי לאתר מכשירים בקרבת מקום." צפייה מסמכי התיעוד של 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))
שולחים התראה מקומית ב-handler של המינוי שנמצא בהודעה:
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... }