انتشار و اشتراک

‫Nearby Messages API یک میانای برنامه‌سازی کاربردی انتشار-اشتراک است که به دستگاه‌های اطراف اجازه می‌دهد محموله‌های کوچک داده را مبادله کنند. وقتی دستگاهی پیامی را منتشر می‌کند، دستگاه‌های اطراف می‌توانند پیام را دریافت کنند. اندازه پیام باید نسبتاً کوچک باشد تا عملکرد خوب حفظ شود. این سرویس برای تبادل اشیای بزرگ‌تر مثل عکس و ویدیو طراحی نشده است.

مجموعه دستگاه‌های اطراف با تبادل نشان‌های کوچک ازطریق بلوتوث و صدای فراصوت نزدیک (ناشنیدنی) تعیین می‌شود. وقتی دستگاهی نشانه‌ای از دستگاهی در اطراف شناسایی می‌کند، نشانه را برای سرور «پیام‌های اطراف» ارسال می‌کند تا آن را تأیید کند و بررسی کند که آیا پیامی برای مجموعه اشتراک‌های فعلی برنامه وجود دارد یا نه.

برنامه می‌تواند مجموعه رسانه‌های مورداستفاده برای شناسایی دستگاه را کنترل کند و مشخص کند که آیا از رسانه‌ها برای همه‌فرستی نشان‌ها و/یا اسکن کردن نشان‌ها استفاده شود یا نه. به‌طور پیش‌فرض، پخش و اسکن در همه رسانه‌ها انجام می‌شود. برای انجام اکتشاف در زیرمجموعه یا رسانه‌ها، و برای کنترل اینکه پخش یا اسکن شود، باید هنگام ایجاد انتشارات و اشتراک‌ها، پارامترهای بیشتری را ارسال کنید.

این کتابخانه در iOS 7 و بالاتر اجرا می‌شود و با iOS 8 SDK ساخته می‌شود.

درحال ایجاد مدیر پیام

این کد یک شیء مدیر پیام ایجاد می‌کند که به شما امکان می‌دهد منتشر و مشترک شوید. تبادل پیام اصالت‌سنجی نشده است، بنابراین باید کلید میانای برنامه‌سازی کاربردی عمومی برای iOS ارائه دهید. می‌توانید بااستفاده از ورودی کنسول توسعه‌دهندگان Google برای پروژه‌تان ایجاد کنید.

آبجکتیو-سی

#import <GNSMessages.h>

GNSMessageManager *messageManager =
    [[GNSMessageManager alloc] initWithAPIKey:@"API_KEY"];

Swift

let messageManager = GNSMessageManager(APIKey: "API_KEY")

انتشار پیام

این تکه‌کد نحوه انتشار پیامی حاوی نام را نشان می‌دهد. تا زمانی که شیء نشریه وجود داشته باشد، نشریه فعال است. برای متوقف کردن انتشار، شیء نشریه را آزاد کنید.

آبجکتیو-سی

id<GNSPublication> publication =
    [messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]];

Swift

let publication =
    messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)))

درحال مشترک شدن در پیام‌ها

این تکه‌کد اشتراک در همه نام‌های هم‌رسانی‌شده توسط تکه کد انتشار قبلی را نشان می‌دهد. تا زمانی که شیء اشتراک وجود داشته باشد، اشتراک فعال است. برای توقف اشتراک، شیء اشتراک را رها کنید.

وقتی دستگاه‌های اطراف که پیام منتشر می‌کنند شناسایی می‌شوند، کارپرداز پیام پیدا‌شده فراخوانی می‌شود. وقتی پیامی دیگر مشاهده نمی‌شود (دستگاه از محدوده خارج شده است یا دیگر پیام را منتشر نمی‌کند)، کنترل‌کننده پیام ازدست‌رفته فراخوانده می‌شود.

آبجکتیو-سی

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 را اضافه کنید که رشته‌ای است که توضیح می‌دهد چرا از میکروفون استفاده خواهید کرد. برای مثال، «میکروفون به‌دنبال نشان‌های ناشناس از دستگاه‌های اطراف است.»

  • اگر برنامه‌تان بااستفاده از «بلوتوث کم‌مصرف» همه‌فرستی می‌کند، NSBluetoothPeripheralUsageDescription را اضافه کنید، که رشته‌ای است که توضیح می‌دهد چرا بااستفاده از «بلوتوث کم‌مصرف» تبلیغ خواهید کرد. برای مثال، «یک کد ناشناس ازطریق بلوتوث تبلیغ می‌شود تا دستگاه‌های اطراف را پیدا کند.»

در برخی موارد، ممکن است برنامه شما فقط به استفاده از یکی از رسانه‌ها نیاز داشته باشد و ممکن است نیازی به انجام هم‌زمان همه‌فرستی و اسکن در آن رسانه نداشته باشد.

برای مثال، برنامه‌ای که برای اتصال به جعبه تنظیم طراحی شده است و فقط صدا پخش می‌کند، برای شناسایی آن باید صدا را اسکن کند. قطعه زیر نشان می‌دهد که چگونه می‌توان پیامی را در آن گیرنده دیجیتال فقط بااستفاده از اسکن صوتی برای کاوش منتشر کرد:

آبجکتیو-سی

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» در برنامه‌تان با آن‌ها مواجه شوید مفید باشد. اگر برای پشتیبانی فنی با ما تماس بگیرید، این گزارش‌ها را درخواست خواهیم کرد.

باید آن را قبل‌از ایجاد مدیر پیام فعال کنید. این تکه‌کد نحوه فعال کردن گزارش اشکال‌زدایی را نشان می‌دهد:

آبجکتیو-سی

[GNSMessageManager setDebugLoggingEnabled:YES];

Swift

GNSMessageManager.setDebugLoggingEnabled(true)

ردیابی وضعیت اجازه «اطراف»

برای فعال کردن شناسایی دستگاه، رضایت کاربر لازم است. این موضوع با وضعیت اجازه «نزدیک» نشان داده می‌شود. در اولین تماس برای ایجاد نشریه یا اشتراک، چارگوش گفتگوی موافقت به کاربر نشان داده می‌شود. اگر کاربر موافقت نکند، «یافتن دستگاه» کار نخواهد کرد. در این مورد، برنامه شما باید پیامی نمایش دهد تا به کاربر یادآوری کند که شناسایی دستگاه غیرفعال است. وضعیت اجازه در NSUserDefaults ذخیره می‌شود.

تکه کد زیر نحوه مشترک شدن در وضعیت اجازه را نشان می‌دهد. هرگاه وضعیت تغییر کند، گرداننده تغییر وضعیت اجازه فراخوانی می‌شود و تا زمانی که کاربر اجازه را اعطا یا رد نکرده باشد، برای اولین‌بار فراخوانی نمی‌شود. برای توقف اشتراک، شیء اجازه را منتشر کنید.

آبجکتیو-سی

GNSPermission *nearbyPermission = [[GNSPermission alloc] initWithChangedHandler:^(BOOL granted) {
  // Update the UI here
}];

Swift

let nearbyPermission = GNSPermission(changedHandler: { (granted: Bool) in
  // Update the UI here
})

برنامه شما می‌تواند روشی برای کاربر فراهم کند تا وضعیت اجازه را تغییر دهد؛ برای مثال، بااستفاده از کلید تغییر وضعیت در صفحه تنظیمات.

در اینجا نمونه‌ای از نحوه دریافت و تنظیم وضعیت اجازه آورده شده است.

آبجکتیو-سی

BOOL permissionState = [GNSPermission isGranted];
[GNSPermission setGranted:!permissionState];  // toggle the state

Swift

let permissionState = GNSPermission.isGranted()
GNSPermission.setGranted(!permissionState)  // toggle the state

پیگیری تنظیمات کاربر که بر «اطراف» تأثیر می‌گذارد

اگر کاربر اجازه میکروفون یا اجازه بلوتوث را رد کرده باشد، یا بلوتوث را خاموش کرده باشد، «اطراف» به‌خوبی کار نخواهد کرد یا ممکن است اصلاً کار نکند. برنامه شما باید در این موارد پیامی نشان دهد و به کاربر هشدار دهد که عملیات «اطراف» با مانع مواجه شده است. تکه‌کد زیر نشان می‌دهد که چگونه با عبور دادن کنترل‌کننده‌ها هنگام ایجاد مدیر پیام، وضعیت این تنظیمات کاربر را پیگیری کنید:

آبجکتیو-سی

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 برای استفاده از میکروفون اجازه می‌خواهد. در این موارد، «اطراف» گفتگوی «پیش‌پرواز» را نمایش می‌دهد که توضیح می‌دهد چرا از کاربر خواسته می‌شود اجازه بدهد.

اگر می‌خواهید کادر گفتگوی «پیش‌پرواز» سفارشی ارائه دهید، پارامتر permissionRequestHandler را روی بلوک سفارشی در پارامترهای انتشارات یا اشتراک تنظیم کنید. واحد سفارشی‌تان باید پس‌از پاسخ کاربر، permissionHandler واحد را فراخوانی کند. قطعه کد زیر نحوه انجام این کار را برای یک انتشارات نشان می‌دهد:

آبجکتیو-سی

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 استفاده کند؛ از صدا پشتیبانی نمی‌شود.
  • برای «بلوتوث کم‌مصرف» پس‌زمینه‌ای هزینه باتری اضافه می‌شود. هزینه پایین است، اما قبل‌از تصمیم‌گیری برای استفاده از حالت پس‌زمینه باید آن را اندازه‌گیری کنید.
  • iOS از کاربر برای تبلیغ ازطریق BLE در پس‌زمینه اجازه می‌خواهد.

برای افزودن حالت پس‌زمینه به یک نشریه یا اشتراک، این مراحل اضافی را دنبال کنید:

  • با ارسال شیء GNSStrategy که به‌درستی پیکربندی شده است، حالت پس‌زمینه و BLE-only را در انتشار یا اشتراک خود فعال کنید. تکه کد زیر نحوه انجام این کار را برای اشتراک نشان می‌دهد:

    آبجکتیو-سی

    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 را بازیابی کنید.

اعلان‌های پس‌زمینه

اگر می‌خواهید برنامه‌تان وقتی اشتراکی در پس‌زمینه پیام دریافت می‌کند به کاربر اطلاع دهد، می‌توانید از اعلان‌های محلی استفاده کنید.

برای افزودن آن‌ها به برنامه‌تان، این مراحل را دنبال کنید:

  • ثبت‌نام برای اعلان‌های محلی هنگام راه‌اندازی:

    آبجکتیو-سی

    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))
    

  • اعلان محلی را در مدیریت‌کننده پیام یافت‌شده اشتراکتان ارسال کنید:

    آبجکتیو-سی

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