النشر والاشتراك

واجهة برمجة التطبيقات لتطبيق "الرسائل عن قرب" هي واجهة برمجة تطبيقات لنشر الاشتراك تتيح للأجهزة المجاورة تبادل أحمال صغيرة من البيانات. بعد أن ينشر الجهاز رسالة، يمكن للأجهزة المجاورة تلقّي الرسالة. يجب أن يظل حجم الرسالة صغيرًا نسبيًا للحفاظ على الأداء الجيد. لم يتم تصميم هذه الخدمة لتبادل عناصر أكبر حجمًا مثل الصور والفيديوهات.

يتم تحديد مجموعة الأجهزة المجاورة من خلال تبادل الرموز الصغيرة الصغيرة عبر البلوتوث والصوت شبه السمعي (غير المسموع). عندما يرصد جهاز رمزًا مميزًا من جهاز مجاور، يرسل الرمز إلى خادم "الرسائل المجاورة" للتحقّق من صحته ومعرفة ما إذا كانت هناك أي رسائل يمكن تسليمها للمجموعة الحالية من اشتراكات التطبيق.

يمكن للتطبيق التحكم في مجموعة الوسائط المستخدمة لاكتشاف الجهاز، وما إذا كانت الوسائط تُستخدَم لبث الرموز المميزة و/أو البحث عن الرموز المميزة. يتم تلقائيًا البث والمسح الضوئي على جميع الوسائط. لاكتشاف مجموعة فرعية أو وسائط والتحكّم في البث أو المسح الضوئي، عليك ضبط معلَمات إضافية عند إنشاء جهات النشر والاشتراكات.

تعمل هذه المكتبة على iOS 7 والإصدارات الأحدث، ويتم إنشاؤها باستخدام iOS 8 SDK.

إنشاء مدير رسائل

يؤدي هذا الرمز إلى إنشاء كائن مدير الرسائل الذي يتيح لك النشر والاشتراك. لم تتم مصادقة تبادل الرسائل، لذا يجب عليك تقديم مفتاح واجهة برمجة تطبيقات عام لنظام التشغيل 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)))

الاشتراك في الرسائل

يوضح مقتطف الرمز هذا الاشتراك في جميع الأسماء التي تمت مشاركتها من خلال مقتطف جهة النشر السابق. يبقى الاشتراك نشطًا ما دامت كائنات الاشتراك متوفرة. لإيقاف الاشتراك، حرر كائن الاشتراك.

يتم استدعاء معالِج الرسالة التي تم العثور عليها عند اكتشاف الأجهزة المجاورة التي تنشر الرسائل. يتم استدعاء المعالِج المفقود للرسائل عند توقُّف رصد رسالة (عندما يكون الجهاز خارج النطاق أو لم يعُد ينشر الرسالة).

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

وسائط استكشاف المحتوى

وبشكل تلقائي، سيتم استخدام الوسيطَين (الصوت والبلوتوث) لاكتشاف الأجهزة المجاورة، وسيتم بث المحتوى والبحث عنه معًا. في بعض الحالات، يجب إضافة الإدخالات التالية إلى Info.plist في تطبيقك:

  • إذا كان تطبيقك يبحث باستخدام الصوت، يمكنك إضافة NSMicrophoneUsageDescription، وهي سلسلة توضّح سبب استخدامك للميكروفون. على سبيل المثال، "يستمع الميكروفون إلى الرموز المميزة المجهولة من الأجهزة المجاورة".

  • إذا كان تطبيقك يبث باستخدام تقنية BLE، أضِف NSBluetoothPeripheralUsageDescription، وهي سلسلة توضّح سبب الإعلان على تقنية BLE. على سبيل المثال، "يتم الإعلان عن رمز مميز مجهول عبر البلوتوث لاكتشاف الأجهزة المجاورة".

في بعض الحالات، قد يحتاج تطبيقك إلى استخدام وسيط واحد فقط، وقد لا يحتاج إلى البث أو البحث باستخدام هذا الوسيط.

على سبيل المثال، التطبيق المصمم للاتصال بجهاز فكّ ترميز المحتوى التلفزيوني يبث على الصوت يحتاج فقط إلى البحث عنه باستخدام الصوت لاكتشافه. يوضح المقتطف التالي كيفية نشر رسالة على جهاز الاستقبال باستخدام المسح الصوتي فقط لاكتشافها:

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

تفعيل تسجيل تصحيح الأخطاء

يؤدي تسجيل تصحيح الأخطاء إلى طباعة الأحداث الداخلية المهمة في وحدة التحكم، والتي يمكن أن تكون مفيدة في تعقب المشكلات التي قد تواجهها عند دمج رسائل "الأجهزة المجاورة" في تطبيقك. وسنطلب الحصول على هذه السجلات في حال تواصلك معنا للحصول على الدعم الفني.

عليك تفعيله قبل إنشاء مدير الرسائل. يعرض مقتطف الرمز هذا كيفية تفعيل تسجيل تصحيح الأخطاء:

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

تتبُّع إعدادات المستخدم التي تؤثر في ميزة "الأجهزة المجاورة"

إذا رفض المستخدم الحصول على إذن استخدام الميكروفون، أو رفض منح الإذن باستخدام البلوتوث، أو أوقف ميزة البلوتوث، لن تعمل ميزة "الأجهزة المجاورة" أيضًا، أو قد لا تعمل على الإطلاق. في هذه الحالات، من المفترض أن يعرض تطبيقك رسالة لتنبيه المستخدم بأنّه يتم عرقلة عمليات الأجهزة المجاورة. ويوضّح المقتطف التالي كيفية تتبُّع حالة إعدادات المستخدم هذه من خلال تمرير المعالجات عند إنشاء مدير الرسائل:

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 الإذن باستخدام الميكروفون. وفي هذه الحالات، ستعرض ميزة "الأجهزة المجاورة" مربع حوار "ما قبل التنفيذ" يشرح سبب مطالبة المستخدم بمنح الإذن.

إذا أردت توفير مربّع حوار مخصّص "للطلب المُسبَق"، اضبط المعلَمة 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. على سبيل المثال، "يتم الإعلان عن رمز مميز مجهول عبر البلوتوث لاكتشاف الأجهزة المجاورة". اطّلِع على مستندات 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))
    

  • يمكنك إرسال إشعار محلي في المعالج الذي تم العثور على الرسائل له في اشتراكك:

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