Branddrop 1.0.1

Branddrop 1.0.1

Taylor Whitlatch维护。



Branddrop 1.0.1

  • 作者
  • BrandDrop

Cocoapods platforms GitHub top language Cocoapods GitHub commits since tagged version (branch) GitHub issues

Branddrop

BDLogo

基于位置的用户参与

增强您的应用。赋予您营销力。
这不是关于广告... 而是关于“个性化”

Branddrop平台通过位置基础的用户参与将品牌和消费者连接起来。我们的国际专利申请中的Visualmatic™软件是一个强大的营销工具,允许品牌在任何位置周围设置虚拟围栏,测量人流量,并在用户进入地理定位时通过个性化的消息与他们互动... 并通过查看用户在印象之后的去向有效地归因于营销活动的效率!

使用您的Branddrop账户创建地点(地理围栏区域)和消息(通知),向您的应用用户发送定制消息。

点击这里获取Branddrop账户

一旦客户至少建立一个地理围栏,BAKit SDK将利用任何智能设备的本地位置监控,确定何时用户进入所提到的地理围栏,并派发客户组成的个性化通知。


所需设置

  1. 您已将应用添加的Firebase项目。
  2. 一个Branddrop账户

创建Firebase项目

将Firebase Core和Firebase Messaging添加到您应用中

要使用Firebase Cloud Messaging,您必须创建一个Firebase项目。

创建相关Firebase项目后,您可以下载GoogleService-Info.plist并保留该文件,用于"CocoaPods"部分。

接收您的Branddrop应用密钥

  • 请将Firebase项目设置中“Service Accounts” -> “Firebase Admin SDK”下的Firebase密钥通过电子邮件发送到[email protected],他将回复您的AppKey。

安装BAKit SDK

  • 支持iOS 10以上,要求使用Swift 4.0。
  • 使用Xcode 9+进行构建,需要支持iPhone X和iOS 11。
  • 目前,SDK可通过CocoaPods或下载仓库并手动将SDK的源代码链接到项目中获取。

CocoaPods

  1. 设置CocoaPods
  2. 关闭/退出Xcode。
  3. 通过项目目录中的终端运行$ pod init
  4. 打开您刚刚创建的Podfile,并添加以下pod(见本节末尾的示例Podfile)。
    • pod 'Branddrop'
    • pod 'Firebase/Core', '~> 5.0'
    • pod 'Firebase/Messaging'
  5. 从主项目目录中的终端运行 $ pod repo update
  6. 从主项目目录的终端运行 $ pod install,一旦 CocoaPods 创建了工作空间,打开 .workspace 文件。
  7. 通过将文件拖入项目将之前在 创建 Firebase 项目 部分提到的 GoogleService-Info.plist 文件集成到您的项目中。

示例 Podfile

    platform :ios, '10.0'

    use_frameworks!

    target :YourTargetName do  
        pod 'Branddrop'
        pod 'Firebase/Core', '~> 5.0'
        pod 'Firebase/Messaging'
    end

更新 Info.plist - 位置权限

请求位置权限需要在您的 Info.plist 文件中添加以下条目。每个条目都需要一个 String 格式的匹配键,解释用户地理位置数据将如何使用。

  • NSLocationAndWhenInUseUsageDescription
    • 隐私 - 总是和在使用时位置使用描述
  • NSLocationWhenInUseUsageDescription
    • 隐私 - 在使用时使用描述
  • NSLocationAlwaysUsageDescription
    • 隐私 - 总是位置使用描述

更新应用能力

在您的应用的主要目标下,您需要如下编辑其 能力

  1. 启用 后台模式。Apple 提供了有关各种 后台模式 的文档,您可以在此处找到:[链接](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW22)
  2. 勾选复选框 位置更新
  3. 勾选复选框 远程推送通知
  4. 启用 推送通知

使用 BAKit

AppDelegate

按照 向您的应用添加 Firebase Core 和 Firebase Messaging 部分中链接的 Apple 指令进行操作后,请将以下代码添加到您的 AppDelegate.swift 文件的顶部。

import BAKit
import Firebase
import UIKit
import UserNotifications
import Messages
import CoreLocation
import os.log

AppDelegate 类声明之前,声明了一个协议。符合该协议的类将在示例应用中接收到通知。

protocol NotificationDelegate: NSObject {
    func appReceivedRemoteNotification(notification: [AnyHashable: Any])
    func appReceivedRemoteNotificationInForeground(notification: [AnyHashable: Any])
}

AppDelegate 类声明内部,声明了以下变量和常量。

    public weak var notificationDelegate: NotificationDelegate?

    private let authOptions = UNAuthorizationOptions(arrayLiteral: [.alert, .badge, .sound])
    
    //Flags use to manage notification behaviour in various states
    var isNotificationStatusActive = false
    var isApplicationInBackground = false
    var isAppActive = false
    var isReceviedEventUpdated = false

在配置 Firebase 并声明 AppDelegate 对 Firebase 的 MessagingDelegate 的符合性后,将您的 Branddrop AppId 和 AppKey 存储到 Branddrop.client.userDefaults,如下所示。

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    FirebaseApp.configure()
    Messaging.messaging().delegate = self
    UNUserNotificationCenter.current().delegate = self
    
    // AppId is of type Int        
    Branddrop.client.userDefaults?.set(<#AppId#>, forKey: "AppId")

    // AppKey is of type String
    Branddrop.client.userDefaults?.set(<#AppKey#>, forKey: "AppKey")

    return true
}

/**
  Update the flag values when application enters in background
*/
func applicationDidEnterBackground(_ application: UIApplication) {
    isApplicationInBackground = true
    isAppActive = false
}

在您的 AppDelegate 类的结束括号下方添加以下内容。

extension AppDelegate {
/**
Call this function after having received your FCM and APNS tokens.
Additionally, you must have set your AppId and AppKey using the
Branddrop class's userDefaults.
*/
    func setupSDK() {
        let operationQueue = OperationQueue()
        let registerDeviceOperation = BlockOperation.init {
                            Branddrop.client.registerDevice { (parsedJSON, err) in
                guard err == nil, let parsedJSON = parsedJSON else {
                    fatalError()
                }

                Branddrop.client.userDefaults?.set(true, forKey: String.ConfigKeys.DeviceRegistered)
                Branddrop.client.userDefaults?.synchronize()
            }
        }

        let requestNotificationsOperation = BlockOperation.init {
            self.requestNotifications()
        }

        let monitorLocationOperation = BlockOperation.init {
            DispatchQueue.main.async {
            Branddrop.client.monitorLocation()
            }
        }

        monitorLocationOperation.addDependency(requestNotificationsOperation)
        requestNotificationsOperation.addDependency(registerDeviceOperation)

        operationQueue.addOperation(registerDeviceOperation)
        operationQueue.addOperation(requestNotificationsOperation)
        operationQueue.addOperation(monitorLocationOperation)
    }

    public func requestNotifications() {        
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in        
            if Branddrop.client.userDefaults?.object(forKey: "dateNotificationRequested") == nil {
                Branddrop.client.userDefaults?.set(Date().iso8601, forKey: "dateNotificationRequested")
                Branddrop.client.userDefaults?.synchronize()
            }
            Branddrop.client.updatePermissionStates()
            guard error == nil, granted else {
                // Handle error and possibility of user not granting permission
                return
            }
        }
        DispatchQueue.main.async {
            UIApplication.shared.registerForRemoteNotifications()
        }
    }
}

在一个遵循 Firebase 的 MessagingDelegate 的扩展中接收 FCM 令牌,将令牌存储在 BAKit 的 userDefaults 中。

// MARK: - MessagingDelegate

extension AppDelegate: MessagingDelegate {
    /**
     This function will be called once a token is available, or has been refreshed. Typically it will be called once per app start, but may be called more often, if a token is invalidated or updated. In this method, you should perform operations such as:

     * Uploading the FCM token to your application server, so targeted notifications can be sent.
     * Subscribing to any topics.
     */
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        Branddrop.client.userDefaults?.set(fcmToken, forKey: "deviceToken")
        Branddrop.client.userDefaults?.synchronize()
    }
}

作为检查您是否实现了必要的 UNUserNotificationCenterDelegate 函数的手段,提供以下代码片段。

// MARK: - UNUserNotificationCenterDelegate

extension AppDelegate: UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let deviceTokenString = deviceToken.reduce("", { $0 + String(format: "%02X", $1) })
        os_log("\n[AppDelegate] didRegisterForRemoteNotificationsWithDeviceToken :: APNs TOKEN: %s \n", deviceTokenString)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    // Handle APNS token registration error
        os_log("\n[AppDelegate] didFailToRegisterForRemoteNotificationsWithError :: APNs TOKEN FAIL :: %s \n", error.localizedDescription)
    }

    /**
     Called when app in foreground or background as opposed to `application(_:didReceiveRemoteNotification:)` which is only called in the foreground.
     (Source: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application)
     */
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        handleNotification(application: application, userInfo: userInfo)
        completionHandler(UIBackgroundFetchResult.newData)
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

        let userInfo = notification.request.content.userInfo as! [String: Any]

        if userInfo["notificationId"] as? String == "0000001" {
            handleNotification(application: UIApplication.shared, userInfo: userInfo)
        }

        NotificationCenter.default.post(name: NSNotification.Name("Refresh HomeViewController Tableview"), object: nil, userInfo: userInfo)
        completionHandler(UNNotificationPresentationOptions.init(arrayLiteral: [.badge, .sound, .alert]))
    }

    /**
        This delegate method will call when user opens the notification from the notification center.
    */
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        guard (response.actionIdentifier == UNNotificationDefaultActionIdentifier) || (response.actionIdentifier == UNNotificationDismissActionIdentifier) else {
            return
        }
        let userInfo = response.notification.request.content.userInfo as! [String: Any]

        if isApplicationInBackground && !isNotificationStatusActive {
          isNotificationStatusActive = false
          isApplicationInBackground = false
          if let _ = userInfo["aps"] as? [String: Any], let messageId = userInfo["baMessageId"] as? String, let firebaseNotificationId = userInfo["gcm.message_id"] as? String, let notificationId =  userInfo["baNotificationId"] as? String {
             if (isReceviedEventUpdated) {
                 self.notificationDelegate?.appReceivedRemoteNotificationInForeground(notification: userInfo)
             } else {
                 self.notificationDelegate?.appReceivedRemoteNotification(notification: userInfo)
             }
          }

       } else if isAppActive && !isNotificationStatusActive {         
           if (isReceviedEventUpdated) {
               self.notificationDelegate?.appReceivedRemoteNotificationInForeground(notification: userInfo)
           } else {
               self.notificationDelegate?.appReceivedRemoteNotification(notification: userInfo)
           }

       } else {
           isNotificationStatusActive = true
           isApplicationInBackground = false
           NotificationCenter.default.post(name: Notification.Name("display"), object: nil)
       }

       completionHandler()
    }

    /**
     Use `userInfo` for validating said instance, and calls `createEvent`, capturing the current application state.

     - Parameter userInfo: A dictionary that contains information related to the remote notification, potentially including a badge number for the app icon, an alert sound, an alert message to display to the user, a notification identifier, and custom data. The provider originates it as a JSON-defined dictionary that iOS converts to an `NSDictionary` object; the dictionary may contain only property-list objects plus `NSNull`. For more information about the contents of the remote notification dictionary, see Generating a Remote Notification.
     */
    public func handleNotification(application: UIApplication, userInfo: [AnyHashable: Any]) {

        NotificationCenter.default.post(name: NSNotification.Name("Refresh HomeViewController Tableview"), object: nil, userInfo: userInfo)

       if let _ = userInfo["aps"] as? [String: Any], let messageId = userInfo["baMessageId"] as? String, let firebaseNotificationId = userInfo["gcm.message_id"] as? String, let notificationId =  userInfo["baNotificationId"] as? String {
            switch application.applicationState {
            case .active:
                Branddrop.client.postEvent(name: String.Received, messageId: messageId, firebaseNotificationId: firebaseNotificationId, notificationId: notificationId)
                break
            case .background:
                Branddrop.client.postEvent(name: String.Received, messageId: messageId, firebaseNotificationId: firebaseNotificationId, notificationId: notificationId)
                break
            case .inactive:
                Branddrop.client.postEvent(name: String.Opened, messageId: messageId, firebaseNotificationId: firebaseNotificationId, notificationId: notificationId)
                break
            default:
                break
            }
        }
    }
}

添加以下代码以在应用终止时监测显著的位置更新。

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {

    if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
            let locationManager = CLLocationManager()
            if CLLocationManager.locationServicesEnabled() {
                locationManager.desiredAccuracy = kCLLocationAccuracyBest
                locationManager.delegate = self
                locationManager.pausesLocationUpdatesAutomatically = false
                locationManager.allowsBackgroundLocationUpdates = true
                locationManager.startMonitoringSignificantLocationChanges()
            }
        }
        NotificationCenter.default.addObserver(Branddrop.client, selector: #selector(Branddrop.client.updatePermissionStates), name: Notification.Name("Update user permission states"), object: nil)
        return true
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
            application.applicationIconBadgeNumber = 0

        if (isApplicationInBackground) {
            NotificationCenter.default.post(name: Notification.Name("Update user permission states"), object: nil)
        }
        isAppActive = true

    }

    extension AppDelegate: CLLocationManagerDelegate {
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
            Branddrop.client.postLocation(location: manager.location!)
        }
    }

在您想要启动位置和通知服务的控制器中添加以下方法。

(UIApplication.shared.delegate! as! AppDelegate).setupSDK()

下载示例应用源代码

示例应用已包含在代码库中的 "Example" 目录下。[链接](https://github.com/BoardActive/BD-SDK-iOS/tree/main/Example)

寻求帮助

我们的团队愿为您提供帮助。请联系我们。

  • 打电话给我们:(678) 383-2200
  • 发送邮件 [email protected]
  • 在线支持 [网站](https://www.branddrop.us/)