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

API پیام‌های نزدیک، یک API انتشار-اشتراک است که به دستگاه‌های مجاور اجازه می‌دهد حجم کمی از داده‌ها را تبادل کنند. به محض اینکه یک دستگاه پیامی را منتشر می‌کند، دستگاه‌های مجاور می‌توانند آن پیام را دریافت کنند. اندازه پیام باید نسبتاً کوچک نگه داشته شود تا عملکرد خوبی حفظ شود. این سرویس برای تبادل اشیاء بزرگتر مانند عکس و فیلم در نظر گرفته نشده است.

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

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

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

ایجاد مدیریت پیام‌ها

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

هدف-سی

#import <GNSMessages.h>

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

سویفت

let messageManager = GNSMessageManager(APIKey: "API_KEY")

انتشار یک پیام

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

هدف-سی

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

سویفت

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
    }];

سویفت

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 تبلیغ خواهید کرد. برای مثال، "یک توکن ناشناس از طریق بلوتوث برای کشف دستگاه‌های مجاور تبلیغ می‌شود."

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

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

هدف-سی

id<GNSPublication> publication = [messageManager publicationWithMessage:message
    paramsBlock:^(GNSPublicationParams *params) {
      params.strategy = [GNSStrategy strategyWithParamsBlock:^(GNSStrategyParams *params) {
        params.discoveryMediums = kGNSDiscoveryMediumsAudio;
        params.discoveryMode = kGNSDiscoveryModeScan;
      }];
    }];

سویفت

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

فعال کردن ثبت گزارش اشکال‌زدایی

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

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

هدف-سی

[GNSMessageManager setDebugLoggingEnabled:YES];

سویفت

GNSMessageManager.setDebugLoggingEnabled(true)

ردیابی وضعیت مجوز Nearby

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

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

هدف-سی

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

سویفت

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

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

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

هدف-سی

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

سویفت

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

ردیابی تنظیمات کاربر که بر Nearby تأثیر می‌گذارند

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

هدف-سی

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
         };
}];

سویفت

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

لغو کردن پنجره‌ی مجوز Nearby

بسته به پارامترهایی که به نشریات و اشتراک‌های خود وارد می‌کنید، iOS ممکن است قبل از اجازه دادن به Nearby برای عملکرد، مجوزهای مختلفی را درخواست کند. به عنوان مثال، استراتژی پیش‌فرض به داده‌های منتقل شده با صدای نزدیک به فراصوت گوش می‌دهد، بنابراین iOS برای استفاده از میکروفون درخواست اجازه می‌کند. در این موارد، Nearby یک کادر محاوره‌ای "پیش از پرواز" نشان می‌دهد که توضیح می‌دهد چرا از کاربر خواسته شده است که اجازه دهد.

اگر می‌خواهید یک دیالوگ "پیش از شروع" سفارشی ارائه دهید، پارامتر 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.
                                 };
                               }];

سویفت

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 را در انتشار یا اشتراک خود فعال کنید. قطعه کد زیر نحوه انجام این کار را برای یک اشتراک نشان می‌دهد:

    هدف-سی

    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;
          }];
        }];
    

    سویفت

    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 تبلیغ خواهید کرد. برای مثال، "یک توکن ناشناس از طریق بلوتوث برای کشف دستگاه‌های نزدیک تبلیغ می‌شود." برای جزئیات بیشتر به مستندات اپل مراجعه کنید.

  • برنامه شما می‌تواند در هر زمانی توسط سیستم در پس‌زمینه بسته شود. اگر حالت پس‌زمینه تنظیمی است که می‌تواند توسط کاربر فعال یا غیرفعال شود، برنامه شما باید موارد زیر را انجام دهد:

    • هر زمان که کاربر مقدار حالت پس‌زمینه را تغییر دهد، آن را در NSUserDefaults ذخیره می‌کند.
    • در هنگام راه‌اندازی، آن را از NSUserDefaults بخوانید و اگر حالت پس‌زمینه فعال است، نشریات و/یا اشتراک‌های Nearby را بازیابی کنید.

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

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

برای اضافه کردن آنها به برنامه خود، این مراحل را دنبال کنید:

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

    هدف-سی

    if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
      [[UIApplication sharedApplication] registerUserNotificationSettings:
          [UIUserNotificationSettings settingsForTypes:
              UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound
                                            categories:nil]];
    }
    

    سویفت

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

    سویفت

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