פרסום והרשמה

‫Nearby Messages API הוא ממשק API של פרסום והרשמה, שמאפשר למכשירים קרובים להחליף ביניהם נתונים בכמויות קטנות. אחרי שמכשיר מפרסם הודעה, מכשירים קרובים יכולים לקבל אותה. כדי לשמור על רמת ביצועים טובה, חשוב לשמור על גודל הודעה קטן יחסית. השירות הזה לא מיועד להעברת אובייקטים גדולים יותר כמו תמונות וסרטונים.

קבוצת המכשירים בקרבת מקום נקבעת על ידי חילופי טוקנים קטנים באמצעות Bluetooth ואודיו בתדרים קרובים לאולטרסוניים (לא נשמע). כשמכשיר מזהה טוקן ממכשיר בקרבת מקום, הוא שולח את הטוקן לשרת Nearby Messages כדי לאמת אותו ולבדוק אם יש הודעות למסירה עבור קבוצת המינויים הנוכחית של האפליקציה.

אפליקציה יכולה לשלוט בקבוצת האמצעים שמשמשים לגילוי מכשירים, ולקבוע אם האמצעים משמשים לשידור אסימונים או לסריקת אסימונים. כברירת מחדל, השידור והסריקה מתבצעים בכל המדיומים. כדי לבצע גילוי של קבוצת משנה או של אמצעי תקשורת, וכדי לשלוט בהפצה או בסריקה, צריך להעביר פרמטרים נוספים כשיוצרים פרסומים ומינויים.

הספרייה הזו פועלת ב-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 של ההודעה שנמצאה נקרא כשמזוהים מכשירים בקרבת מקום שמפרסמים הודעות. הפונקציה לטיפול באובדן הודעות מופעלת כשההודעה לא נצפית יותר (המכשיר יצא מטווח הקליטה או שהוא כבר לא מפרסם את ההודעה).

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 שמתארת למה תשתמשו במיקרופון. לדוגמה, "המיקרופון מאזין לטוקנים אנונימיים ממכשירים סמוכים".

  • אם האפליקציה משדרת באמצעות 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)

מעקב אחרי מצב ההרשאה 'בקרבת מקום'

כדי להפעיל את האפשרות לאיתור מכשירים, נדרשת הסכמה מהמשתמש. הסטטוס הזה מצוין על ידי מצב ההרשאה 'בסביבה'. בשיחה הראשונה ליצירת פרסום או מינוי, מוצגת למשתמש תיבת דו-שיח להבעת הסכמה. אם המשתמשים לא יביעו הסכמה, גילוי המכשירים לא יפעל. במקרה כזה, האפליקציה צריכה להציג הודעה שתזכיר למשתמש שגילוי המכשיר מושבת. מצב ההרשאה מאוחסן ב-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

מעקב אחרי הגדרות משתמש שמשפיעות על שיתוף בקרבת מקום

אם המשתמש דחה את ההרשאה לשימוש במיקרופון, דחה את ההרשאה לשימוש ב-Bluetooth או השבית את ה-Bluetooth, יכול להיות שהתכונה 'שיתוף בקרבת מקום' לא תפעל בצורה תקינה, או שלא תפעל בכלל. במקרים כאלה, האפליקציה צריכה להציג הודעה שתתריע בפני המשתמש שהפעולות של Nearby מוגבלות. קטע הקוד הבא מראה איך לעקוב אחרי הסטטוס של הגדרות המשתמש האלה באמצעות העברת פונקציות handler כשיוצרים את מנהל ההודעות:

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 תתבקשו לתת הרשאות שונות לפני שתהיה אפשרות להשתמש בתכונה 'שיתוף עם מכשירים בקרבת מקום'. לדוגמה, אסטרטגיית ברירת המחדל מאזינה לנתונים שמועברים באודיו בתדרים קרובים לאולטרה-סוניים, ולכן מערכת 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 ברקע.

כדי להוסיף מצב רקע לפרסום או למינוי, צריך לבצע את השלבים הנוספים הבאים:

  • כדי להפעיל מצב רקע ו-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 entries:

      • 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...
    }