Branddrop平台通过位置基础的用户参与将品牌和消费者连接起来。我们的国际专利申请中的Visualmatic™软件是一个强大的营销工具,允许品牌在任何位置周围设置虚拟围栏,测量人流量,并在用户进入地理定位时通过个性化的消息与他们互动... 并通过查看用户在印象之后的去向有效地归因于营销活动的效率!
使用您的Branddrop账户创建地点(地理围栏区域)和消息(通知),向您的应用用户发送定制消息。
一旦客户至少建立一个地理围栏,BAKit SDK将利用任何智能设备的本地位置监控,确定何时用户进入所提到的地理围栏,并派发客户组成的个性化通知。
- 您已将应用添加的Firebase项目。
- 一个Branddrop账户
要使用Firebase Cloud Messaging,您必须创建一个Firebase项目。
- Firebase iOS 快速入门 - 创建和了解Firebase项目的指南。
- 在iOS上设置Firebase Cloud Messaging客户端应用 - 如何处理Firebase Cloud Messaging(发送推送通知的途径)。
- 请参考以下两篇文章有关APNs,因为Firebase的文档有些过时。我们还将介绍如何在安装SDK的同时将推送通知添加到您的账户
- 点击这里进入Firebase控制台
创建相关Firebase项目后,您可以下载GoogleService-Info.plist
并保留该文件,用于"CocoaPods"部分。
- 请将Firebase项目设置中“Service Accounts” -> “Firebase Admin SDK”下的Firebase密钥通过电子邮件发送到[email protected],他将回复您的AppKey。
- 支持iOS 10以上,要求使用Swift 4.0。
- 使用Xcode 9+进行构建,需要支持iPhone X和iOS 11。
- 目前,SDK可通过CocoaPods或下载仓库并手动将SDK的源代码链接到项目中获取。
- 设置CocoaPods
- 关闭/退出Xcode。
- 通过项目目录中的终端运行
$ pod init
- 打开您刚刚创建的
Podfile
,并添加以下pod(见本节末尾的示例Podfile)。pod 'Branddrop'
pod 'Firebase/Core', '~> 5.0'
pod 'Firebase/Messaging'
- 从主项目目录中的终端运行
$ pod repo update
。 - 从主项目目录的终端运行
$ pod install
,一旦 CocoaPods 创建了工作空间,打开 .workspace 文件。 - 通过将文件拖入项目将之前在 创建 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
文件中添加以下条目。每个条目都需要一个 String
格式的匹配键,解释用户地理位置数据将如何使用。
NSLocationAndWhenInUseUsageDescription
隐私 - 总是和在使用时位置使用描述
NSLocationWhenInUseUsageDescription
隐私 - 在使用时使用描述
NSLocationAlwaysUsageDescription
隐私 - 总是位置使用描述
在您的应用的主要目标下,您需要如下编辑其 能力
- 启用 后台模式。Apple 提供了有关各种 后台模式 的文档,您可以在此处找到:[链接](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW22)
- 勾选复选框 位置更新
- 勾选复选框 远程推送通知
- 启用 推送通知
按照 向您的应用添加 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/)