BAKit 2.0.1

BAKit 2.0.1

Tom PowellBoardActive 维护。



BAKit 2.0.1

  • BoardActive

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

BAKit-iOS

基于位置的用户互动

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

BoardActive 的平台通过基于位置的互动将品牌与消费者连接。我们的国际专利待审的 Visualmatic™ 软件是一款强大的营销工具,允许品牌在任意位置设立虚拟区域,测量人流量,并在用户进入地理位置时发布个性化的消息…… 除此之外,通过查看用户的印象后去了哪里,有效地归因于营销活动的效率!

使用您的 BoardActive 账户创建地点(地理围栏区域)和消息(通知),以便将定制消息发送给您的应用程序用户。

点击此处获取 BoardActive 账户

一旦客户端建立了至少一个地理围栏,BAKit SDK 利用任何智能手机的本地位置监控,确定何时用户进入该围栏,并向客户端发布由其组成的个性化通知。


所需用于设置

  1. 添加了您的应用的 Firebase 项目的项目。
  2. BoardActive 账户

创建 Firebase 项目

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

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

创建相关的 Firebase 项目后,您可以下载 GoogleService-Info.plist 并将其保存在“CocoaPods”部分中使用。

接收您的 BoardActive AppKey

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

安装BAKit SDK

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

CocoaPods

  1. 设置CocoaPods
  2. 关闭/退出Xcode。
  3. 在您的项目目录中的终端运行 $ pod init
  4. 打开您刚刚创建的 Podfile 文件,并添加以下插件(请参阅本节最后的示例Podfile)。
    • pod 'BAKit'
    • 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 'BAKit'
        pod 'Firebase/Core', '~> 5.0'
        pod 'Firebase/Messaging'
    end

更新Info.plist - 位置权限

请求位置权限需要在您的 Info.plist 文件中包含以下条目。每个条目都需要一个伴随的关键字,形式为String,解释用户地理位置数据将如何使用。

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

更新应用权限

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

  1. 启用 后台模式。Apple提供了关于不同 后台模式 的文档,请在此处
  2. 勾选 位置更新 复选框
  3. 勾选 后台获取 复选框
  4. 勾选复选框 远程通知
  5. 启用 推送通知

使用 BAKit

AppDelegate

在“将 Firebase Core 和 Firebase Messaging 添加到您的应用程序”部分中,按照 Apple 的说明操作后,请将以下代码添加到您的 AppDelegate.swift 文件的顶部

import BAKit
import Firebase
import UIKit
import UserNotifications
import Messages

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

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

AppDelegate 类声明的刚下方,声明了以下变量和常量

    public weak var notificationDelegate: NotificationDelegate?

    private let authOptions = UNAuthorizationOptions(arrayLiteral: [.alert, .badge, .sound])

在配置 Firebase 并声明 AppDelegate 对 Firebase 的 MessagingDelegate 的一致性后,将您的 BoardActive AppId 和 AppKey 存储到 BoardActive.client.userDefaults 中,如下所示

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    FirebaseApp.configure()
    Messaging.messaging().delegate = self
    UNUserNotificationCenter.current().delegate = self
    application.applicationIconBadgeNumber = UserDefaults.extensions.badge

    // AppId is of type Int        
    BoardActive.client.userDefaults?.set(<#AppId#>, forKey: "AppId")

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

在您的 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 
BoardActive class's userDefaults.
*/
    func setupSDK() {
        let operationQueue = OperationQueue()
        let registerDeviceOperation = BlockOperation.init {
            BoardActive.client.registerDevice { (parsedJSON, err) in
                guard err == nil, let parsedJSON = parsedJSON else {
                    fatalError()
                }
                
                BoardActive.client.userDefaults?.set(true, forKey: String.ConfigKeys.DeviceRegistered)
                BoardActive.client.userDefaults?.synchronize()
            }
        }
       
        let requestNotificationsOperation = BlockOperation.init {
            self.requestNotifications()
        }
        
        let monitorLocationOperation = BlockOperation.init {
            DispatchQueue.main.async {
                BoardActive.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 BoardActive.client.userDefaults?.object(forKey: "dateNotificationPermissionRequested") == nil {
                BoardActive.client.userDefaults?.set(Date().iso8601, forKey: "dateNotificationPermissionRequested")
                BoardActive.client.userDefaults?.synchronize()
            }
            guard error == nil, granted else {
            // Handle error and possibility of user not granting permission
                return
            }
        }
        
        DispatchQueue.main.async {
            UIApplication.shared.registerForRemoteNotifications()
        }
    } 
}

在一个遵循 Firebase 的 MessagingDelegate 扩展中接收 FCM Token 时,将此令牌存储到 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) {
        BoardActive.client.userDefaults?.set(fcmToken, forKey: "deviceToken")
        BoardActive.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]))
    }
        
    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]
        
        self.notificationDelegate?.appReceivedRemoteNotification(notification: userInfo)
        
        completionHandler()
    }
    
    /**
     Creates an instance of `NotificationModel` from `userInfo`, validates 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]) {
        let tempUserInfo = userInfo as! [String: Any]
        
        if let _ = tempUserInfo["aps"], let messageId = tempUserInfo["messageId"] as? String, let firebaseNotificationId = tempUserInfo["gcmmessageId"] as? String {
            switch application.applicationState {
            case .active:
                os_log("%s", String.ReceivedBackground)
                BoardActive.client.postEvent(name: String.Received, messageId: messageId, firebaseNotificationId: firebaseNotificationId)
                break
            case .background:
                os_log("%s", String.ReceivedBackground)
                BoardActive.client.postEvent(name: String.Received, messageId: messageId, firebaseNotificationId: firebaseNotificationId)
                break
            case .inactive:
                os_log("%s", String.TappedAndTransitioning)
                BoardActive.client.postEvent(name: String.Opened, messageId: messageId, firebaseNotificationId: firebaseNotificationId)
                break
            default:
                break
            }
        }
    }
}

下载示例应用程序源代码

在代码库的“示例”部分包含了一个示例应用程序。

寻求帮助

我们团队愿意提供帮助。请联系我们