diff --git a/.gitignore b/.gitignore
index d660cc80c..55924626a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,10 +19,6 @@ UnityPackageManager/
/Temp
/Library
## https://stackoverflow.com/a/57728803/3745724
-#Ignore all .meta file
-*.meta
-#But not source file with postfix. which is everything but a folder
-!*.*.meta
# Firebase
/unity-samples/Assets/Plugins/Android/*.aar
@@ -87,3 +83,5 @@ unity-samples/iOS/Roll-A-Ball-Ios/fastlane/report.xml
# Visual Studio
.vs/
obj/
+.vscode/
+
diff --git a/Assets/Editor.meta b/Assets/Editor.meta
new file mode 100644
index 000000000..5a0b87a39
--- /dev/null
+++ b/Assets/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 71fbc09525bca413cafd9ae08a29d175
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta
new file mode 100644
index 000000000..397bbe3dc
--- /dev/null
+++ b/Assets/Plugins.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2245c82083ae24e51b7730ccad41cef9
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Android.meta b/Assets/Plugins/Android.meta
new file mode 100644
index 000000000..a2153c028
--- /dev/null
+++ b/Assets/Plugins/Android.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0b188b8d8c25040e59346b214285c462
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Android/appboy-ui.aar b/Assets/Plugins/Android/appboy-ui.aar
index 930119b27..757ef6701 100644
Binary files a/Assets/Plugins/Android/appboy-ui.aar and b/Assets/Plugins/Android/appboy-ui.aar differ
diff --git a/Assets/Plugins/Android/appboy-unity.aar b/Assets/Plugins/Android/appboy-unity.aar
index 2285f2c23..65a35e78b 100644
Binary files a/Assets/Plugins/Android/appboy-unity.aar and b/Assets/Plugins/Android/appboy-unity.aar differ
diff --git a/Assets/Plugins/Android/appboy.aar b/Assets/Plugins/Android/appboy.aar
index ec2d12f7e..4027c43e4 100644
Binary files a/Assets/Plugins/Android/appboy.aar and b/Assets/Plugins/Android/appboy.aar differ
diff --git a/Assets/Plugins/Appboy.meta b/Assets/Plugins/Appboy.meta
new file mode 100644
index 000000000..bdbd9363d
--- /dev/null
+++ b/Assets/Plugins/Appboy.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7946e19958b6c4b36938e0ff6292a975
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/AppboyBinding.cs b/Assets/Plugins/Appboy/AppboyBinding.cs
index 64291187c..6a8cfdd64 100755
--- a/Assets/Plugins/Appboy/AppboyBinding.cs
+++ b/Assets/Plugins/Appboy/AppboyBinding.cs
@@ -1,23 +1,82 @@
// When developing, you can place #define UNITY_ANDROID or #define UNITY_IOS above this line
// in order to get correct syntax highlighting in the region you are working on.
+using Appboy.Internal;
using Appboy.Models;
-using UnityEngine;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
using Appboy.Utilities;
using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
using System.Text;
+using UnityEngine;
///
/// These methods can be called by Unity applications using iOS or Android in order to report
-/// events and set user attributes. Please see the Appboy Android JavaDocs for more
-/// detailed guidance on usage (note that only a subset of the functions in the JavaDocs
-/// are available in the Unity API):
-/// http://appboy.github.io/appboy-android-sdk/javadocs/com/appboy/IAppboy.html
-/// http://appboy.github.io/appboy-android-sdk/javadocs/index.html
+/// events, set user attributes, and control messaging
///
-
namespace Appboy {
+
+ public delegate void PushPromptResponseReceived(bool granted);
+ public delegate void PushTokenReceivedFromSystem(string token);
+
+ ///
+ /// Types of messages that Braze can be configured to send to a GameObject method at runtime.
+ ///
+ /// Use to set up a listener.
+ ///
+ public enum BrazeUnityMessageType {
+ ///
+ /// Sent when Braze receives a response from the user after displaying a push prompt via
+ /// , or if Braze is automatically configured
+ /// to register for push. Currently only sent for iOS.
+ ///
+ PUSH_PERMISSIONS_PROMPT_RESPONSE = 0,
+
+ ///
+ /// Sent when Braze receives a push token from the OS. Currently only sent for iOS.
+ ///
+ /// On iOS, only sent if Braze is configured to automatically integrate push.
+ ///
+ PUSH_TOKEN_RECEIVED_FROM_SYSTEM = 1,
+
+ ///
+ /// Sent when the user receives a push notification.
+ ///
+ /// On iOS, only sent if Braze is configured to automatically integrate push. On iOS, we recommend
+ /// configuring this value before application:didFinishLaunchingWithOptions: returns to ensure your
+ /// callback is set before iOS push delegates are called.
+ ///
+ PUSH_RECEIVED = 2,
+
+ ///
+ /// Sent when the user opens a push notification.
+ ///
+ /// On iOS, only sent if Braze is configured to automatically integrate push. On iOS, we recommend
+ /// configuring this value before application:didFinishLaunchingWithOptions: returns to ensure your
+ /// callback is set before iOS push delegates are called.
+ ///
+ PUSH_OPENED = 3,
+
+ ///
+ /// Sent when the user has swiped away a push notification. Currently only sent for Android.
+ ///
+ PUSH_DELETED = 4,
+
+ ///
+ /// Sent when the SDK has a new In-App Message.
+ ///
+ IN_APP_MESSAGE = 5,
+
+ ///
+ /// Sent when the SDK has an update for the News Feed.
+ ///
+ NEWS_FEED_UPDATED = 6,
+
+ ///
+ /// Sent when the SDK has an update for Content Cards.
+ ///
+ CONTENT_CARDS_UPDATED = 7
+ }
+
public class AppboyBinding : MonoBehaviour {
// Overloads
// These will call the associated binding method for the current live platform
@@ -32,7 +91,7 @@ public static void IncrementCustomUserAttribute(string key) {
#if UNITY_IOS
void Start() {
- Debug.Log("Starting Appboy binding for iOS clients.");
+ Debug.Log("Starting Braze binding for iOS clients.");
}
[System.Runtime.InteropServices.DllImport("__Internal")]
@@ -185,9 +244,18 @@ void Start() {
[System.Runtime.InteropServices.DllImport("__Internal")]
private static extern void _registerAppboyPushMessages(string registrationTokenBase64);
+ [System.Runtime.InteropServices.DllImport("__Internal")]
+ private static extern void _promptUserForPushPermissions(bool provisional);
+
[System.Runtime.InteropServices.DllImport("__Internal")]
private static extern void _addAlias(string label, string alias);
+ [System.Runtime.InteropServices.DllImport("__Internal")]
+ private static extern void _configureListener(int messageType, string gameobject, string method);
+
+ [System.Runtime.InteropServices.DllImport("__Internal")]
+ private static extern void _configureInternalListener(int messageType);
+
public static void LogCustomEvent(string eventName) {
_logCustomEvent(eventName, null);
}
@@ -206,6 +274,11 @@ public static void LogPurchase(string productId, string currencyCode, decimal pr
_logPurchase(productId, currencyCode, price.ToString(), quantity, propertiesString);
}
+ ///
+ /// When you first start using Braze on a device, the user is considered "anonymous". You can use this
+ /// method to optionally identify a user with a unique ID.
+ ///
+ ///
public static void ChangeUser(string userId) {
_changeUser(userId);
}
@@ -238,10 +311,18 @@ public static void SetUserHomeCity(string city) {
_setUserHomeCity(city);
}
+ ///
+ /// Configures the user's opt-in status for email within Braze.
+ ///
+ ///
public static void SetUserEmailNotificationSubscriptionType(AppboyNotificationSubscriptionType emailNotificationSubscriptionType) {
_setUserEmailNotificationSubscriptionType((int)emailNotificationSubscriptionType);
}
+ ///
+ /// Configures the user's opt-in status for push within Braze.
+ ///
+ ///
public static void SetUserPushNotificationSubscriptionType(AppboyNotificationSubscriptionType pushNotificationSubscriptionType) {
_setUserPushNotificationSubscriptionType((int)pushNotificationSubscriptionType);
}
@@ -395,18 +476,56 @@ public static void RequestLocationInitialization() {
}
///
- /// Registers a device token with Braze. See
- /// https://docs.unity3d.com/2018.4/Documentation/ScriptReference/iOS.NotificationServices.RegisterForNotifications.html
+ /// Registers a device token (the term for push token on iOS) with Braze.
///
///
- /// https://docs.unity3d.com/2018.4/Documentation/ScriptReference/iOS.NotificationServices-deviceToken.html
+ /// The device token
///
- ///
public static void RegisterAppboyPushMessages(byte[] registrationDeviceToken) {
string registrationTokenBase64 = Convert.ToBase64String(registrationDeviceToken);
_registerAppboyPushMessages(registrationTokenBase64);
}
+ ///
+ /// Prompts the user for push permissions and registers the user to receive push notifications.
+ ///
+ /// To subscribe to the result, set a Game Object to listen for
+ /// events using
+ /// , or pass in a delegate instance of .
+ ///
+ ///
+ /// If set to true, on iOS 12 and above, the user will be provisionally (silently) authorized
+ /// to receive quiet push.
+ /// Otherwise, the user will be shown the native push prompt.
+ ///
+ ///
+ /// An optional delegate instance to receive the user's response to the prompt.
+ ///
+ public static void PromptUserForPushPermissions(bool provisional, PushPromptResponseReceived reponseDelegate = null) {
+ if (reponseDelegate != null) {
+ _configureInternalListener((int)BrazeUnityMessageType.PUSH_PERMISSIONS_PROMPT_RESPONSE);
+ BrazeInternalGameObject.setPushPromptResponseReceivedDelegate(reponseDelegate);
+ }
+ _promptUserForPushPermissions(provisional);
+ }
+
+ ///
+ /// Configures Braze to send push tokens from the OS to the provided delegate. Braze will only listen for push tokens
+ /// from the OS if automatic push registration is enabled.
+ ///
+ /// Tokens passed to Braze via will also cause the delegate to be called.
+ ///
+ ///
+ /// A delegate instance to receive push tokens.
+ ///
+ public static void SetPushTokenReceivedFromSystemDelegate(PushTokenReceivedFromSystem tokenDelegate) {
+ if (tokenDelegate == null) {
+ return;
+ }
+ BrazeInternalGameObject.setPushTokenReceivedFromSystemDelegate(tokenDelegate);
+ _configureInternalListener((int)BrazeUnityMessageType.PUSH_TOKEN_RECEIVED_FROM_SYSTEM);
+ }
+
///
/// Requests a refresh of Braze Geofences for the specified GPS coordinate.
///
@@ -429,13 +548,35 @@ public static void AddAlias(string alias, string label) {
_addAlias(alias, label);
}
+ ///
+ /// Used to configure Braze to send messages to GameObjects based
+ /// on lifecycle events. See for
+ /// available message types.
+ ///
+ /// Any previous configured game object callback will be overwritten.
+ /// There can only be one active callback per message type.
+ ///
+ ///
+ /// The type of message to send to the target GameObject.
+ ///
+ ///
+ /// The target GameObject.
+ ///
+ ///
+ /// The script method to call on the GameObject.
+ ///
+ public static void ConfigureListener(BrazeUnityMessageType messageType, string gameobject, string method) {
+ _configureListener((int)messageType, gameobject, method);
+ }
+
#elif UNITY_ANDROID
private static AndroidJavaObject appboyUnityActivity;
private static AndroidJavaObject inAppMessageUtils;
private static AndroidJavaObject appboyLocationService;
+ private static AndroidJavaObject unityConfigurationProvider;
void Start() {
- Debug.Log("Starting Appboy binding for Android clients.");
+ Debug.Log("Starting Braze binding for Android clients.");
}
#region Properties
@@ -476,6 +617,15 @@ public static AndroidJavaObject AppboyLocationService {
}
}
+ public static AndroidJavaObject UnityConfigurationProvider {
+ get {
+ if (unityConfigurationProvider == null) {
+ unityConfigurationProvider = new AndroidJavaObject("com.appboy.unity.configuration.UnityConfigurationProvider", AppboyUnityActivity);
+ }
+ return unityConfigurationProvider;
+ }
+ }
+
#endregion
private static AndroidJavaObject GetCurrentUser() {
@@ -533,6 +683,11 @@ public static void LogPurchase(string productId, string currencyCode, decimal pr
Appboy.Call("logPurchase", productId, currencyCode, javaPrice, quantity, appboyProperties);
}
+ ///
+ /// When you first start using Braze on a device, the user is considered "anonymous". You can use this
+ /// method to optionally identify a user with a unique ID.
+ ///
+ ///
public static void ChangeUser(string userId) {
Appboy.Call("changeUser", userId);
}
@@ -651,6 +806,10 @@ public static void SetUserHomeCity(string city) {
GetCurrentUser().Call("setHomeCity", city);
}
+ ///
+ /// Configures the user's opt-in status for email within Braze.
+ ///
+ ///
public static void SetUserEmailNotificationSubscriptionType(AppboyNotificationSubscriptionType emailNotificationSubscriptionType) {
using (var notificationTypeClass = new AndroidJavaClass("com.appboy.enums.NotificationSubscriptionType")) {
switch (emailNotificationSubscriptionType) {
@@ -670,6 +829,10 @@ public static void SetUserEmailNotificationSubscriptionType(AppboyNotificationSu
}
}
+ ///
+ /// Configures the user's opt-in status for push within Braze.
+ ///
+ ///
public static void SetUserPushNotificationSubscriptionType(AppboyNotificationSubscriptionType pushNotificationSubscriptionType) {
using (var notificationTypeClass = new AndroidJavaClass("com.appboy.enums.NotificationSubscriptionType")) {
switch (pushNotificationSubscriptionType) {
@@ -796,10 +959,30 @@ public static void RemoveFromCustomUserAttributeArray(string key, string value)
GetCurrentUser().Call("removeFromCustomAttributeArray", key, value);
}
+ ///
+ /// Registers a push token with Braze.
+ ///
+ ///
+ /// The push token
+ ///
public static void RegisterAppboyPushMessages(string registrationId) {
Appboy.Call("registerAppboyPushMessages", new object[] { registrationId });
}
+ ///
+ /// No-op on Android.
+ ///
+ ///
+ ///
+ public static void PromptUserForPushPermissions(bool provisional, PushPromptResponseReceived reponseDelegate = null) {}
+
+ ///
+ /// No-op on Android.
+ ///
+ ///
+ ///
+ public static void SetPushTokenReceivedFromSystemDelegate(PushTokenReceivedFromSystem tokenDelegate) {}
+
public static void LogInAppMessageClicked(string inAppMessageJSONString) {
var inAppMessage = InAppMessageUtils.CallStatic("inAppMessageFromString", appboyUnityActivity, inAppMessageJSONString);
InAppMessageUtils.CallStatic("logInAppMessageClick", inAppMessage);
@@ -905,96 +1088,61 @@ public static void AddAlias(string alias, string label) {
GetCurrentUser().Call("addAlias", alias, label);
}
+ ///
+ /// Used to configure Braze to send messages to GameObjects based
+ /// on lifecycle events. See for
+ /// available message types.
+ ///
+ ///
+ /// The type of message to send to the target GameObject.
+ ///
+ ///
+ /// The target GameObject.
+ ///
+ ///
+ /// The script method to call on the GameObject.
+ ///
+ public static void ConfigureListener(BrazeUnityMessageType messageType, string gameobject, string method) {
+ UnityConfigurationProvider.Call("configureListener", (int)messageType, gameobject, method);
+ }
+
#else
// Empty implementations of the API, in case the application is being compiled for a platform other than iOS or Android.
void Start() {
- Debug.Log("Starting no-op Appboy binding for non iOS/Android clients.");
- }
-
- public static void LogCustomEvent(string eventName) {
- }
-
- public static void LogCustomEvent(string eventName, Dictionary properties) {
- }
-
- public static void LogPurchase(string productId, string currencyCode, decimal price, int quantity) {
- }
-
- public static void LogPurchase(string productId, string currencyCode, decimal price, int quantity, Dictionary properties) {
- }
-
- public static void ChangeUser(string userId) {
- }
-
- public static void SetUserFirstName(string firstName) {
- }
-
- public static void SetUserLastName(string lastName) {
- }
-
- public static void SetUserEmail(string email) {
- }
-
- public static void SetUserBio(string bio) {
- }
-
- public static void SetUserGender(Gender gender) {
- }
-
- public static void SetUserDateOfBirth(int year, int month, int day) {
- }
-
- public static void SetUserCountry(string country) {
- }
-
- public static void SetUserHomeCity(string city) {
- }
-
- public static void SetUserIsSubscribedToEmails(bool isSubscribedToEmails) {
- }
-
- public static void SetUserEmailNotificationSubscriptionType(AppboyNotificationSubscriptionType emailNotificationSubscriptionType) {
- }
-
- public static void SetUserPushNotificationSubscriptionType(AppboyNotificationSubscriptionType pushNotificationSubscriptionType) {
- }
-
- public static void SetUserPhoneNumber(string phoneNumber) {
- }
-
- public static void SetUserAvatarImageURL(string imageURL) {
- }
-
- public static void SetCustomUserAttribute(string key, bool value) {
- }
-
- public static void SetCustomUserAttribute(string key, int value) {
- }
-
- public static void SetCustomUserAttribute(string key, float value) {
- }
-
- public static void SetCustomUserAttribute(string key, string value) {
- }
-
- public static void SetCustomUserAttributeToNow(string key) {
- }
-
- public static void SetCustomUserAttributeToSecondsFromEpoch(string key, long secondsFromEpoch) {
- }
-
- public static void UnsetCustomUserAttribute(string key) {
- }
-
- public static void IncrementCustomUserAttribute(string key, int incrementValue) {
- }
-
- public static void SetCustomUserAttributeArray(string key, List array, int size) {
- }
-
- public static void AddToCustomUserAttributeArray(string key, string value) {
- }
+ Debug.Log("Starting no-op Braze binding for non iOS/Android clients.");
+ }
+
+ public static void LogCustomEvent(string eventName) {}
+ public static void LogCustomEvent(string eventName, Dictionary properties) {}
+ public static void LogPurchase(string productId, string currencyCode, decimal price, int quantity) {}
+ public static void LogPurchase(string productId, string currencyCode, decimal price, int quantity, Dictionary properties) {}
+
+ public static void ChangeUser(string userId) {}
+
+ public static void SetUserFirstName(string firstName) {}
+ public static void SetUserLastName(string lastName) {}
+ public static void SetUserEmail(string email) {}
+ public static void SetUserGender(Gender gender) {}
+ public static void SetUserDateOfBirth(int year, int month, int day) {}
+ public static void SetUserCountry(string country) {}
+ public static void SetUserHomeCity(string city) {}
+ public static void SetUserEmailNotificationSubscriptionType(AppboyNotificationSubscriptionType emailNotificationSubscriptionType) {}
+ public static void SetUserPushNotificationSubscriptionType(AppboyNotificationSubscriptionType pushNotificationSubscriptionType) {}
+ public static void SetUserPhoneNumber(string phoneNumber) {}
+ public static void SetUserAvatarImageURL(string imageURL) {}
+
+ public static void SetCustomUserAttribute(string key, bool value) {}
+ public static void SetCustomUserAttribute(string key, int value) {}
+ public static void SetCustomUserAttribute(string key, float value) {}
+ public static void SetCustomUserAttribute(string key, string value) {}
+ public static void SetCustomUserAttributeToNow(string key) {}
+ public static void SetCustomUserAttributeToSecondsFromEpoch(string key, long secondsFromEpoch) {}
+ public static void UnsetCustomUserAttribute(string key) {}
+ public static void IncrementCustomUserAttribute(string key, int incrementValue) {}
+ public static void SetCustomUserAttributeArray(string key, List array, int size) {}
+ public static void AddToCustomUserAttributeArray(string key, string value) {}
+ public static void RemoveFromCustomUserAttributeArray(string key, string value) {}
public static void setUserFacebookData(string facebookId, string firstName, string lastName, string email,
string bio, string cityName, Gender? gender, int? numberOfFriends, string birthday) {}
@@ -1002,75 +1150,43 @@ public static void setUserFacebookData(string facebookId, string firstName, stri
public static void setUserTwitterData(int? twitterUserId, string twitterHandle, string name, string description, int? followerCount,
int? followingCount, int? tweetCount, string profileImageUrl) {}
- public static void RemoveFromCustomUserAttributeArray(string key, string value) {
- }
-
- public static void RegisterAppboyPushMessages(string registrationId) {
- }
-
- public static void LogInAppMessageClicked(string inAppMessageJSONString) {
- }
-
- public static void LogInAppMessageImpression(string inAppMessageJSONString) {
- }
-
- public static void LogInAppMessageButtonClicked(string inAppMessageJSONString, int buttonID) {
- }
-
- public static void RequestFeedRefresh() {
- }
-
- public static void RequestFeedRefreshFromCache() {
- }
-
- public static void LogFeedDisplayed() {
- }
-
- public static void RequestContentCardsRefresh() {
- }
-
- public static void RequestContentCardsRefreshFromCache() {
- }
+ public static void RegisterAppboyPushMessages(string registrationId) {}
+ public static void PromptUserForPushPermissions(bool provisional, PushPromptResponseReceived reponseDelegate = null) {}
+ public static void SetPushTokenReceivedFromSystemDelegate(PushTokenReceivedFromSystem tokenDelegate) {}
- public static void LogContentCardsDisplayed() {
- }
+ public static void LogInAppMessageClicked(string inAppMessageJSONString) {}
+ public static void LogInAppMessageImpression(string inAppMessageJSONString) {}
+ public static void LogInAppMessageButtonClicked(string inAppMessageJSONString, int buttonID) {}
- public static void LogContentCardClicked(string contentCardString) {
- }
+ public static void RequestFeedRefresh() {}
+ public static void RequestFeedRefreshFromCache() {}
+ public static void LogFeedDisplayed() {}
- public static void LogContentCardImpression(string contentCardString) {
- }
+ public static void RequestContentCardsRefresh() {}
+ public static void RequestContentCardsRefreshFromCache() {}
+ public static void LogContentCardsDisplayed() {}
+ public static void LogContentCardClicked(string contentCardString) {}
+ public static void LogContentCardImpression(string contentCardString) { }
+ public static void LogContentCardDismissed(string contentCardString) { }
- public static void LogContentCardDismissed(string contentCardString) {
- }
-
- public static void WipeData() {
- }
-
- public static void EnableSDK() {
- }
-
- public static void DisableSDK() {
- }
+ public static void WipeData() {}
+ public static void EnableSDK() {}
+ public static void DisableSDK() {}
public static string GetInstallTrackingId() {
return null;
}
- public static void SetAttributionData(string network, string campaign, string adgroup, string creative) {
- }
+ public static void SetAttributionData(string network, string campaign, string adgroup, string creative) {}
- public static void RequestLocationInitialization() {
- }
+ public static void RequestLocationInitialization() {}
+ public static void RequestGeofences(decimal latitude, decimal longitude) {}
- public static void RequestGeofences(decimal latitude, decimal longitude) {
- }
+ public static void RequestImmediateDataFlush() {}
- public static void RequestImmediateDataFlush() {
- }
+ public static void AddAlias(string alias, string label) {}
- public static void AddAlias(string alias, string label) {
- }
+ public static void ConfigureListener(BrazeUnityMessageType messageType, string gameobject, string method) {}
#endif
}
}
diff --git a/Assets/Plugins/Appboy/Editor.meta b/Assets/Plugins/Appboy/Editor.meta
new file mode 100644
index 000000000..0faeb635e
--- /dev/null
+++ b/Assets/Plugins/Appboy/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ed3f31f832ecb4cd98c6f8dbd5ea07f6
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/Editor/AppboyConfig.cs b/Assets/Plugins/Appboy/Editor/AppboyConfig.cs
index 884281497..043d035c9 100644
--- a/Assets/Plugins/Appboy/Editor/AppboyConfig.cs
+++ b/Assets/Plugins/Appboy/Editor/AppboyConfig.cs
@@ -52,6 +52,10 @@ public class AppboyConfig : ScriptableObject {
[SerializeField]
private bool iOSDisableAutomaticPushRegistration = false;
[SerializeField]
+ private bool iOSDisableProvisionalAuth = false;
+ [SerializeField]
+ private bool iOSDisableAutomaticPushCapability = false;
+ [SerializeField]
private bool iOSPushIsBackgroundEnabled = false;
[SerializeField]
private string iOSPushReceivedGameObjectName = string.Empty;
@@ -173,6 +177,16 @@ public static bool IOSDisableAutomaticPushRegistration {
set { SetProperty(ref Instance.iOSDisableAutomaticPushRegistration, value); }
}
+ public static bool IOSDisableProvisionalAuth {
+ get { return Instance.iOSDisableProvisionalAuth; }
+ set { SetProperty(ref Instance.iOSDisableProvisionalAuth, value); }
+ }
+
+ public static bool IOSDisableAutomaticPushCapability {
+ get { return Instance.iOSDisableAutomaticPushCapability; }
+ set { SetProperty(ref Instance.iOSDisableAutomaticPushCapability, value); }
+ }
+
public static string IOSPushReceivedGameObjectName {
get { return Instance.iOSPushReceivedGameObjectName; }
set { SetProperty(ref Instance.iOSPushReceivedGameObjectName, value); }
diff --git a/Assets/Plugins/Appboy/Editor/AppboyConfigEditor.cs b/Assets/Plugins/Appboy/Editor/AppboyConfigEditor.cs
index d0bef0aac..a09bbeba0 100644
--- a/Assets/Plugins/Appboy/Editor/AppboyConfigEditor.cs
+++ b/Assets/Plugins/Appboy/Editor/AppboyConfigEditor.cs
@@ -129,6 +129,20 @@ private void IOSBuildGUIPush() {
EditorGUILayout.LabelField("Disables automatic user registration for push notifications upon app startup.", EditorStyles.wordWrappedMiniLabel);
}
+ AppboyConfig.IOSDisableProvisionalAuth = EditorGUILayout.ToggleLeft(" Disable Provisional Authorization", AppboyConfig.IOSDisableProvisionalAuth);
+ if (AppboyConfig.IOSDisableProvisionalAuth) {
+ EditorGUILayout.LabelField("Users will see the native push prompt dialog at app startup.", EditorStyles.miniBoldLabel);
+ } else {
+ EditorGUILayout.LabelField("Disables provisional (quiet) authorization. If disabled, users will see the native push prompt dialog at app startup.", EditorStyles.wordWrappedMiniLabel);
+ }
+
+ AppboyConfig.IOSDisableAutomaticPushCapability = EditorGUILayout.ToggleLeft(" Disable Automatic Push Capability", AppboyConfig.IOSDisableAutomaticPushCapability);
+ if (AppboyConfig.IOSDisableAutomaticPushCapability) {
+ EditorGUILayout.LabelField("You will need to manually add the Push Capability to your Xcode project.", EditorStyles.miniBoldLabel);
+ } else {
+ EditorGUILayout.LabelField("Disables adding the Xcode Push Capability automatically.", EditorStyles.wordWrappedMiniLabel);
+ }
+
AppboyConfig.IOSPushIsBackgroundEnabled = EditorGUILayout.ToggleLeft(" Enable Background Push", AppboyConfig.IOSPushIsBackgroundEnabled);
EditorGUILayout.LabelField("Allows the system to wake your app from suspension when a push notification arrives.", EditorStyles.wordWrappedMiniLabel);
diff --git a/Assets/Plugins/Appboy/Editor/PostBuild.cs b/Assets/Plugins/Appboy/Editor/PostBuild.cs
index 587c3470f..72948bfd0 100644
--- a/Assets/Plugins/Appboy/Editor/PostBuild.cs
+++ b/Assets/Plugins/Appboy/Editor/PostBuild.cs
@@ -12,15 +12,16 @@
namespace Appboy.Editor {
public class PostBuild {
#if UNITY_IOS
- private const string ProjectSubpath = "/Unity-iPhone.xcodeproj/project.pbxproj";
private const string AppboyAppDelegatePath = "Libraries/Plugins/iOS/AppboyAppDelegate.mm";
private const string PlistSubpath = "/Info.plist";
+ private const string MainTargetName = "Unity-iPhone";
private const string ABKEndpointKey = "Endpoint";
private const string ABKLogLevelKey = "LogLevel";
private const string ABKUnityApiKey = "ApiKey";
private const string ABKUnityAutomaticPushIntegrationKey = "IntegratesPush";
private const string ABKUnityDisableAutomaticPushRegistrationKey = "DisableAutomaticPushRegistration";
+ private const string ABKUnityDisableProvisionalAuthKey = "DisableProvisionalAuth";
private const string ABKUnityPushReceivedGameObjectKey = "PushReceivedGameObjectName";
private const string ABKUnityPushReceivedCallbackKey = "PushReceivedCallbackMethodName";
private const string ABKUnityPushOpenedGameObjectKey = "PushOpenedGameObjectName";
@@ -34,15 +35,15 @@ public class PostBuild {
private const string ABKUnityHandleInAppMessageDisplayKey = "DisplayInAppMessages";
[PostProcessBuildAttribute(1)]
- public static void OnPostprocessBuild(BuildTarget target, string buildPath) {
+ public static void OnPostprocessBuild(BuildTarget target, string path) {
if (target == BuildTarget.iOS) {
- ModifyProject(buildPath + ProjectSubpath);
- ModifyPlist(buildPath + PlistSubpath);
+ ModifyPlist(path + PlistSubpath);
+ ModifyProject(path);
}
}
- private static void ModifyProject(string projectPath) {
- // Create PBXProject
+ private static void ModifyProject(string path) {
+ var projectPath = PBXProject.GetPBXProjectPath(path);
PBXProject project = new PBXProject();
project.ReadFromString(File.ReadAllText(projectPath));
@@ -78,8 +79,6 @@ private static void ModifyProject(string projectPath) {
"CoreTelephony.framework",
"Social.framework",
"Accounts.framework",
- "AdSupport.framework",
- "StoreKit.framework",
"CoreLocation.framework", // optional for location tracking
"ImageIO.framework", // required by SDWebImage
"MobileCoreServices.framework", // required by FLAnimatedImage
@@ -110,12 +109,42 @@ private static void ModifyProject(string projectPath) {
project.AddBuildProperty(target, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks");
}
+
+ if (AppboyConfig.IOSIntegratesPush && !AppboyConfig.IOSDisableAutomaticPushCapability) {
+ AddPushEntitlement(
+ path,
+ project,
+ targets[0] // the main target
+ );
+ }
}
- // Write changes to XCode project
File.WriteAllText(projectPath, project.WriteToString());
}
+ private static void AddPushEntitlement(string path, PBXProject project, string target) {
+ var entitlements = new PlistDocument();
+
+ string entitlementsFilename = MainTargetName + ".entitlements";
+ string entitlementsRelativePath = MainTargetName + "/" + entitlementsFilename;
+ string entitlementsPath = path + "/" + entitlementsRelativePath;
+
+ if (File.Exists(entitlementsPath)) {
+ entitlements.ReadFromFile(entitlementsPath);
+ }
+
+ if (entitlements.root["aps-environment"] != null) {
+ return;
+ } else {
+ entitlements.root.SetString("aps-environment", "development");
+ }
+
+ project.AddFile(entitlementsRelativePath, entitlementsFilename);
+ entitlements.WriteToFile(entitlementsPath);
+
+ project.AddBuildProperty(target, "CODE_SIGN_ENTITLEMENTS", entitlementsRelativePath);
+ }
+
private static void AddFileToEmbedFrameworks(PBXProject project, string target, string unityPath, string xcodePath) {
string frameworkPath = project.AddFile(unityPath, xcodePath, PBXSourceTree.Source);
project.AddFileToBuild(target, frameworkPath);
@@ -162,6 +191,7 @@ private static void ModifyPlist(string plistPath) {
PlistElementArray backgroundModes = (rootDict["UIBackgroundModes"] == null) ? rootDict.CreateArray("UIBackgroundModes") : rootDict["UIBackgroundModes"].AsArray();
backgroundModes.AddString("remote-notification");
}
+ appboyUnityDict.SetBoolean(ABKUnityDisableProvisionalAuthKey, AppboyConfig.IOSDisableProvisionalAuth);
// Set push listeners
if (ValidateListenerFields(ABKUnityPushReceivedGameObjectKey, AppboyConfig.IOSPushReceivedGameObjectName,
@@ -204,7 +234,7 @@ private static void ModifyPlist(string plistPath) {
}
private static void DisplayInvalidSettingsWarning(string key, string details) {
- EditorUtility.DisplayDialog("Invalid Appboy Settings", "The " + Regex.Replace(key, @"\B[A-Z]", " $0") + " is blank. " + details + " Set this field in Braze > Braze Configuration.", "OK");
+ EditorUtility.DisplayDialog("Invalid Braze Settings", "The " + Regex.Replace(key, @"\B[A-Z]", " $0") + " is blank. " + details + " Set this field in Braze > Braze Configuration.", "OK");
}
private static bool ValidateField(string key, string value, string errorDetails) {
diff --git a/Assets/Plugins/Appboy/Internal.meta b/Assets/Plugins/Appboy/Internal.meta
new file mode 100644
index 000000000..b9d548f13
--- /dev/null
+++ b/Assets/Plugins/Appboy/Internal.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ab5b022ad07294763b86968c6e01168b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/Internal/BrazeInternalComponent.cs b/Assets/Plugins/Appboy/Internal/BrazeInternalComponent.cs
new file mode 100644
index 000000000..f259bf497
--- /dev/null
+++ b/Assets/Plugins/Appboy/Internal/BrazeInternalComponent.cs
@@ -0,0 +1,30 @@
+using System;
+using UnityEngine;
+
+namespace Appboy.Internal {
+ public class BrazeInternalComponent : MonoBehaviour {
+
+ private PushPromptResponseReceived pushPromptResponseReceived;
+ private PushTokenReceivedFromSystem pushTokenReceivedFromSystem;
+
+ public void setPushPromptResponseReceivedDelegate(PushPromptResponseReceived responseDelegate) {
+ pushPromptResponseReceived = responseDelegate;
+ }
+
+ public void setPushTokenReceivedFromSystemDelegate(PushTokenReceivedFromSystem responseDelegate) {
+ pushTokenReceivedFromSystem = responseDelegate;
+ }
+
+ public void onPushPromptResponseReceived(String response) {
+ if (pushPromptResponseReceived != null) {
+ pushPromptResponseReceived(Convert.ToBoolean(response));
+ }
+ }
+
+ public void onPushTokenReceivedFromSystem(String token) {
+ if (pushTokenReceivedFromSystem != null) {
+ pushTokenReceivedFromSystem(token);
+ }
+ }
+ }
+}
diff --git a/Assets/Plugins/Appboy/Internal/BrazeInternalComponent.cs.meta b/Assets/Plugins/Appboy/Internal/BrazeInternalComponent.cs.meta
new file mode 100644
index 000000000..30c56d908
--- /dev/null
+++ b/Assets/Plugins/Appboy/Internal/BrazeInternalComponent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 006e4d620bf2d4c11befcede36edae3f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/Internal/BrazeInternalGameObject.cs b/Assets/Plugins/Appboy/Internal/BrazeInternalGameObject.cs
new file mode 100644
index 000000000..a611d8808
--- /dev/null
+++ b/Assets/Plugins/Appboy/Internal/BrazeInternalGameObject.cs
@@ -0,0 +1,30 @@
+using System;
+using UnityEngine;
+
+namespace Appboy.Internal {
+ public class BrazeInternalGameObject : MonoBehaviour {
+
+ private static GameObject instance;
+
+ private static GameObject Instance {
+ get {
+ if (instance == null) {
+ instance = new GameObject("BrazeInternalCallback");
+ instance.AddComponent();
+ DontDestroyOnLoad(instance);
+ }
+ return instance;
+ }
+ }
+
+ public static void setPushPromptResponseReceivedDelegate(PushPromptResponseReceived responseDelegate) {
+ BrazeInternalComponent internalComponent = Instance.GetComponent();
+ internalComponent.setPushPromptResponseReceivedDelegate(responseDelegate);
+ }
+
+ public static void setPushTokenReceivedFromSystemDelegate(PushTokenReceivedFromSystem responseDelegate) {
+ BrazeInternalComponent internalComponent = Instance.GetComponent();
+ internalComponent.setPushTokenReceivedFromSystemDelegate(responseDelegate);
+ }
+ }
+}
diff --git a/Assets/Plugins/Appboy/Internal/BrazeInternalGameObject.cs.meta b/Assets/Plugins/Appboy/Internal/BrazeInternalGameObject.cs.meta
new file mode 100644
index 000000000..c38eacf3d
--- /dev/null
+++ b/Assets/Plugins/Appboy/Internal/BrazeInternalGameObject.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9874d28efa3d344afa3967391efe52cb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/Tests.meta b/Assets/Plugins/Appboy/Tests.meta
new file mode 100644
index 000000000..c19dbf970
--- /dev/null
+++ b/Assets/Plugins/Appboy/Tests.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 745cb92dce1ef4df79ef620ba31f92cf
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/Tests/AppboyBindingTester.cs b/Assets/Plugins/Appboy/Tests/AppboyBindingTester.cs
index 5667a5624..b9f6dcee2 100755
--- a/Assets/Plugins/Appboy/Tests/AppboyBindingTester.cs
+++ b/Assets/Plugins/Appboy/Tests/AppboyBindingTester.cs
@@ -11,48 +11,47 @@ namespace Appboy {
public class AppboyBindingTester : MonoBehaviour {
void Start() {
+ Debug.Log("AppboyBindingTester starting with component name: " + this.name);
}
void InAppMessageReceivedCallback(string message) {
Debug.Log("InAppMessageReceivedCallback message: " + message);
IInAppMessage inApp = InAppMessageFactory.BuildInAppMessage(message);
Debug.Log("In-app message received: " + inApp);
- // Here we are testing the Unity SDK by manually logging the in-app message's click and impression.
- // We should only log the click and impression when the in-app message isn't displayed by Appboy but in Unity.
- //inApp.LogClicked();
- //inApp.LogImpression();
- if (inApp is IInAppMessageImmersive) {
- IInAppMessageImmersive inAppImmersive = inApp as IInAppMessageImmersive;
- if (inAppImmersive.Buttons != null && inAppImmersive.Buttons.Count > 0) {
- // Here we are testing the Unity SDK by manually logging the in-app message's first button's click.
- // We should only log the button click when the in-app message isn't displayed by Appboy but in Unity.
- //inAppImmersive.LogButtonClicked(inAppImmersive.Buttons[0].ButtonID);
- }
- }
+ }
+
+ void PromptUserForPushPermissionsCallback(string message) {
+ Debug.Log("User push permission prompt result was: " + message);
+ }
+
+ void PushTokenReceivedCallback(string message) {
+ Debug.Log("Push token received: " + message);
}
void PushNotificationReceivedCallback(string message) {
- Debug.Log("PushNotificationReceivedCallback message: " + message);
+ Debug.Log("Push received callback for Android received: " + message);
PushNotification pushNotification = new PushNotification(message);
- Debug.Log("Push Notification received: " + pushNotification);
+ Debug.Log("Push received message parsed into json: " + pushNotification);
}
void PushNotificationOpenedCallback(string message) {
- Debug.Log("PushNotificationOpenedCallback message: " + message);
+ Debug.Log("Push opened callback for Android received: " + message);
PushNotification pushNotification = new PushNotification(message);
- Debug.Log("Push Notification opened: " + pushNotification);
+ Debug.Log("Push opened message parsed into json: " + pushNotification);
}
void PushNotificationReceivedCallbackForiOS(string message) {
+ Debug.Log("Push received callback for iOS received: " + message);
JSONClass pushNotificationJson = (JSONClass)JSON.Parse(message);
ApplePushNotification pushNotification = new ApplePushNotification(pushNotificationJson);
- Debug.Log("Push received Notification event: " + pushNotification);
+ Debug.Log("Push received message parsed into json: " + pushNotification);
}
void PushNotificationOpenedCallbackForiOS(string message) {
+ Debug.Log("Push opened callback for iOS received: " + message);
JSONClass pushNotificationJson = (JSONClass)JSON.Parse(message);
ApplePushNotification pushNotification = new ApplePushNotification(pushNotificationJson);
- Debug.Log("Push opened Notification event: " + pushNotification);
+ Debug.Log("Push opened message parsed into json: " + pushNotification);
}
void FeedReceivedCallback(string message) {
@@ -71,7 +70,7 @@ void ContentCardsReceivedCallback(string message) {
JSONClass json = (JSONClass)JSON.Parse(message);
if (json["mContentCards"] != null) {
JSONArray jsonArray = (JSONArray)JSON.Parse(json["mContentCards"].ToString());
- Debug.Log(String.Format("Parsed content cards array with {0} cards", jsonArray.Count));
+ Debug.Log(String.Format("Parsing Content Cards array of size {0}", jsonArray.Count));
for (int i = 0; i < jsonArray.Count; i++) {
JSONClass cardJson = jsonArray[i].AsObject;
try {
diff --git a/Assets/Plugins/Appboy/Utilities.meta b/Assets/Plugins/Appboy/Utilities.meta
new file mode 100644
index 000000000..79b09fe9d
--- /dev/null
+++ b/Assets/Plugins/Appboy/Utilities.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 581060ca2af7c4a3680c5237d918720f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/models.meta b/Assets/Plugins/Appboy/models.meta
new file mode 100644
index 000000000..6017bdfd5
--- /dev/null
+++ b/Assets/Plugins/Appboy/models.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 78b8d94eadfe241f0976ce862b0b5e64
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/models/AppboyNotificationSubscriptionType.cs b/Assets/Plugins/Appboy/models/AppboyNotificationSubscriptionType.cs
index e584d9336..931bf87f3 100644
--- a/Assets/Plugins/Appboy/models/AppboyNotificationSubscriptionType.cs
+++ b/Assets/Plugins/Appboy/models/AppboyNotificationSubscriptionType.cs
@@ -1,9 +1,22 @@
using System.Collections;
namespace Appboy.Models {
+
+ ///
+ /// User opt-in states.
+ ///
public enum AppboyNotificationSubscriptionType {
+ ///
+ /// The user has explicitly opted-in.
+ ///
OPTED_IN = 0,
+ ///
+ /// The user is subscribed but has not explicitly opted-in.
+ ///
SUBSCRIBED = 1,
+ ///
+ /// The user is unsubscribed or has opted-out.
+ ///
UNSUBSCRIBED = 2
}
}
diff --git a/Assets/Plugins/Appboy/models/Cards.meta b/Assets/Plugins/Appboy/models/Cards.meta
new file mode 100644
index 000000000..624772e27
--- /dev/null
+++ b/Assets/Plugins/Appboy/models/Cards.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 430a0954c4eb64461bdf334343ac7fe7
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/models/Cards/Card.cs b/Assets/Plugins/Appboy/models/Cards/Card.cs
index d9c3d2925..7ed4a0c58 100755
--- a/Assets/Plugins/Appboy/models/Cards/Card.cs
+++ b/Assets/Plugins/Appboy/models/Cards/Card.cs
@@ -48,9 +48,7 @@ public Card(JSONClass json) {
} else {
for (int i = 0; i < jsonArray.Count; i++) {
CardCategory category = (CardCategory)EnumUtils.TryParse(typeof(CardCategory), jsonArray[i], true, CardCategory.NO_CATEGORY);
- if (category != CardCategory.NO_CATEGORY) {
- Categories.Add(category);
- }
+ Categories.Add(category);
}
if (Categories.Count == 0) {
Categories.Add(CardCategory.NO_CATEGORY);
diff --git a/Assets/Plugins/Appboy/models/Feed.cs b/Assets/Plugins/Appboy/models/Feed.cs
index 1734de4c3..14bc86158 100755
--- a/Assets/Plugins/Appboy/models/Feed.cs
+++ b/Assets/Plugins/Appboy/models/Feed.cs
@@ -24,22 +24,22 @@ public Feed(string message) {
json = (JSONClass)JSON.Parse(message);
if (json["mFeedCards"] != null) {
JSONArray jsonArray = (JSONArray)JSON.Parse(json["mFeedCards"].ToString());
- Debug.Log(String.Format("parsed cards array with {0} of cards", jsonArray.Count));
+ Debug.Log(String.Format("Parsing News Feed card array of size {0}.", jsonArray.Count));
for (int i = 0; i < jsonArray.Count; i++) {
JSONClass cardJson = jsonArray[i].AsObject;
try {
- Debug.Log(String.Format("Card NO. {0} json string is {1}", i, cardJson));
+ Debug.Log(String.Format("Parsing card with json: {0}", cardJson));
Card card = Feed.CreateCardFromJson(cardJson);
if (card != null) {
Cards.Add(card);
}
} catch {
- Debug.Log(String.Format("Unable to parse card from {0}", cardJson));
+ Debug.Log(String.Format("Unable to parse card from json: {0}", cardJson));
}
}
}
} catch {
- throw new ArgumentException("Cannot parse feed JSON message.");
+ throw new ArgumentException("Could not parse News Feed json.");
}
IsFromOfflineStorage = json["mFromOfflineStorage"].AsBool;
diff --git a/Assets/Plugins/Appboy/models/InAppMessage.meta b/Assets/Plugins/Appboy/models/InAppMessage.meta
new file mode 100644
index 000000000..76b18beb6
--- /dev/null
+++ b/Assets/Plugins/Appboy/models/InAppMessage.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: df80300b9949a4830a004fc04e20dd68
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/models/InAppMessage/IInAppMessage.cs b/Assets/Plugins/Appboy/models/InAppMessage/IInAppMessage.cs
index 873e31f56..e90bb3cc9 100644
--- a/Assets/Plugins/Appboy/models/InAppMessage/IInAppMessage.cs
+++ b/Assets/Plugins/Appboy/models/InAppMessage/IInAppMessage.cs
@@ -5,59 +5,42 @@
namespace Appboy.Models.InAppMessage {
public interface IInAppMessage {
- // BackgroundColor defines the background color of the in-app message.
Color? BackgroundColor { get; set; }
- // TextColor defines the message text color of the in-app message.
Color? TextColor { get; set; }
- // Icon defines the font awesome unicode string of the Appboy icon.
- // You can choose to display one of the Appboy icons from Appboy dashboard. When you do so, this property will have the
- // unicode string of font awesome.
+ // The font awesome unicode string of the in-app message icon.
string Icon { get; set; }
- // IconColor defines the font color of icon property.
+ // The color of the icon text.
Color? IconColor { get; set; }
- // IconBackgroundColor defines the background color of icon property.
+ // The color of the icon background.
Color? IconBackgroundColor { get; set; }
- // ImageURI defines the URI of the image icon on in-app message.
- // When there is a iconImage defined, the iconImage will be used and the value of property icon will
- // be ignored.
string ImageURI { get; set; }
- // This property defines the message displayed within the in-app message.
string Message { get; set; }
- // This property carries extra data in the form of an dictionary which can be sent down via the Appboy Dashboard.
- // You may want to design and implement a custom handler to access this data depending on your use-case.
Dictionary Extras { get; set; }
- // This property defines the action that will be performed when the in-app message is clicked.
- // See the ClickAction enum documentation above offers additional details.
ClickAction InAppClickAction { get; }
-
- // When the in-app message's InAppClickAction is URI, clicking on the in-app message will redirect to the uri defined
- // in this property.
- //
- // This property can be a HTTP URI or a protocol URI.
+
string URI { get; }
-
- // InAppDismissType defines the dismissal behavior of the in-app message.
+
DismissType InAppDismissType { get; set; }
- // This property defines the number of seconds before the in-app message is automatically dismissed.
+ // The number of seconds that should elapse before the in-app message is automatically dismissed.
int Duration { get; set; }
void LogClicked();
void LogImpression();
- // Set InAppClickAction to be NEWS_FEED or NONE
+ // Use this method for ClickAction.NEWS_FEED or ClickAction.NONE
bool SetInAppClickAction(ClickAction clickAction);
- // Set InAppClickAction to be URI
+ // Use this method for ClickAction.URI
bool SetInAppClickAction(ClickAction clickAction, string uri);
}
}
diff --git a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageBase.cs b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageBase.cs
index 477af1bb4..78667e30c 100644
--- a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageBase.cs
+++ b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageBase.cs
@@ -7,9 +7,6 @@
using UnityEngine;
namespace Appboy.Models.InAppMessage {
-
- // Use InAppMessageFactory.BuildInAppMessage(InAppMessageString) to get the in-app message with correct type from
- // Appboy SDK.
public abstract class InAppMessageBase : IInAppMessage {
private const int DefaultDuration = 5000;
protected string _jsonString;
@@ -17,49 +14,33 @@ public abstract class InAppMessageBase : IInAppMessage {
private bool _impressionLogged = false;
private int _duration;
- // BackgroundColor defines the background color of the in-app message.
+ // The background color of the in-app message.
public Color? BackgroundColor { get; set; }
- // TextColor defines the message text color of the in-app message.
public Color? TextColor { get; set; }
- // Icon defines the font awesome unicode string of the Appboy icon.
- // You can choose to display one of the Appboy icons from Appboy dashboard. When you do so, this property will have the
- // unicode string of font awesome.
+ // The font awesome unicode string of the in-app message icon.
public string Icon { get; set; }
- // IconColor defines the font color of icon property.
+ // The color of the icon text.
public Color? IconColor { get; set; }
- // IconBackgroundColor defines the background color of icon property.
+ // The color of the icon background.
public Color? IconBackgroundColor { get; set; }
- // imageURI defines the URI of the image icon on in-app message.
- // When there is a iconImage defined, the iconImage will be used and the value of property icon will
- // be ignored.
public string ImageURI { get; set; }
- // This property defines the message displayed within the in-app message.
public string Message { get; set; }
- // This property carries extra data in the form of an dictionary which can be sent down via the Appboy Dashboard.
- // You may want to design and implement a custom handler to access this data depending on your use-case.
public Dictionary Extras { get; set; }
- // This property defines the action that will be performed when the in-app message is clicked.
- // See the ClickAction enum documentation above offers additional details.
public ClickAction InAppClickAction { get; private set; }
- // When the in-app message's InAppClickAction is URI, clicking on the in-app message will redirect to the uri defined
- // in this property.
- //
- // This property can be a HTTP URI or a protocol URI.
public string URI { get; private set; }
- // InAppDismissType defines the dismissal behavior of the in-app message.
public DismissType InAppDismissType { get; set; }
- // This property defines the number of seconds before the in-app message is automatically dismissed.
+ // The number of seconds that should elapse before the in-app message is automatically dismissed.
public int Duration {
get {
return _duration;
@@ -81,7 +62,7 @@ protected InAppMessageBase() {
public InAppMessageBase(JSONClass json) {
if (json == null) {
- throw new ArgumentNullException("The JSON Class passed to InAppMessage constructor is null.");
+ throw new ArgumentNullException("Received null JSONClass.");
}
_jsonString = json.ToString();
Message = json[InAppMessageConstants.MessageKey];
@@ -92,7 +73,7 @@ public InAppMessageBase(JSONClass json) {
URI = json[InAppMessageConstants.URIKey];
ImageURI = json[InAppMessageConstants.ImageURLKey];
if (InAppClickAction == ClickAction.URI && URI == null) {
- Debug.Log("The click action cannot be set to URI because the uri is null. Setting click action to NONE.");
+ Debug.Log("Received ClickAction.URI but URI was null. Setting click action to NONE.");
InAppClickAction = ClickAction.NONE;
}
InAppDismissType = (DismissType)EnumUtils.TryParse(typeof(DismissType), json[InAppMessageConstants.DismissTypeKey], true, DismissType.AUTO_DISMISS);
@@ -109,7 +90,7 @@ public void LogClicked() {
_clickLogged = true;
AppboyBinding.LogInAppMessageClicked(_jsonString);
} else {
- Debug.Log("The in-app message already logged a click.");
+ Debug.Log("Already logged a click. Doing nothing.");
}
}
@@ -118,7 +99,7 @@ public void LogImpression() {
_impressionLogged = true;
AppboyBinding.LogInAppMessageImpression(_jsonString);
} else {
- Debug.Log("The in-app message already logged an impression.");
+ Debug.Log("Already logged an impression. Doing nothing.");
}
}
@@ -129,7 +110,7 @@ public bool SetInAppClickAction(ClickAction clickAction) {
URI = null;
return true;
} else {
- Debug.LogError("A non-null URI is required in order to set the InAppClickAction to URI.");
+ Debug.Log("A non-null URI is required in order to set the InAppClickAction to URI.");
return false;
}
}
diff --git a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageButton.cs b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageButton.cs
index 6c97afe34..83531558e 100644
--- a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageButton.cs
+++ b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageButton.cs
@@ -28,7 +28,7 @@ public InAppMessageButton(JSONClass json) {
URI = json[InAppMessageConstants.ButtonURIKey];
ButtonClickAction = (ClickAction)EnumUtils.TryParse(typeof(ClickAction), json[InAppMessageConstants.ButtonClickActionKey], true, ClickAction.NEWS_FEED);
if (ButtonClickAction == ClickAction.URI && URI == null) {
- Debug.Log("The click action cannot be set to URI because the uri is null. Setting click action to NONE.");
+ Debug.Log("Required URI not present for URI click action type. Setting click action to NONE.");
ButtonClickAction = ClickAction.NONE;
}
}
@@ -39,7 +39,7 @@ public bool SetButtonClickAction(ClickAction clickAction) {
URI = null;
return true;
} else {
- Debug.LogError("A non-null URI is required in order to set the ButtonClickAction to URI.");
+ Debug.Log("A non-null URI is required for ClickAction.URI.");
return false;
}
}
diff --git a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageConstants.cs b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageConstants.cs
index 819c1626c..89c9dbb5d 100644
--- a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageConstants.cs
+++ b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageConstants.cs
@@ -4,7 +4,7 @@
namespace Appboy.Models.InAppMessage {
public class InAppMessageConstants {
- // In-app message JSON keys
+ // In-app message base
public const string MessageKey = "message";
public const string ExtrasKey = "extras";
public const string ClickActionKey = "click_action";
@@ -19,17 +19,17 @@ public class InAppMessageConstants {
public const string IconBackgroundColorKey = "icon_bg_color";
public const string TypeKey = "type";
- // In-app message immersive JSON keys
+ // In-app message immersive
public const string HeaderKey = "header";
public const string HeaderTextColorKey = "header_text_color";
public const string CloseButtonColorKey = "close_btn_color";
public const string ButtonsKey = "btns";
- // In-app message slideup jSON keys
+ // In-app message slideup
public const string SlideFromKey = "slide_from";
public const string HideChevronKey = "hide_chevron";
- // In-app message button keys
+ // In-app message buttons
public const string ButtonIDKey = "id";
public const string ButtonTextKey = "text";
public const string ButtonTextColorKey = "text_color";
@@ -37,16 +37,16 @@ public class InAppMessageConstants {
public const string ButtonURIKey = "uri";
public const string ButtonClickActionKey = "click_action";
- // This method parses an in-app message JSON string to be a json object
+ // Safe wrapper for JSON.Parse
public static JSONClass JSONObjectFromString(string JSONString) {
if (String.IsNullOrEmpty(JSONString)) {
- Debug.LogError("Slideup JSON Message cannot be null or empty.");
+ Debug.Log("JSON string was null or empty.");
}
JSONClass json = null;
try {
json = (JSONClass)JSON.Parse(JSONString);
} catch {
- Debug.LogError(String.Format("Cannot parse in-app message JSON message {0}.", JSONString));
+ Debug.Log(String.Format("Could not parse JSON {0}.", JSONString));
}
return json;
}
diff --git a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageFactory.cs b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageFactory.cs
index 9a6622ff0..0eb826192 100644
--- a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageFactory.cs
+++ b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageFactory.cs
@@ -2,13 +2,23 @@
using Appboy.Utilities;
namespace Appboy.Models.InAppMessage {
- // This class is the in-app message builder. Passing the in-app message JSON string from Appboy, and the Builder will
- // return a corresponding InAppMessageSlideup, InAppMessageModal or InAppMessageFull;
public class InAppMessageFactory {
+
+ ///
+ /// Builds in-app message instances from serialized in-app message objects.
+ ///
+ /// Use this method to create a useful model object from the in-app message string
+ /// passed into your gameobject callback.
+ ///
+ ///
+ /// The serialized in-app message object.
+ ///
+ ///
+ /// An IInAppMessage instance populated by the serialized in-app message object.
+ ///
public static IInAppMessage BuildInAppMessage(string inAppMessageJSONString) {
JSONClass json = InAppMessageConstants.JSONObjectFromString(inAppMessageJSONString);
if (json != null) {
- // If the type is specified, create corresponding in-app message, otherwise, create an in-app message slideup.
InAppMessageType type = (InAppMessageType)EnumUtils.TryParse(typeof(InAppMessageType), json[InAppMessageConstants.TypeKey], true, InAppMessageType.SLIDEUP);
switch (type) {
case InAppMessageType.FULL:
diff --git a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageImmersiveBase.cs b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageImmersiveBase.cs
index d2d3f61e9..cdf83c1c1 100644
--- a/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageImmersiveBase.cs
+++ b/Assets/Plugins/Appboy/models/InAppMessage/InAppMessageImmersiveBase.cs
@@ -31,7 +31,7 @@ public InAppMessageImmersiveBase(JSONClass json) : base(json) {
if (json[InAppMessageConstants.ButtonsKey] != null) {
Buttons = new List();
JSONArray jsonArray = (JSONArray)JSON.Parse(json[InAppMessageConstants.ButtonsKey].ToString());
- Debug.Log(String.Format("parse in-app message with {0} buttons", jsonArray.Count));
+ Debug.Log(String.Format("Parsing in-app message with {0} buttons", jsonArray.Count));
for (int i = 0; i < jsonArray.Count; i++) {
JSONClass buttonJson = jsonArray[i].AsObject;
try {
@@ -52,7 +52,7 @@ public void LogButtonClicked(int buttonID) {
_buttonClickLogged = true;
AppboyBinding.LogInAppMessageButtonClicked(_jsonString, buttonID);
} else {
- Debug.Log("The in-app message already log a button clicked.");
+ Debug.Log("Already logged a button click. Doing nothing.");
}
}
}
diff --git a/Assets/Plugins/Appboy/models/obj.meta b/Assets/Plugins/Appboy/models/obj.meta
new file mode 100644
index 000000000..278ed818b
--- /dev/null
+++ b/Assets/Plugins/Appboy/models/obj.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d79af308526e94b638dbb283c6d7f262
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Appboy/obj.meta b/Assets/Plugins/Appboy/obj.meta
new file mode 100644
index 000000000..7f98ed8da
--- /dev/null
+++ b/Assets/Plugins/Appboy/obj.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 57578cce0fa9044b2b8ccda087822d0d
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS.meta b/Assets/Plugins/iOS.meta
new file mode 100644
index 000000000..25a49faba
--- /dev/null
+++ b/Assets/Plugins/iOS.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6d9c7041e643e49958759c15a0d3b847
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/AppboyAppDelegate.mm b/Assets/Plugins/iOS/AppboyAppDelegate.mm
index a3af000e4..fdffca311 100644
--- a/Assets/Plugins/iOS/AppboyAppDelegate.mm
+++ b/Assets/Plugins/iOS/AppboyAppDelegate.mm
@@ -6,66 +6,68 @@
@interface AppboyAppDelegate : UnityAppController
+@property (nonatomic,copy) NSDictionary *brazeUnityPlist;
+
@end
@implementation AppboyAppDelegate : UnityAppController
# pragma mark - UIApplicationDelegate methods
-- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
+- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
[super application:application didFinishLaunchingWithOptions:launchOptions];
NSLog(@"AppboyAppDelegate called from application:didFinishLaunchingWithOptions:");
- [[AppboyUnityManager sharedInstance] parsePlist];
+ self.brazeUnityPlist = [[AppboyUnityManager sharedInstance] parsePlist];
- // Initialize Appboy
+ // Initialize Braze
[Appboy startWithApiKey:[[AppboyUnityManager sharedInstance] getApiKeyFromUnity]
inApplication:application
withLaunchOptions:launchOptions
withAppboyOptions:@{ABKSDKFlavorKey: @(UNITY)}];
// Set listeners
- [[AppboyUnityManager sharedInstance] setListeners];
+ [[AppboyUnityManager sharedInstance] setListenersFromPList];
// Register for push notifications
- [[AppboyUnityManager sharedInstance] registerForRemoteNotifications];
+ if ([self.brazeUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue] &&
+ ![self.brazeUnityPlist[ABKUnityDisableAutomaticPushRegistrationKey] boolValue]) {
+ BOOL provisional = ![self.brazeUnityPlist[ABKUnityDisableProvisionalAuthKey] boolValue];
+ [[AppboyUnityManager sharedInstance] registerForRemoteNotificationsWithProvisional:provisional];
+ }
return YES;
}
-- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
if ([UnityAppController instancesRespondToSelector:@selector(application:didRegisterForRemoteNotificationsWithDeviceToken:)]) {
[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- NSLog(@"AppboyAppDelegate called from application:didRegisterForRemoteNotificationsWithDeviceToken with token %@", deviceToken);
- // Register push token with Appboy
- [[AppboyUnityManager sharedInstance] registerPushToken:deviceToken];
-}
-
-- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
- if ([UnityAppController instancesRespondToSelector:@selector(application:didReceiveRemoteNotification:)]) {
- [super application:application didReceiveRemoteNotification:userInfo];
+ // Register device token with Braze
+ if ([self.brazeUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue]) {
+ NSLog(@"Automatic push integration enabled. Sending device token to Braze: %@", deviceToken);
+ [[AppboyUnityManager sharedInstance] registerPushToken:deviceToken];
+ } else{
+ NSLog(@"Automatic push integration disabled. Ignoring device token %@", deviceToken);
}
- NSLog(@"AppboyAppDelegate called from application:didReceiveRemoteNotification:. UIApplicationState is %ld", (long)[[UIApplication sharedApplication] applicationState]);
-
- // Pass notification to Appboy
- [[AppboyUnityManager sharedInstance] registerApplication:application
- didReceiveRemoteNotification:userInfo
- fetchCompletionHandler:nil];
}
-- (void) application:(UIApplication *)application
- didReceiveRemoteNotification:(NSDictionary *)userInfo
+- (void)application:(UIApplication *)application
+ didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
if ([UnityAppController instancesRespondToSelector:@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]) {
[super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
NSLog(@"AppboyAppDelegate called from application:didReceiveRemoteNotification:fetchCompletionHandler:. UIApplicationState is %ld", (long)[[UIApplication sharedApplication] applicationState]);
- // Pass notification to Appboy
- [[AppboyUnityManager sharedInstance] registerApplication:application
- didReceiveRemoteNotification:userInfo
- fetchCompletionHandler:completionHandler];
+ // Pass notification to Braze
+ if ([self.brazeUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue]) {
+ [[AppboyUnityManager sharedInstance] registerApplication:application
+ didReceiveRemoteNotification:userInfo
+ fetchCompletionHandler:completionHandler];
+ } else {
+ NSLog(@"Automatic push integration disabled. Not forwarding notification.");
+ }
}
@end
diff --git a/Assets/Plugins/iOS/AppboyBinding.m b/Assets/Plugins/iOS/AppboyBinding.m
index fc2a19882..c2469129c 100644
--- a/Assets/Plugins/iOS/AppboyBinding.m
+++ b/Assets/Plugins/iOS/AppboyBinding.m
@@ -5,6 +5,12 @@
char* convertNSStringToCString(const NSString* nsString);
+# pragma mark - Appboy
+
+void _changeUser(const char* userId) {
+ [[Appboy sharedInstance] changeUser:GetStringParam(userId)];
+}
+
void _logCustomEvent(const char* eventName, const char* properties) {
NSMutableDictionary *eventProperties = [NSMutableDictionary dictionaryWithCapacity:1];
if (properties != NULL && properties != nil) {
@@ -14,11 +20,7 @@ void _logCustomEvent(const char* eventName, const char* properties) {
options:NSJSONReadingMutableContainers
error:&jsonError];
}
- [[AppboyUnityManager sharedInstance] logCustomEvent:GetStringParam(eventName) withProperties:eventProperties];
-}
-
-void _changeUser(const char* userId) {
- [[AppboyUnityManager sharedInstance] changeUser:GetStringParam(userId)];
+ [[Appboy sharedInstance] logCustomEvent:GetStringParam(eventName) withProperties:eventProperties];
}
void _logPurchase(const char* productId, const char* currencyCode, const char* price, int quantity, const char* properties) {
@@ -30,134 +32,176 @@ void _logPurchase(const char* productId, const char* currencyCode, const char* p
options:NSJSONReadingMutableContainers
error:&jsonError];
}
- [[AppboyUnityManager sharedInstance] logPurchase:GetStringParam(productId)
- inCurrency:GetStringParam(currencyCode)
- atPrice:GetStringParam(price)
- withQuantity:quantity
- withProperties:purchaseProperties];
+ [[Appboy sharedInstance] logPurchase:GetStringParam(productId)
+ inCurrency:GetStringParam(currencyCode)
+ atPrice:[NSDecimalNumber decimalNumberWithString:GetStringParam(price)]
+ withQuantity:quantity
+ andProperties:(NSDictionary *)purchaseProperties];
+
+}
+
+void _requestGeofences(int latitude, int longitude) {
+ [[Appboy sharedInstance] requestGeofencesWithLongitude:longitude
+ latitude:latitude];
}
+void _requestImmediateDataFlush() {
+ [[Appboy sharedInstance] flushDataAndProcessRequestQueue];
+}
+
+void _addAlias(const char* alias, const char* label) {
+ [[Appboy sharedInstance].user addAlias:GetStringParam(alias) withLabel:GetStringParam(label)];
+}
+
+# pragma mark - ABKUser
+
void _setUserFirstName(const char* firstName) {
- [[AppboyUnityManager sharedInstance] setUserFirstName:GetStringParam(firstName)];
+ [Appboy sharedInstance].user.firstName = GetStringParam(firstName);
}
void _setUserLastName(const char* lastName) {
- [[AppboyUnityManager sharedInstance] setUserLastName:GetStringParam(lastName)];
+ [Appboy sharedInstance].user.lastName = GetStringParam(lastName);
}
void _setUserPhoneNumber(const char* phoneNumber) {
- [[AppboyUnityManager sharedInstance] setUserPhoneNumber:GetStringParam(phoneNumber)];
+ [Appboy sharedInstance].user.phone = GetStringParam(phoneNumber);
}
void _setUserAvatarImageURL(const char* imageURL) {
- [[AppboyUnityManager sharedInstance] setUserAvatarImageURL:GetStringParam(imageURL)];
+ [Appboy sharedInstance].user.avatarImageURL = GetStringParam(imageURL);
}
void _setUserEmail(const char* email) {
- [[AppboyUnityManager sharedInstance] setUserEmail:GetStringParam(email)];
-}
-
-void _setUserBio(const char* bio) {
- [[AppboyUnityManager sharedInstance] setUserBio:GetStringParam(bio)];
+ [Appboy sharedInstance].user.email = GetStringParam(email);
}
void _setUserGender(int gender) {
- [[AppboyUnityManager sharedInstance] setUserGender:gender];
+ [[Appboy sharedInstance].user setGender:(ABKUserGenderType)gender];
}
void _setUserDateOfBirth(int year, int month, int day) {
- [[AppboyUnityManager sharedInstance] setUserDateOfBirthToYear:year Month:month andDay:day];
+ NSDateComponents *comps = [[NSDateComponents alloc] init];
+ [comps setDay:day];
+ [comps setMonth:month];
+ [comps setYear:year];
+ NSCalendar *gregorian = [[NSCalendar alloc]
+ initWithCalendarIdentifier:NSGregorianCalendar];
+ NSDate *date = [gregorian dateFromComponents:comps];
+ [Appboy sharedInstance].user.dateOfBirth = date;
}
void _setUserCountry(const char* country) {
- [[AppboyUnityManager sharedInstance] setUserCountry:GetStringParam(country)];
+ [Appboy sharedInstance].user.country = GetStringParam(country);
}
void _setUserHomeCity(const char* city) {
- [[AppboyUnityManager sharedInstance] setUserHomeCity:GetStringParam(city)];
-}
-
-void _setUserIsSubscribedToEmails(bool isSubscribedToEmails) {
- [[AppboyUnityManager sharedInstance] setUserIsSubscribedToEmails:isSubscribedToEmails];
+ [Appboy sharedInstance].user.homeCity = GetStringParam(city);
}
void _setUserEmailNotificationSubscriptionType(int emailNotificationSubscriptionType) {
- [[AppboyUnityManager sharedInstance] setUserEmailNotificationSubscriptionType:emailNotificationSubscriptionType];
+ [[Appboy sharedInstance].user setEmailNotificationSubscriptionType:(ABKNotificationSubscriptionType)emailNotificationSubscriptionType];
}
void _setUserPushNotificationSubscriptionType(int pushNotificationSubscriptionType) {
- [[AppboyUnityManager sharedInstance] setUserPushNotificationSubscriptionType:pushNotificationSubscriptionType];
+ [[Appboy sharedInstance].user setPushNotificationSubscriptionType:(ABKNotificationSubscriptionType)pushNotificationSubscriptionType];
}
-void _setCustomUserAttributeBool(const char* key, bool val) {
- [[AppboyUnityManager sharedInstance] setUserCustomAttributeWithKey:GetStringParam(key) andBOOLValue:val];
+void _setCustomUserAttributeBool(const char* key, bool value) {
+ [[Appboy sharedInstance].user setCustomAttributeWithKey:GetStringParam(key) andBOOLValue:value];
}
-void _setCustomUserAttributeInt(const char* key, int val) {
- [[AppboyUnityManager sharedInstance] setUserCustomAttributeWithKey:GetStringParam(key) andIntegerValue:val];
+void _setCustomUserAttributeInt(const char* key, int value) {
+ [[Appboy sharedInstance].user setCustomAttributeWithKey:GetStringParam(key) andIntegerValue:value];
}
-void _setCustomUserAttributeFloat(const char* key, float val) {
- NSString *floatString = [NSString stringWithFormat:@"%f", val];
- [[AppboyUnityManager sharedInstance] setUserCustomAttributeWithKey:GetStringParam(key) andDoubleValue:[floatString doubleValue]];
+void _setCustomUserAttributeFloat(const char* key, float value) {
+ NSString *floatString = [NSString stringWithFormat:@"%f", value];
+ [[Appboy sharedInstance].user setCustomAttributeWithKey:GetStringParam(key) andDoubleValue:[floatString doubleValue]];
}
-void _setCustomUserAttributeString(const char* key, const char* val) {
- [[AppboyUnityManager sharedInstance] setUserCustomAttributeWithKey:GetStringParam(key) andStringValue:GetStringParam(val)];
+void _setCustomUserAttributeString(const char* key, const char* value) {
+ [[Appboy sharedInstance].user setCustomAttributeWithKey:GetStringParam(key) andStringValue:GetStringParam(value)];
}
void _setCustomUserAttributeToNow(const char* key) {
- [[AppboyUnityManager sharedInstance] setUserCustomAttributeToNowWithKey:GetStringParam(key)];
+ [[Appboy sharedInstance].user setCustomAttributeWithKey:GetStringParam(key) andDateValue:[NSDate date]];
}
void _setCustomUserAttributeToSecondsFromEpoch(const char* key, long seconds) {
- [[AppboyUnityManager sharedInstance] setUserCustomAttributeWithKey:GetStringParam(key) toDateAsSecondsFromEpoch:(NSTimeInterval)seconds];
+ [[Appboy sharedInstance].user setCustomAttributeWithKey:GetStringParam(key) andDateValue:[NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)seconds]];
}
void _unsetCustomUserAttribute(const char* key) {
- [[AppboyUnityManager sharedInstance] unsetUserCustomAttributeWithKey:GetStringParam(key)];
+ [[Appboy sharedInstance].user unsetCustomAttributeWithKey:GetStringParam(key)];
}
void _incrementCustomUserAttribute(const char* key, int incrementValue) {
- [[AppboyUnityManager sharedInstance] incrementCustomUserAttributeWithKey:GetStringParam(key) by:incrementValue];
+ [[Appboy sharedInstance].user incrementCustomUserAttribute:GetStringParam(key) by:incrementValue];
}
void _setCustomUserAttributeArray(const char* key, const char* array[], int size) {
if (array == NULL || array == nil) {
- [[AppboyUnityManager sharedInstance] setCustomAttributeArrayWithKey:GetStringParam(key)
- array:nil];
+ [[Appboy sharedInstance].user setCustomAttributeArrayWithKey:GetStringParam(key) array:nil];
} else if (size == 0) {
- [[AppboyUnityManager sharedInstance] setCustomAttributeArrayWithKey:GetStringParam(key)
- array:[NSMutableArray arrayWithCapacity:1]];
+ [[Appboy sharedInstance].user setCustomAttributeArrayWithKey:GetStringParam(key) array:[NSMutableArray arrayWithCapacity:1]];
} else {
NSMutableArray *customAttributeArray = [NSMutableArray arrayWithCapacity:size];
for (int i = 0; i < size; i ++) {
NSString *value = GetStringParam(array[i]);
[customAttributeArray addObject:value];
}
- [[AppboyUnityManager sharedInstance] setCustomAttributeArrayWithKey:GetStringParam(key)
- array:customAttributeArray];
+ [[Appboy sharedInstance].user setCustomAttributeArrayWithKey:GetStringParam(key) array:customAttributeArray];
}
}
void _addToCustomUserAttributeArray(const char* key, const char* value) {
- [[AppboyUnityManager sharedInstance] addToCustomAttributeArrayWithKey:GetStringParam(key) value:GetStringParam(value)];
+ [[Appboy sharedInstance].user addToCustomAttributeArrayWithKey:GetStringParam(key) value:GetStringParam(value)];
}
void _removeFromCustomUserAttributeArray(const char* key, const char* value) {
- [[AppboyUnityManager sharedInstance] removeFromCustomAttributeArrayWithKey:GetStringParam(key) value:GetStringParam(value)];
+ [[Appboy sharedInstance].user removeFromCustomAttributeArrayWithKey:GetStringParam(key) value:GetStringParam(value)];
}
+void _setAttributionData(const char* network, const char* campaign,const char* adgroup, const char* creative) {
+ ABKAttributionData *attributionData = [[ABKAttributionData alloc]
+ initWithNetwork:GetStringParam(network)
+ campaign:GetStringParam(campaign)
+ adGroup:GetStringParam(adgroup)
+ creative:GetStringParam(creative)];
+ [[Appboy sharedInstance].user setAttributionData:attributionData];
+}
+
+# pragma mark - Social Media
void _setUserFacebookData(const char* facebookId, const char* firstName, const char* lastName, const char* email,
const char* bio, const char* cityName, int gender, int numberOfFriends, const char* birthday) {
- [[AppboyUnityManager sharedInstance] setUserFacebookData:GetStringParam(facebookId) firstName:GetStringParam(firstName) lastName:GetStringParam(lastName) email:GetStringParam(email)
- bio:GetStringParam(bio) cityName:GetStringParam(cityName) gender:gender numberOfFriends:numberOfFriends birthday:GetStringParam(birthday)];
+ [[AppboyUnityManager sharedInstance] setUserFacebookData:GetStringParam(facebookId)
+ firstName:GetStringParam(firstName)
+ lastName:GetStringParam(lastName)
+ email:GetStringParam(email)
+ bio:GetStringParam(bio)
+ cityName:GetStringParam(cityName)
+ gender:gender
+ numberOfFriends:numberOfFriends
+ birthday:GetStringParam(birthday)];
}
void _setUserTwitterData(int twitterUserId, const char* twitterHandle, const char* name, const char* description, int followerCount,
int followingCount, int tweetCount, const char* profileImageUrl) {
- [[AppboyUnityManager sharedInstance] setUserTwitterData:twitterUserId twitterHandle:GetStringParam(twitterHandle) name:GetStringParam(name) description:GetStringParam(description) followerCount:followerCount followingCount:followingCount tweetCount:tweetCount profileImageUrl:GetStringParam(profileImageUrl)];
+ [[AppboyUnityManager sharedInstance] setUserTwitterData:twitterUserId
+ twitterHandle:GetStringParam(twitterHandle)
+ name:GetStringParam(name)
+ description:GetStringParam(description)
+ followerCount:followerCount
+ followingCount:followingCount
+ tweetCount:tweetCount
+ profileImageUrl:GetStringParam(profileImageUrl)];
+}
+
+# pragma mark - In-app message analytics
+
+void _logInAppMessageImpression(const char* inAppMessageJSONString) {
+ [[AppboyUnityManager sharedInstance] logInAppMessageImpression:GetStringParam(inAppMessageJSONString)];
}
void _logInAppMessageClicked(const char* inAppMessageJSONString) {
@@ -168,10 +212,14 @@ void _logInAppMessageButtonClicked(const char* inAppMessageJSONString, int butto
[[AppboyUnityManager sharedInstance] logInAppMessageButtonClicked:GetStringParam(inAppMessageJSONString) withButtonID:buttonID];
}
-void _logInAppMessageImpression(const char* inAppMessageJSONString) {
- [[AppboyUnityManager sharedInstance] logInAppMessageImpression:GetStringParam(inAppMessageJSONString)];
+# pragma mark - In-app message display
+
+void _displayNextInAppMessage(bool withDelegate) {
+ [[AppboyUnityManager sharedInstance] displayNextInAppMessageWithDelegate:withDelegate];
}
+# pragma mark - News Feed analytics
+
void _logCardImpression(const char* cardJSONString) {
[[AppboyUnityManager sharedInstance] logCardImpression:GetStringParam(cardJSONString)];
}
@@ -180,6 +228,12 @@ void _logCardClicked(const char* cardJSONString) {
[[AppboyUnityManager sharedInstance] logCardClicked:GetStringParam(cardJSONString)];
}
+void _logFeedDisplayed() {
+ [[Appboy sharedInstance] logFeedDisplayed];
+}
+
+# pragma mark - News Feed refresh
+
void _requestFeedRefresh() {
[[AppboyUnityManager sharedInstance] requestFeedRefresh];
}
@@ -188,6 +242,8 @@ void _requestFeedRefreshFromCache() {
[[AppboyUnityManager sharedInstance] requestFeedFromCache:nil];
}
+# pragma mark - Content Card analytics
+
void _logContentCardImpression(const char* cardJSONString) {
[[AppboyUnityManager sharedInstance] logContentCardImpression:GetStringParam(cardJSONString)];
}
@@ -200,10 +256,12 @@ void _logContentCardDismissed(const char* cardJSONString) {
[[AppboyUnityManager sharedInstance] logContentCardDismissed:GetStringParam(cardJSONString)];
}
-void _logFeedDisplayed() {
- [[AppboyUnityManager sharedInstance] logFeedDisplayed];
+void _logContentCardsDisplayed() {
+ [[Appboy sharedInstance] logContentCardsDisplayed];
}
+# pragma mark - Content Card refresh
+
void _requestContentCardsRefresh() {
[[AppboyUnityManager sharedInstance] requestContentCardsRefresh];
}
@@ -212,52 +270,45 @@ void _requestContentCardsRefreshFromCache() {
[[AppboyUnityManager sharedInstance] requestContentCardsFromCache:nil];
}
-void _logContentCardsDisplayed() {
- [[AppboyUnityManager sharedInstance] logContentCardsDisplayed];
-}
-
-void _displayNextInAppMessage(bool withDelegate) {
- [[AppboyUnityManager sharedInstance] displayNextInAppMessageWithDelegate:withDelegate];
-}
+# pragma mark - Data management
void _wipeData() {
- [AppboyUnityManager wipeDataAndDisableForAppRun];
+ [Appboy wipeDataAndDisableForAppRun];
}
void _enableSDK() {
- [AppboyUnityManager requestEnableSDKOnNextAppRun];
+ [Appboy disableSDK];
}
void _disableSDK() {
- [AppboyUnityManager disableSDK];
+ [Appboy requestEnableSDKOnNextAppRun];
}
-void _setAttributionData(const char* network, const char* campaign,const char* adgroup, const char* creative) {
- [[AppboyUnityManager sharedInstance] setAttributionData:GetStringParam(network) campaign:GetStringParam(campaign) adgroup:GetStringParam(adgroup) creative:GetStringParam(creative)];
-}
+# pragma mark - Push
-void _requestGeofences(int latitude, int longitude) {
- [[Appboy sharedInstance] requestGeofencesWithLongitude:longitude
- latitude:latitude];
+void _registerAppboyPushMessages(const char* tokenBase64) {
+ [[AppboyUnityManager sharedInstance] registerPushTokenBase64:GetStringParam(tokenBase64)];
}
-void _requestImmediateDataFlush() {
- [[Appboy sharedInstance] flushDataAndProcessRequestQueue];
+void _promptUserForPushPermissions(bool provisional) {
+ [[AppboyUnityManager sharedInstance] registerForRemoteNotificationsWithProvisional:provisional];
}
-void _registerAppboyPushMessages(const char* tokenBase64) {
- [[AppboyUnityManager sharedInstance] registerPushTokenBase64:GetStringParam(tokenBase64)];
-}
+# pragma mark - Device Id
char* _getInstallTrackingId() {
NSString* deviceId = [[Appboy sharedInstance] getDeviceId];
return convertNSStringToCString(deviceId);
}
-void _addAlias(const char* alias, const char* label) {
- [[AppboyUnityManager sharedInstance] addAlias:GetStringParam(alias) withLabel:GetStringParam(label)];
+# pragma mark - Gameobject callbacks
+
+void _configureListener(int messageType, const char* gameobject, const char* method) {
+ [[AppboyUnityManager sharedInstance] configureListenerFor:messageType withGameObject:GetStringParam(gameobject) withMethod:GetStringParam(method)];
}
+# pragma mark - Internal
+
char* convertNSStringToCString(const NSString* nsString) {
if (nsString == NULL) {
return NULL;
@@ -269,3 +320,7 @@ void _addAlias(const char* alias, const char* label) {
return cString;
}
+
+void _configureInternalListener(int messageType) {
+ [[AppboyUnityManager sharedInstance] configureInternalListenerFor:messageType];
+}
diff --git a/Assets/Plugins/iOS/AppboyUnityManager.h b/Assets/Plugins/iOS/AppboyUnityManager.h
index 67cd3fdd6..f5acba03d 100644
--- a/Assets/Plugins/iOS/AppboyUnityManager.h
+++ b/Assets/Plugins/iOS/AppboyUnityManager.h
@@ -4,6 +4,7 @@
static NSString *const ABKUnityApiKey = @"ApiKey";
static NSString *const ABKUnityAutomaticPushIntegrationKey = @"IntegratesPush";
static NSString *const ABKUnityDisableAutomaticPushRegistrationKey = @"DisableAutomaticPushRegistration";
+static NSString *const ABKUnityDisableProvisionalAuthKey = @"DisableProvisionalAuth";
static NSString *const ABKUnitySetPushListenerKey = @"SetPushListener";
static NSString *const ABKUnityPushReceivedGameObjectKey = @"PushReceivedGameObjectName";
static NSString *const ABKUnityPushReceivedCallbackKey = @"PushReceivedCallbackMethodName";
@@ -17,6 +18,20 @@ static NSString *const ABKUnityContentCardsGameObjectKey = @"ContentCardsGameObj
static NSString *const ABKUnityContentCardsCallbackKey = @"ContentCardsCallbackMethodName";
static NSString *const ABKUnityHandleInAppMessageDisplayKey = @"DisplayInAppMessages";
+/**
+ * These must correspond 1:1 to BrazeUnityMessageType in AppboyBinding.cs.
+ */
+typedef NS_ENUM(NSInteger, ABKUnityMessageType) {
+ ABKPushPermissionsPromptResponse = 0,
+ ABKPushTokenReceivedFromSystem = 1,
+ ABKPushReceived = 2,
+ ABKPushOpened = 3,
+ ABKPushDeleted = 4,
+ ABKInAppMessageReceived = 5,
+ ABKNewsFeedUpdated = 6,
+ ABKContentCardsUpdated = 7
+};
+
@interface AppboyUnityManager : NSObject
@property (nonatomic,copy) NSDictionary *appboyUnityPlist;
@@ -30,71 +45,90 @@ static NSString *const ABKUnityHandleInAppMessageDisplayKey = @"DisplayInAppMess
@property (nonatomic, copy) NSString *unityPushReceivedCallbackFunctionName;
@property (nonatomic, copy) NSString *unityPushOpenedGameObjectName;
@property (nonatomic, copy) NSString *unityPushOpenedCallbackFunctionName;
+@property (nonatomic, copy) NSString *unityPushPermissionsPromptResponseGameObjectName;
+@property (nonatomic, copy) NSString *unityPushPermissionsPromptResponseFunctionName;
+@property (nonatomic, copy) NSString *unityPushTokenReceivedFromSystemGameObjectName;
+@property (nonatomic, copy) NSString *unityPushTokenReceivedFromSystemFunctionName;
+@property (nonatomic) BOOL sendInternalPushPermissionsPromptResponse;
+@property (nonatomic) BOOL sendPushTokenReceivedFromSystem;
+ (AppboyUnityManager *) sharedInstance;
-- (void) showStreamView;
-- (void) logCustomEvent:(NSString *)eventName withProperties:(NSDictionary *)properties;
-- (void) changeUser:(NSString *)userId;
-- (void) logPurchase:(NSString *)productId inCurrency:(NSString *)currencyCode
- atPrice:(NSString *)price withQuantity:(NSUInteger)quantity withProperties:(NSDictionary *)properties;
-- (void) setUserFirstName:(NSString *)firstName;
-- (void) setUserLastName:(NSString *)lastName;
-- (void) setUserPhoneNumber:(NSString *)number;
-- (void) setUserAvatarImageURL:(NSString *)imageURL;
-- (void) setUserEmail:(NSString *)email;
-- (void) setUserBio:(NSString *)bio;
-- (void) setUserGender:(NSInteger)gender;
-- (void) setUserDateOfBirthToYear:(NSInteger)year Month:(NSInteger)month andDay:(NSInteger)day;
-- (void) setUserCountry:(NSString *)country;
-- (void) setUserHomeCity:(NSString *)city;
-- (void) setUserIsSubscribedToEmails:(BOOL)subscribedToEmail;
-- (void) setUserEmailNotificationSubscriptionType:(NSInteger)emailNotificationSubscriptionType;
-- (void) setUserPushNotificationSubscriptionType:(NSInteger)pushNotificationSubscriptionType;
-- (void) setUserCustomAttributeWithKey:(NSString *)key andBOOLValue:(BOOL)value;
-- (void) setUserCustomAttributeWithKey:(NSString *)key andIntegerValue:(NSInteger)value;
-- (void) setUserCustomAttributeWithKey:(NSString *)key andDoubleValue:(double)value;
-- (void) setUserCustomAttributeWithKey:(NSString *)key andStringValue:(NSString *)value;
-- (void) setUserCustomAttributeToNowWithKey:(NSString *)key;
-- (void) setUserCustomAttributeWithKey:(NSString *)key toDateAsSecondsFromEpoch:(NSTimeInterval)seconds;
-- (void) unsetUserCustomAttributeWithKey:(NSString *)key;
-- (void) incrementCustomUserAttributeWithKey:(NSString *)key by:(NSInteger)incrementValue;
-- (void) setCustomAttributeArrayWithKey:(NSString *)key array:(NSArray *)valueArray;
-- (void) addToCustomAttributeArrayWithKey:(NSString *)key value:(NSString *)value;
-- (void) removeFromCustomAttributeArrayWithKey:(NSString *)key value:(NSString *)value;
-- (void) setAttributionData:(NSString *)network campaign:(NSString *)campaign adgroup:(NSString *)adgroup creative:(NSString *)creative;
-- (void) setUserFacebookData:(NSString *)facebookId firstName:(NSString *)firstName lastName:(NSString *)lastName email:(NSString *)email bio:(NSString *)bio cityName:(NSString *)cityName gender:(NSInteger)gender numberOfFriends:(NSInteger)numberOfFriends birthday:(NSString *)birthday;
-- (void) setUserTwitterData:(NSInteger)twitterUserId twitterHandle:(NSString *)twitterHandle name:(NSString *)name description:(NSString *)description followerCount:(NSInteger)followerCount followingCount:(NSInteger)followingCount tweetCount:(NSInteger)tweetCount profileImageUrl:(NSString *)profileImageUrl;
-- (void) parsePlist;
-- (NSString *) getApiKeyFromUnity;
-- (void) setListeners;
-- (void) addInAppMessageListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
-- (void) addFeedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
-- (void) addContentCardsListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
-- (void) addPushReceivedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
-- (void) addPushOpenedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
-- (void) registerForRemoteNotifications;
-- (void) registerPushToken:(NSData *)deviceToken;
-- (void) registerPushTokenBase64:(NSString *)deviceTokenBase64;
-- (void) registerApplication:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
-- (void) logInAppMessageClicked:(NSString *)inAppMessageJSONString;
-- (void) logInAppMessageButtonClicked:(NSString *)inAppMessageJSONString withButtonID:(NSInteger)buttonID;
-- (void) logInAppMessageImpression:(NSString *)inAppMessageJSONString;
-- (void) logCardImpression:(NSString *)cardJSONString;
-- (void) logCardClicked:(NSString *)cardJSONString;
-- (void) requestFeedRefresh;
-- (void) requestFeedFromCache:(NSNotification *)notification;
-- (void) logFeedDisplayed;
-- (void) requestContentCardsRefresh;
-- (void) requestContentCardsFromCache:(NSNotification *)notification;
-- (void) logContentCardsDisplayed;
-- (void) logContentCardImpression:(NSString *)cardJSONString;
-- (void) logContentCardClicked:(NSString *)cardJSONString;
-- (void) logContentCardDismissed:(NSString *)cardJSONString;
-- (void) displayNextInAppMessageWithDelegate:(BOOL)withDelegate;
-- (void) requestGeofences;
-- (void) requestImmediateDataFlush;
-- (void) addAlias:(NSString *)alias withLabel:(NSString *)label;
-+ (void) wipeDataAndDisableForAppRun;
-+ (void) disableSDK;
-+ (void) requestEnableSDKOnNextAppRun;
+- (NSString *)getApiKeyFromUnity;
+- (NSDictionary *)parsePlist;
+
+// Social
+- (void)setUserFacebookData:(NSString *)facebookId firstName:(NSString *)firstName lastName:(NSString *)lastName email:(NSString *)email bio:(NSString *)bio cityName:(NSString *)cityName gender:(NSInteger)gender numberOfFriends:(NSInteger)numberOfFriends birthday:(NSString *)birthday;
+- (void)setUserTwitterData:(NSInteger)twitterUserId twitterHandle:(NSString *)twitterHandle name:(NSString *)name description:(NSString *)description followerCount:(NSInteger)followerCount followingCount:(NSInteger)followingCount tweetCount:(NSInteger)tweetCount profileImageUrl:(NSString *)profileImageUrl;
+
+// In-app messages
+- (void)logInAppMessageImpression:(NSString *)inAppMessageJSONString;
+- (void)logInAppMessageClicked:(NSString *)inAppMessageJSONString;
+- (void)logInAppMessageButtonClicked:(NSString *)inAppMessageJSONString withButtonID:(NSInteger)buttonID;
+- (void)displayNextInAppMessageWithDelegate:(BOOL)withDelegate;
+
+// News Feed
+- (void)logCardImpression:(NSString *)cardJSONString;
+- (void)logCardClicked:(NSString *)cardJSONString;
+- (void)requestFeedRefresh;
+- (void)requestFeedFromCache:(NSNotification *)notification;
+
+// Content Cards
+- (void)logContentCardImpression:(NSString *)cardJSONString;
+- (void)logContentCardClicked:(NSString *)cardJSONString;
+- (void)logContentCardDismissed:(NSString *)cardJSONString;
+- (void)requestContentCardsRefresh;
+- (void)requestContentCardsFromCache:(NSNotification *)notification;
+
+/*!
+ * @discussion Passes the device token to Braze. The caller is responsible for respecting
+ * automatic integration and automatic registration configuration as this method is unaware of Braze-specific configuration.
+ *
+ * Any Game object method configured for ABKUnityMessageType.ABKPushTokenReceivedFromSystem will be notified.
+ *
+ * @param deviceToken the device token
+ */
+- (void)registerPushToken:(NSData *)deviceToken;
+
+/*!
+ * @discussion Passes the device token to Braze. The caller is responsible for respecting
+ * automatic integration and automatic registration configuration as this method is unaware of Braze-specific configuration.
+ *
+ * Any Game object method configured for ABKUnityMessageType.ABKPushTokenReceivedFromSystem will be notified.
+ *
+ * @param deviceToken the device token
+ */
+- (void)registerPushTokenBase64:(NSString *)deviceTokenBase64;
+
+/*!
+ * @discussion Requests authorization and registers the user for notifications. The caller is responsible for respecting
+ * automatic integration and automatic registration configuration as this method is unaware of Braze-specific configuration.
+ *
+ * When the user responds to the request authorization permission prompt, any Game object method configured for
+ * ABKUnityMessageType.ABKPushPermissionsPromptResponse will be notified.
+ * @param provisional If set to true, on iOS 12 and above, provisional authorization will be requested.
+ */
+- (void)registerForRemoteNotificationsWithProvisional:(BOOL)provisional;
+
+- (void)configureListenerFor:(NSInteger)messageType withGameObject:(NSString *)gameobject withMethod:(NSString *)method;
+- (void)setListenersFromPList;
+- (void)addInAppMessageListenerWithObjectNameAndSetDelegate:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
+- (void)addFeedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
+- (void)addContentCardsListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
+- (void)addPushReceivedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
+- (void)addPushOpenedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod;
+
+/*!
+ * @discussion Passes the push notification data to Braze. The caller is responsible for respecting
+ * automatic integration and automatic registration configuration as this method is unaware of Braze-specific configuration.
+ *
+ * Any Game object method configured for ABKUnityMessageType.ABKPushReceived or ABKUnityMessageType.ABKPushOpened
+ * will be notified as appropriate.
+ *
+ * @param deviceToken the device token
+ */
+- (void)registerApplication:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
+
+// Internal
+- (void)configureInternalListenerFor:(NSInteger)messageType;
+
@end
diff --git a/Assets/Plugins/iOS/AppboyUnityManager.mm b/Assets/Plugins/iOS/AppboyUnityManager.mm
index f94a24907..12d070d7e 100644
--- a/Assets/Plugins/iOS/AppboyUnityManager.mm
+++ b/Assets/Plugins/iOS/AppboyUnityManager.mm
@@ -4,12 +4,20 @@
#import
#import
+static NSString *const ABKInternalCallback = @"BrazeInternalCallback";
+static NSString *const ABKInternalPushPermissionsPromptResponse = @"onPushPromptResponseReceived";
+static NSString *const ABKInternalPushTokenReceivedFromSystem = @"onPushTokenReceivedFromSystem";
+
@interface ABKCard(proxy)
-- (NSMutableDictionary *) proxyForJson;
+- (NSMutableDictionary *)proxyForJson;
@end
@interface ABKInAppMessage(proxy)
-- (NSMutableDictionary *) proxyForJson;
+- (NSMutableDictionary *)proxyForJson;
+@end
+
+@interface AppboyUnityManager()
++ (NSString *)hexStringFromNSData:(NSData *)data;
@end
@implementation AppboyUnityManager
@@ -23,132 +31,21 @@ + (AppboyUnityManager*)sharedInstance {
return sharedInstance;
}
-- (void) logCustomEvent:(NSString *)eventName withProperties:(NSDictionary *)properties {
- [[Appboy sharedInstance] logCustomEvent:eventName withProperties:properties];
-}
-
-- (void) changeUser:(NSString *)userId {
- [[Appboy sharedInstance] changeUser:userId];
-}
-
-- (void) logPurchase:(NSString *)productId inCurrency:(NSString *)currencyCode
- atPrice:(NSString *)price withQuantity:(NSUInteger)quantity withProperties:(NSDictionary *)properties {
- [[Appboy sharedInstance] logPurchase:productId
- inCurrency:currencyCode
- atPrice:[NSDecimalNumber decimalNumberWithString:price]
- withQuantity:quantity
- andProperties:(NSDictionary *)properties];
-}
-
-- (void) setUserFirstName:(NSString *)firstName {
- [Appboy sharedInstance].user.firstName = firstName;
-}
-
-- (void) setUserLastName:(NSString *)lastName {
- [Appboy sharedInstance].user.lastName = lastName;
-}
-
-- (void) setUserPhoneNumber:(NSString *)number {
- [Appboy sharedInstance].user.phone = number;
-}
-
-- (void) setUserAvatarImageURL:(NSString *)imageURL {
- [Appboy sharedInstance].user.avatarImageURL = imageURL;
-}
-
-- (void) setUserEmail:(NSString *)email {
- [Appboy sharedInstance].user.email = email;
-}
-
-- (void) setUserGender:(NSInteger)gender {
- [[Appboy sharedInstance].user setGender:(ABKUserGenderType)gender];
-}
+# pragma mark - Config
-- (void) setUserDateOfBirthToYear:(NSInteger)year Month:(NSInteger)month andDay:(NSInteger)day {
- NSDateComponents *comps = [[NSDateComponents alloc] init];
- [comps setDay:day];
- [comps setMonth:month];
- [comps setYear:year];
- NSCalendar *gregorian = [[NSCalendar alloc]
- initWithCalendarIdentifier:NSGregorianCalendar];
- NSDate *date = [gregorian dateFromComponents:comps];
- [Appboy sharedInstance].user.dateOfBirth = date;
-}
-
-- (void) setUserCountry:(NSString *)country {
- [Appboy sharedInstance].user.country = country;
-}
-
-- (void) setUserHomeCity:(NSString *)city {
- [Appboy sharedInstance].user.homeCity = city;
-}
-
-- (void) setUserEmailNotificationSubscriptionType:(NSInteger)emailNotificationSubscriptionType {
- [[Appboy sharedInstance].user setEmailNotificationSubscriptionType:(ABKNotificationSubscriptionType)emailNotificationSubscriptionType];
-}
-
-- (void) setUserPushNotificationSubscriptionType:(NSInteger)pushNotificationSubscriptionType {
- [[Appboy sharedInstance].user setPushNotificationSubscriptionType:(ABKNotificationSubscriptionType)pushNotificationSubscriptionType];
-}
-
-- (void) setUserCustomAttributeWithKey:(NSString *)key andBOOLValue:(BOOL)value {
- [[Appboy sharedInstance].user setCustomAttributeWithKey:key andBOOLValue:value];
-}
-
-- (void) setUserCustomAttributeWithKey:(NSString *)key andIntegerValue:(NSInteger)value {
- [[Appboy sharedInstance].user setCustomAttributeWithKey:key andIntegerValue:value];
-}
-
-- (void) setUserCustomAttributeWithKey:(NSString *)key andDoubleValue:(double)value {
- [[Appboy sharedInstance].user setCustomAttributeWithKey:key andDoubleValue:value];
-}
-
-- (void) addAlias:(NSString *)alias withLabel:(NSString *)label {
- [[Appboy sharedInstance].user addAlias:alias withLabel:label];
-}
-
-- (void) setUserCustomAttributeWithKey:(NSString *)key andStringValue:(NSString *)value {
- [[Appboy sharedInstance].user setCustomAttributeWithKey:key andStringValue:value];
-}
-
-- (void) setUserCustomAttributeToNowWithKey:(NSString *)key {
- [[Appboy sharedInstance].user setCustomAttributeWithKey:key andDateValue:[NSDate date]];
-}
-
-- (void) setUserCustomAttributeWithKey:(NSString *)key toDateAsSecondsFromEpoch:(NSTimeInterval)seconds {
- [[Appboy sharedInstance].user setCustomAttributeWithKey:key andDateValue:[NSDate dateWithTimeIntervalSince1970:seconds]];
-}
-
-- (void) unsetUserCustomAttributeWithKey:(NSString *)key {
- [[Appboy sharedInstance].user unsetCustomAttributeWithKey:key];
-}
-
-- (void) incrementCustomUserAttributeWithKey:(NSString *)key by:(NSInteger)incrementValue {
- [[Appboy sharedInstance].user incrementCustomUserAttribute:key by:incrementValue];
-}
-
-- (void) setCustomAttributeArrayWithKey:(NSString *)key array:(NSArray *)valueArray {
- [[Appboy sharedInstance].user setCustomAttributeArrayWithKey:key array:valueArray];
-}
-
-- (void) addToCustomAttributeArrayWithKey:(NSString *)key value:(NSString *)value {
- [[Appboy sharedInstance].user addToCustomAttributeArrayWithKey:key value:value];
+- (NSString *)getApiKeyFromUnity {
+ return self.appboyUnityPlist[ABKUnityApiKey];
}
-- (void) removeFromCustomAttributeArrayWithKey:(NSString *)key value:(NSString *)value {
- [[Appboy sharedInstance].user removeFromCustomAttributeArrayWithKey:key value:value];
+- (NSDictionary *)parsePlist {
+ NSDictionary* appboyUnityPlist = [[NSBundle mainBundle] infoDictionary][@"Appboy"][@"Unity"];
+ self.appboyUnityPlist = appboyUnityPlist;
+ return appboyUnityPlist;
}
-- (void) setAttributionData:(NSString *)network campaign:(NSString *)campaign adgroup:(NSString *)adgroup creative:(NSString *)creative {
- ABKAttributionData *attributionData = [[ABKAttributionData alloc]
- initWithNetwork:network
- campaign:campaign
- adGroup:adgroup
- creative:creative];
- [[Appboy sharedInstance].user setAttributionData:attributionData];
-}
+# pragma mark - Social Media
-- (void) setUserFacebookData:(NSString *)facebookId firstName:(NSString *)firstName lastName:(NSString *)lastName email:(NSString *)email bio:(NSString *)bio cityName:(NSString *)cityName gender:(NSInteger)gender numberOfFriends:(NSInteger)numberOfFriends birthday:(NSString *)birthday {
+- (void)setUserFacebookData:(NSString *)facebookId firstName:(NSString *)firstName lastName:(NSString *)lastName email:(NSString *)email bio:(NSString *)bio cityName:(NSString *)cityName gender:(NSInteger)gender numberOfFriends:(NSInteger)numberOfFriends birthday:(NSString *)birthday {
NSMutableDictionary *facebookData = [NSMutableDictionary dictionary];
facebookData[@"id"] = facebookId;
facebookData[@"first_name"] = firstName;
@@ -172,7 +69,7 @@ - (void) setUserFacebookData:(NSString *)facebookId firstName:(NSString *)firstN
[Appboy sharedInstance].user.facebookUser = facebookUser;
}
-- (void) setUserTwitterData:(NSInteger)twitterUserId twitterHandle:(NSString *)twitterHandle name:(NSString *)name description:(NSString *)description followerCount:(NSInteger)followerCount followingCount:(NSInteger)followingCount tweetCount:(NSInteger)tweetCount profileImageUrl:(NSString *)profileImageUrl {
+- (void)setUserTwitterData:(NSInteger)twitterUserId twitterHandle:(NSString *)twitterHandle name:(NSString *)name description:(NSString *)description followerCount:(NSInteger)followerCount followingCount:(NSInteger)followingCount tweetCount:(NSInteger)tweetCount profileImageUrl:(NSString *)profileImageUrl {
ABKTwitterUser *twitterUser = [[ABKTwitterUser alloc] init];
twitterUser.userDescription = description;
if (twitterUserId > 0) {
@@ -193,173 +90,46 @@ - (void) setUserTwitterData:(NSInteger)twitterUserId twitterHandle:(NSString *)t
[Appboy sharedInstance].user.twitterUser = twitterUser;
}
-// ABKInAppMessageDelegate methods
-- (ABKInAppMessageDisplayChoice)beforeInAppMessageDisplayed:(ABKInAppMessage *)inAppMessage {
- if (self.unityInAppMessageGameObjectName == nil) {
- NSLog(@"Not sending a Unity message in response to an in-app message being received because "
- "no message receiver was defined. To implement custom behavior in response to a in-app"
- "message being received, you must register a GameObject and method name with Appboy "
- "by calling [[AppboyUnityManager sharedInstance] addInAppMessageListenerWithObjectName: callbackMethodName:].");
- return ABKDisplayInAppMessageNow;
- }
- if (self.unityInAppMessageCallbackFunctionName == nil) {
- NSLog(@"Not sending a Unity message in response to a in-app message being received because "
- "no method name was defined for the %@. To implement custom behavior in response to a in-app "
- "message being received, you must register a GameObject and method name with Appboy "
- "[[AppboyUnityManager sharedInstance] addInAppMessageListenerWithObjectName: callbackMethodName:].",
- self.unityInAppMessageGameObjectName);
- return ABKDisplayInAppMessageNow;
- }
- NSLog(@"Sending an in-app message to %@:%@.", self.unityInAppMessageGameObjectName, self.unityInAppMessageCallbackFunctionName);
-
- NSData *inAppMessageData = [inAppMessage serializeToData];
- NSString *dataString = [[NSString alloc] initWithData:inAppMessageData encoding:NSUTF8StringEncoding];
- NSLog(@"dataString is %@.", dataString);
- UnitySendMessage([self.unityInAppMessageGameObjectName cStringUsingEncoding:NSUTF8StringEncoding],
- [self.unityInAppMessageCallbackFunctionName cStringUsingEncoding:NSUTF8StringEncoding],
- [dataString cStringUsingEncoding:NSUTF8StringEncoding]);
- if ([self.appboyUnityPlist[ABKUnityHandleInAppMessageDisplayKey] boolValue]) {
- return ABKDisplayInAppMessageNow;
- }
- return ABKDiscardInAppMessage;
-}
-
-// Internal methods for communications between Appboy and Unity
-- (void) parsePlist {
- self.appboyUnityPlist = [[NSBundle mainBundle] infoDictionary][@"Appboy"][@"Unity"];
-}
-
-- (void) setListeners {
- [self addPushReceivedListenerWithObjectName:self.appboyUnityPlist[ABKUnityPushReceivedGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityPushReceivedCallbackKey]];
- [self addPushOpenedListenerWithObjectName:self.appboyUnityPlist[ABKUnityPushOpenedGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityPushOpenedCallbackKey]];
- [self addInAppMessageListenerWithObjectName:self.appboyUnityPlist[ABKUnityInAppMessageGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityInAppMessageCallbackKey]];
- [self addContentCardsListenerWithObjectName:self.appboyUnityPlist[ABKUnityContentCardsGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityContentCardsCallbackKey]];
- [self addFeedListenerWithObjectName:self.appboyUnityPlist[ABKUnityFeedGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityFeedCallbackKey]];
-}
-
-- (NSString *) getApiKeyFromUnity {
- return self.appboyUnityPlist[ABKUnityApiKey];
-}
+# pragma mark - In-app message analytics
-- (void) addInAppMessageListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
- if (gameObject != nil && callbackMethod != nil) {
- [Appboy sharedInstance].inAppMessageController.delegate = [AppboyUnityManager sharedInstance];
- self.unityInAppMessageGameObjectName = gameObject;
- self.unityInAppMessageCallbackFunctionName = callbackMethod;
- }
-}
-
-- (void) addFeedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
- if (gameObject != nil && callbackMethod != nil) {
- self.unityFeedGameObjectName = gameObject;
- self.unityFeedCallbackFunctionName = callbackMethod;
- }
-}
-
-- (void) addContentCardsListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
- if (gameObject != nil && callbackMethod != nil) {
- self.unityContentCardsGameObjectName = gameObject;
- self.unityContentCardsCallbackFunctionName = callbackMethod;
- }
-}
-
-- (void) addPushReceivedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
- if (gameObject != nil && callbackMethod != nil) {
- self.unityPushReceivedGameObjectName = gameObject;
- self.unityPushReceivedCallbackFunctionName = callbackMethod;
- }
-}
-
-- (void) addPushOpenedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
- if (gameObject != nil && callbackMethod != nil) {
- self.unityPushOpenedGameObjectName = gameObject;
- self.unityPushOpenedCallbackFunctionName = callbackMethod;
- }
-}
-
-// Push related methods
-- (void) registerForRemoteNotifications {
- if ([self.appboyUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue] && ![self.appboyUnityPlist[ABKUnityDisableAutomaticPushRegistrationKey] boolValue]) {
- UIUserNotificationType notificationSettingTypes = (UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound);
- if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
- UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
- center.delegate = self;
- UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
- if (@available(iOS 12.0, *)) {
- options = options | UNAuthorizationOptionProvisional;
- }
- [center requestAuthorizationWithOptions:options
- completionHandler:^(BOOL granted, NSError *_Nullable error) {
- [[Appboy sharedInstance] pushAuthorizationFromUserNotificationCenter:granted];
- }];
- [[UIApplication sharedApplication] registerForRemoteNotifications];
- } else {
- UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationSettingTypes categories:nil];
- [[UIApplication sharedApplication] registerForRemoteNotifications];
- [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
- }
- }
-}
-
-- (void) registerPushToken:(NSData *)deviceToken {
- if ([self.appboyUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue]) {
- [[Appboy sharedInstance] registerDeviceToken:deviceToken];
- }
-}
-
-- (void) registerPushTokenBase64:(NSString *)deviceTokenBase64 {
- NSData *data = [[NSData alloc] initWithBase64EncodedString:deviceTokenBase64 options:0];
- [[Appboy sharedInstance] registerDeviceToken:data];
-}
-
-- (void) registerApplication:(UIApplication *)application
- didReceiveRemoteNotification:(NSDictionary *)notification
- fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
- if (self.appboyUnityPlist == nil || [self.appboyUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue]) {
- [[Appboy sharedInstance] registerApplication:application didReceiveRemoteNotification:notification fetchCompletionHandler:completionHandler];
- [self forwardNotification:notification];
- }
-}
-
-- (void) userNotificationCenter:(UNUserNotificationCenter *)center
- didReceiveNotificationResponse:(UNNotificationResponse *)response
- withCompletionHandler:(void (^)(void))completionHandler {
- if (completionHandler) {
- completionHandler();
- }
-
- if (self.appboyUnityPlist == nil || [self.appboyUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue]) {
- [[Appboy sharedInstance] userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
- [self forwardNotification:response.notification.request.content.userInfo];
- }
+- (void)logInAppMessageImpression:(NSString *)inAppMessageJSONString {
+ ABKInAppMessage *inAppMessage = [[ABKInAppMessage alloc] init];
+ [self getInAppMessageFromString:inAppMessageJSONString withInAppMessage:inAppMessage];
+ [inAppMessage logInAppMessageImpression];
}
-- (void) logInAppMessageClicked:(NSString *)inAppMessageJSONString {
+- (void)logInAppMessageClicked:(NSString *)inAppMessageJSONString {
ABKInAppMessage *inAppMessage = [[ABKInAppMessage alloc] init];
[self getInAppMessageFromString:inAppMessageJSONString withInAppMessage:inAppMessage];
[inAppMessage logInAppMessageClicked];
}
-- (void) logInAppMessageButtonClicked:(NSString *)inAppMessageJSONString withButtonID:(NSInteger)buttonID {
+- (void)logInAppMessageButtonClicked:(NSString *)inAppMessageJSONString withButtonID:(NSInteger)buttonID {
ABKInAppMessageImmersive *inAppMessageImmersive = [[ABKInAppMessageImmersive alloc] init];
[self getInAppMessageFromString:inAppMessageJSONString withInAppMessage:inAppMessageImmersive];
[inAppMessageImmersive logInAppMessageClickedWithButtonID:buttonID];
}
-- (void) logInAppMessageImpression:(NSString *)inAppMessageJSONString {
- ABKInAppMessage *inAppMessage = [[ABKInAppMessage alloc] init];
- [self getInAppMessageFromString:inAppMessageJSONString withInAppMessage:inAppMessage];
- [inAppMessage logInAppMessageImpression];
-}
-
-- (void) getInAppMessageFromString:(NSString *)inAppMessageJSONString withInAppMessage:(ABKInAppMessage *)inAppMessage {
+- (void)getInAppMessageFromString:(NSString *)inAppMessageJSONString withInAppMessage:(ABKInAppMessage *)inAppMessage {
NSData *inAppMessageData = [inAppMessageJSONString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e = nil;
id deserializedInAppMessageDict = [NSJSONSerialization JSONObjectWithData:inAppMessageData options:NSJSONReadingMutableContainers error:&e];
[inAppMessage setValuesForKeysWithDictionary:deserializedInAppMessageDict];
}
-- (void) logCardImpression:(NSString *)cardJSONString {
+# pragma mark - In-app message display
+
+- (void)displayNextInAppMessageWithDelegate:(BOOL)withDelegate {
+ ABKInAppMessageController *delegate = nil;
+ if (withDelegate) {
+ delegate = [Appboy sharedInstance].inAppMessageController.delegate;
+ }
+ [[Appboy sharedInstance].inAppMessageController displayNextInAppMessageWithDelegate:delegate];
+}
+
+# pragma mark - News Feed analytics
+
+- (void)logCardImpression:(NSString *)cardJSONString {
NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e = nil;
id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
@@ -367,7 +137,7 @@ - (void) logCardImpression:(NSString *)cardJSONString {
[card logCardImpression];
}
-- (void) logCardClicked:(NSString *)cardJSONString {
+- (void)logCardClicked:(NSString *)cardJSONString {
NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e = nil;
id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
@@ -375,7 +145,9 @@ - (void) logCardClicked:(NSString *)cardJSONString {
[card logCardClicked];
}
-- (void) requestFeedRefresh {
+# pragma mark - News Feed refresh
+
+- (void)requestFeedRefresh {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(requestFeedFromCache:)
name:ABKFeedUpdatedNotification
@@ -383,30 +155,16 @@ - (void) requestFeedRefresh {
[[Appboy sharedInstance] requestFeedRefresh];
}
-- (void) logFeedDisplayed {
- [[Appboy sharedInstance] logFeedDisplayed];
-}
-
-- (void) requestFeedFromCache:(NSNotification *)notification {
+- (void)requestFeedFromCache:(NSNotification *)notification {
BOOL fromOfflineStorage = YES;
if (notification != nil) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:ABKFeedUpdatedNotification object:nil];
fromOfflineStorage = NO;
}
- if (self.unityFeedGameObjectName == nil) {
- NSLog(@"Not sending a Unity message in response to a feed cards request because "
- "no message receiver was defined. To implement custom behavior in response to a feed"
- "being received, you must register a GameObject and method name with Appboy "
- "by calling [[AppboyUnityManager sharedInstance] addFeedListenerWithObjectName: callbackMethodName:].");
- }
- if (self.unityFeedCallbackFunctionName == nil) {
- NSLog(@"Not sending a Unity message in response to a feed cards request because "
- "no method name was defined for the %@. To implement custom behavior in response to a feed "
- "being received, you must register a GameObject and method name with Appboy "
- "[[AppboyUnityManager sharedInstance] addFeedListenerWithObjectName: callbackMethodName:].",
- self.unityFeedGameObjectName);
+ if (self.unityFeedCallbackFunctionName == nil || self.unityFeedGameObjectName == nil) {
+ NSLog(@"No properly configured game object. Not forwarding News Feed message.");
+ return;
}
- NSLog(@"Sending cards to %@:%@.", self.unityFeedGameObjectName, self.unityFeedCallbackFunctionName);
NSMutableArray *cardsDictionaryArray = [NSMutableArray arrayWithCapacity:1];
NSArray *cards = [[Appboy sharedInstance].feedController getCardsInCategories:ABKCardCategoryAll];
@@ -420,43 +178,67 @@ - (void) requestFeedFromCache:(NSNotification *)notification {
@"mTimestamp" : [NSNumber numberWithDouble:timestamp],
@"mFromOfflineStorage" : [NSNumber numberWithBool:fromOfflineStorage]};
NSError *error;
- NSString *feedString;
NSData *feedData = [NSJSONSerialization dataWithJSONObject:feedDictionary
options:0
error:&error];
if (!feedData) {
- NSLog(@"Got an error %@ when parsing Appboy feed to json data.", error);
- } else {
- feedString = [[NSString alloc] initWithData:feedData encoding:NSUTF8StringEncoding];
+ NSLog(@"Error parsing News Feed to json: %@", error);
+ return;
}
- if (feedString != nil) {
- NSLog(@"the message that's going to pass to Unity is: \n %@", feedString);
- UnitySendMessage([self.unityFeedGameObjectName cStringUsingEncoding:NSUTF8StringEncoding],
- [self.unityFeedCallbackFunctionName cStringUsingEncoding:NSUTF8StringEncoding],
- [feedString cStringUsingEncoding:NSUTF8StringEncoding]);
+ NSString *feedString = [[NSString alloc] initWithData:feedData encoding:NSUTF8StringEncoding];
+ if (feedString == nil) {
+ NSLog(@"Error parsing News Feed json to string");
+ return;
}
+ [self unitySendMessageTo:self.unityFeedGameObjectName withMethod:self.unityFeedCallbackFunctionName withMessage:feedString];
+}
+
+# pragma mark - Content Card analytics
+
+- (void)logContentCardImpression:(NSString *)cardJSONString {
+ NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
+ NSError *e = nil;
+ id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
+ ABKContentCard *card = [ABKContentCard deserializeCardFromDictionary:deserializedCardDict];
+ [card logContentCardImpression];
+}
+
+- (void)logContentCardClicked:(NSString *)cardJSONString {
+ NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
+ NSError *e = nil;
+ id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
+ ABKContentCard *card = [ABKContentCard deserializeCardFromDictionary:deserializedCardDict];
+ [card logContentCardClicked];
}
-- (void) requestContentCardsFromCache:(NSNotification *)notification {
+- (void)logContentCardDismissed:(NSString *)cardJSONString {
+ NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
+ NSError *e = nil;
+ id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
+ ABKContentCard *card = [ABKContentCard deserializeCardFromDictionary:deserializedCardDict];
+ [card logContentCardDismissed];
+}
+
+# pragma mark - Content Card refresh
+
+- (void)requestContentCardsRefresh {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(requestContentCardsFromCache:)
+ name:ABKContentCardsProcessedNotification
+ object:nil];
+ [[Appboy sharedInstance] requestContentCardsRefresh];
+}
+
+- (void)requestContentCardsFromCache:(NSNotification *)notification {
BOOL fromOfflineStorage = YES;
if (notification != nil) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:ABKContentCardsProcessedNotification object:nil];
fromOfflineStorage = NO;
}
- if (self.unityContentCardsGameObjectName == nil) {
- NSLog(@"Not sending a Unity message in response to a content cards request because "
- "no message receiver was defined. To implement custom behavior in response to a cards"
- "being received, you must register a GameObject and method name with Appboy "
- "by calling [[AppboyUnityManager sharedInstance] addContentCardsListenerWithObjectName: callbackMethodName:].");
+ if (self.unityContentCardsCallbackFunctionName == nil || self.unityContentCardsGameObjectName == nil) {
+ NSLog(@"No properly configured game object. Not forwarding Content Cards message.");
+ return;
}
- if (self.unityContentCardsCallbackFunctionName == nil) {
- NSLog(@"Not sending a Unity message in response to a content cards request because "
- "no method name was defined for the %@. To implement custom behavior in response to cards "
- "being received, you must register a GameObject and method name with Appboy "
- "[[AppboyUnityManager sharedInstance] addContentCardsListenerWithObjectName: callbackMethodName:].",
- self.unityContentCardsGameObjectName);
- }
- NSLog(@"Sending cards to %@:%@.", self.unityContentCardsGameObjectName, self.unityContentCardsCallbackFunctionName);
NSMutableArray *cardsDictionaryArray = [NSMutableArray arrayWithCapacity:1];
NSArray *cards = [[Appboy sharedInstance].contentCardsController getContentCards];
@@ -470,80 +252,83 @@ - (void) requestContentCardsFromCache:(NSNotification *)notification {
@"mTimestamp" : [NSNumber numberWithDouble:timestamp],
@"mFromOfflineStorage" : [NSNumber numberWithBool:fromOfflineStorage]};
NSError *error;
- NSString *contentCardsString;
NSData *contentCardsData = [NSJSONSerialization dataWithJSONObject:contentCardsDictionary
options:0
error:&error];
if (!contentCardsData) {
- NSLog(@"Got an error %@ when parsing Appboy feed to json data.", error);
- } else {
- contentCardsString = [[NSString alloc] initWithData:contentCardsData encoding:NSUTF8StringEncoding];
+ NSLog(@"Error parsing Content Cards to json: %@", error);
+ return;
}
- if (contentCardsString != nil) {
- NSLog(@"the message that's going to pass to Unity is: \n %@", contentCardsString);
- UnitySendMessage([self.unityContentCardsGameObjectName cStringUsingEncoding:NSUTF8StringEncoding],
- [self.unityContentCardsCallbackFunctionName cStringUsingEncoding:NSUTF8StringEncoding],
- [contentCardsString cStringUsingEncoding:NSUTF8StringEncoding]);
+ NSString *contentCardsString = [[NSString alloc] initWithData:contentCardsData encoding:NSUTF8StringEncoding];
+ if (contentCardsString == nil) {
+ NSLog(@"Error parsing Content Cards json to string");
+ return;
}
+ [self unitySendMessageTo:self.unityContentCardsGameObjectName withMethod:self.unityContentCardsCallbackFunctionName withMessage:contentCardsString];
}
-- (void) logContentCardsDisplayed {
- [[Appboy sharedInstance] logContentCardsDisplayed];
-}
+# pragma mark - Push
-- (void) requestContentCardsRefresh {
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(requestContentCardsFromCache:)
- name:ABKContentCardsProcessedNotification
- object:nil];
- [[Appboy sharedInstance] requestContentCardsRefresh];
-}
-
-- (void) logContentCardImpression:(NSString *)cardJSONString {
- NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
- NSError *e = nil;
- id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
- ABKContentCard *card = [ABKContentCard deserializeCardFromDictionary:deserializedCardDict];
- [card logContentCardImpression];
-}
-
-- (void) logContentCardClicked:(NSString *)cardJSONString {
- NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
- NSError *e = nil;
- id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
- ABKContentCard *card = [ABKContentCard deserializeCardFromDictionary:deserializedCardDict];
- [card logContentCardClicked];
+- (void)registerPushToken:(NSData *)data {
+ [[Appboy sharedInstance] registerDeviceToken:data];
+ NSString *token = [AppboyUnityManager hexStringFromNSData:data];
+ if (self.unityPushTokenReceivedFromSystemGameObjectName != nil && self.unityPushTokenReceivedFromSystemFunctionName != nil) {
+ [self unitySendMessageTo:self.unityPushTokenReceivedFromSystemGameObjectName withMethod:self.unityPushTokenReceivedFromSystemFunctionName withMessage:token];
+ }
+ if (self.sendPushTokenReceivedFromSystem) {
+ [self unitySendMessageTo:ABKInternalCallback withMethod:ABKInternalPushTokenReceivedFromSystem withMessage:token];
+ }
}
-- (void) logContentCardDismissed:(NSString *)cardJSONString {
- NSData *cardData = [cardJSONString dataUsingEncoding:NSUTF8StringEncoding];
- NSError *e = nil;
- id deserializedCardDict = [NSJSONSerialization JSONObjectWithData:cardData options:NSJSONReadingMutableContainers error:&e];
- ABKContentCard *card = [ABKContentCard deserializeCardFromDictionary:deserializedCardDict];
- [card logContentCardDismissed];
+- (void)registerPushTokenBase64:(NSString *)deviceTokenBase64 {
+ NSData *data = [[NSData alloc] initWithBase64EncodedString:deviceTokenBase64 options:0];
+ [self registerPushToken:data];
}
-- (void) displayNextInAppMessageWithDelegate:(BOOL)withDelegate {
- ABKInAppMessageController *delegate = nil;
- if (withDelegate) {
- delegate = [Appboy sharedInstance].inAppMessageController.delegate;
++ (NSString *)hexStringFromNSData:(NSData *)data {
+ NSUInteger dataLength = data.length;
+ if (dataLength == 0) {
+ return nil;
}
- [[Appboy sharedInstance].inAppMessageController displayNextInAppMessageWithDelegate:delegate];
-}
-
-+ (void) wipeDataAndDisableForAppRun {
- [Appboy wipeDataAndDisableForAppRun];
-}
-+ (void) disableSDK {
- [Appboy disableSDK];
+ const unsigned char *dataBuffer = (const unsigned char *)data.bytes;
+ NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
+ for (int i = 0; i < dataLength; ++i) {
+ [hexString appendFormat:@"%02.2hhx", dataBuffer[i]];
+ }
+ return [hexString copy];
}
-+ (void) requestEnableSDKOnNextAppRun {
- [Appboy requestEnableSDKOnNextAppRun];
+- (void)registerForRemoteNotificationsWithProvisional:(BOOL)provisional {
+ UIUserNotificationType notificationSettingTypes = (UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound);
+ if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
+ center.delegate = self;
+ UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
+ if (@available(iOS 12.0, *)) {
+ if (provisional) {
+ options = options | UNAuthorizationOptionProvisional;
+ }
+ }
+ [center requestAuthorizationWithOptions:options
+ completionHandler:^(BOOL granted, NSError *_Nullable error) {
+ [[Appboy sharedInstance] pushAuthorizationFromUserNotificationCenter:granted];
+ if (self.unityPushPermissionsPromptResponseGameObjectName != nil && self.unityPushPermissionsPromptResponseFunctionName != nil) {
+ [self unitySendMessageTo:self.unityPushPermissionsPromptResponseGameObjectName withMethod:self.unityPushPermissionsPromptResponseFunctionName withMessage:(granted ? @"true" : @"false")];
+ }
+ if (self.sendInternalPushPermissionsPromptResponse) {
+ [self unitySendMessageTo:ABKInternalCallback withMethod:ABKInternalPushPermissionsPromptResponse withMessage:(granted ? @"true" : @"false")];
+ }
+ }];
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
+ } else {
+ UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationSettingTypes categories:nil];
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
+ [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
+ }
}
-- (void) forwardNotification:(NSDictionary *)notification {
+- (void)forwardNotification:(NSDictionary *)notification {
// generate a new dictionary that rearrange the notification elements
NSMutableDictionary *aps = [NSMutableDictionary dictionaryWithDictionary:[notification objectForKey:@"aps"]];
@@ -561,58 +346,190 @@ - (void) forwardNotification:(NSDictionary *)notification {
[aps setObject:extraDictionary forKey:@"extra"];
}
- if ([NSJSONSerialization isValidJSONObject:aps]) {
- NSError *pushParsingError = nil;
- NSData *data = [NSJSONSerialization dataWithJSONObject:aps options:0 error:&pushParsingError];
-
- if (pushParsingError == nil) {
- NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-
- UIApplication *application = [UIApplication sharedApplication];
- if (application.applicationState == UIApplicationStateActive) {
- if (self.unityPushReceivedGameObjectName == nil) {
- NSLog(@"Not sending a Unity message in response to a push notification being received because "
- "no message receiver was defined. To implement custom behavior in response to a push "
- "notification being received, you must register a GameObject and method name with Appboy "
- "by calling [AppboyUnityManager sharedInstance] addPushReceivedListenerWithObjectName: callbackMethodName].");
- return;
- }
- if (self.unityPushReceivedCallbackFunctionName == nil) {
- NSLog(@"Not sending a Unity message in response to a push notification being received because "
- "no method name was defined for the %@. To implement custom behavior in response to a push "
- "notification being received, you must register a GameObject and method name with Appboy "
- "by calling [AppboyUnityManager sharedInstance] addPushReceivedListenerWithObjectName: callbackMethodName].",
- self.unityPushReceivedGameObjectName);
- return;
- }
- NSLog(@"Sending a notification received message to %@:%@.", self.unityPushReceivedGameObjectName, self.unityPushReceivedCallbackFunctionName);
-
- UnitySendMessage([self.unityPushReceivedGameObjectName cStringUsingEncoding:NSUTF8StringEncoding],
- [self.unityPushReceivedCallbackFunctionName cStringUsingEncoding:NSUTF8StringEncoding],
- [dataString cStringUsingEncoding:NSUTF8StringEncoding]);
- } else {
- if (self.unityPushOpenedGameObjectName == nil) {
- NSLog(@"Not sending a Unity message in response to a push notification being opened because "
- "no message receiver was defined. To implement custom behavior in response to a push "
- "notification being opened, you must register a GameObject and method name with Appboy "
- "by calling [AppboyUnityManager sharedInstance] addPushOpenedListenerWithObjectName: callbackMethodName].");
- return;
- }
- if (self.unityPushOpenedCallbackFunctionName == nil) {
- NSLog(@"Not sending a Unity message in response to a push notification being opened because "
- "no method name was defined for the %@. To implement custom behavior in response to a push "
- "notification being opened, you must register a GameObject and method name with Appboy "
- "[AppboyUnityManager sharedInstance] addPushOpenedListenerWithObjectName: callbackMethodName].",
- self.unityPushOpenedGameObjectName);
- return;
- }
- NSLog(@"Sending a notification opened message to %@:%@.", self.unityPushOpenedGameObjectName, self.unityPushOpenedCallbackFunctionName);
-
- UnitySendMessage([self.unityPushOpenedGameObjectName cStringUsingEncoding:NSUTF8StringEncoding],
- [self.unityPushOpenedCallbackFunctionName cStringUsingEncoding:NSUTF8StringEncoding],
- [dataString cStringUsingEncoding:NSUTF8StringEncoding]);
- }
+ if (![NSJSONSerialization isValidJSONObject:aps]) {
+ NSLog(@"Invalid json received. Not forwarding push message.");
+ return;
+ }
+
+ NSError *error = nil;
+ NSData *data = [NSJSONSerialization dataWithJSONObject:aps options:0 error:&error];
+ if (error != nil) {
+ NSLog(@"Error serializing json. Not forwarding push message: %@", [error localizedDescription]);
+ }
+
+ NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+
+ UIApplication *application = [UIApplication sharedApplication];
+ if (application.applicationState == UIApplicationStateActive) {
+ if (self.unityPushReceivedGameObjectName == nil || self.unityPushReceivedCallbackFunctionName == nil) {
+ NSLog(@"No properly configured game object. Not forwarding push received message.");
+ return;
+ }
+ [self unitySendMessageTo:self.unityPushReceivedGameObjectName withMethod:self.unityPushReceivedCallbackFunctionName withMessage:dataString];
+ } else {
+ if (self.unityPushOpenedGameObjectName == nil || self.unityPushOpenedCallbackFunctionName == nil) {
+ NSLog(@"No properly configured game object. Not forwarding push opened message.");
+ return;
}
+ [self unitySendMessageTo:self.unityPushOpenedGameObjectName withMethod:self.unityPushOpenedCallbackFunctionName withMessage:dataString];
+ }
+}
+
+# pragma mark - Gameobject callbacks
+
+- (void)configureListenerFor:(NSInteger)messageType withGameObject:(NSString *)gameobject withMethod:(NSString *)method {
+ switch ((ABKUnityMessageType)messageType) {
+ case ABKPushPermissionsPromptResponse:
+ NSLog(@"Setting push permissions prompt response listener to object %@, method %@", gameobject, method);
+ self.unityPushPermissionsPromptResponseGameObjectName = gameobject;
+ self.unityPushPermissionsPromptResponseFunctionName = method;
+ break;
+ case ABKPushTokenReceivedFromSystem:
+ NSLog(@"Setting push token received from system listener to object %@, method %@", gameobject, method);
+ self.unityPushTokenReceivedFromSystemGameObjectName = gameobject;
+ self.unityPushTokenReceivedFromSystemFunctionName = method;
+ break;
+ case ABKPushReceived:
+ NSLog(@"Setting push received listener to object %@, method %@", gameobject, method);
+ [self addPushReceivedListenerWithObjectName:gameobject callbackMethodName:method];
+ break;
+ case ABKPushOpened:
+ NSLog(@"Setting push opened listener to object %@, method %@", gameobject, method);
+ [self addPushOpenedListenerWithObjectName:gameobject callbackMethodName:method];
+ break;
+ case ABKPushDeleted:
+ NSLog(@"Push opened not supported.");
+ break;
+ case ABKInAppMessageReceived:
+ NSLog(@"Setting in-app message received listener to object %@, method %@", gameobject, method);
+ [self addInAppMessageListenerWithObjectNameAndSetDelegate:gameobject callbackMethodName:method];
+ break;
+ case ABKNewsFeedUpdated:
+ NSLog(@"Setting News Feed updated listener to object %@, method %@", gameobject, method);
+ [self addFeedListenerWithObjectName:gameobject callbackMethodName:method];
+ break;
+ case ABKContentCardsUpdated:
+ NSLog(@"Setting Content Cards updated listener to object %@, method %@", gameobject, method);
+ [self addContentCardsListenerWithObjectName:gameobject callbackMethodName:method];
+ break;
+ default:
+ NSLog(@"Unknown message type received.");
+ return;
+ }
+}
+
+- (void)setListenersFromPList {
+ [self addPushReceivedListenerWithObjectName:self.appboyUnityPlist[ABKUnityPushReceivedGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityPushReceivedCallbackKey]];
+ [self addPushOpenedListenerWithObjectName:self.appboyUnityPlist[ABKUnityPushOpenedGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityPushOpenedCallbackKey]];
+ [self addInAppMessageListenerWithObjectNameAndSetDelegate:self.appboyUnityPlist[ABKUnityInAppMessageGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityInAppMessageCallbackKey]];
+ [self addContentCardsListenerWithObjectName:self.appboyUnityPlist[ABKUnityContentCardsGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityContentCardsCallbackKey]];
+ [self addFeedListenerWithObjectName:self.appboyUnityPlist[ABKUnityFeedGameObjectKey] callbackMethodName:self.appboyUnityPlist[ABKUnityFeedCallbackKey]];
+}
+
+- (void)addInAppMessageListenerWithObjectNameAndSetDelegate:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
+ if (gameObject != nil && callbackMethod != nil) {
+ [Appboy sharedInstance].inAppMessageController.delegate = [AppboyUnityManager sharedInstance];
+ self.unityInAppMessageGameObjectName = gameObject;
+ self.unityInAppMessageCallbackFunctionName = callbackMethod;
+ }
+}
+
+- (void)addFeedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
+ if (gameObject != nil && callbackMethod != nil) {
+ self.unityFeedGameObjectName = gameObject;
+ self.unityFeedCallbackFunctionName = callbackMethod;
+ }
+}
+
+- (void)addContentCardsListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
+ if (gameObject != nil && callbackMethod != nil) {
+ self.unityContentCardsGameObjectName = gameObject;
+ self.unityContentCardsCallbackFunctionName = callbackMethod;
+ }
+}
+
+- (void)addPushReceivedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
+ if (gameObject != nil && callbackMethod != nil) {
+ self.unityPushReceivedGameObjectName = gameObject;
+ self.unityPushReceivedCallbackFunctionName = callbackMethod;
+ }
+}
+
+- (void)addPushOpenedListenerWithObjectName:(NSString *)gameObject callbackMethodName:(NSString *)callbackMethod {
+ if (gameObject != nil && callbackMethod != nil) {
+ self.unityPushOpenedGameObjectName = gameObject;
+ self.unityPushOpenedCallbackFunctionName = callbackMethod;
+ }
+}
+
+# pragma mark - UIApplicationDelegate
+
+- (void)registerApplication:(UIApplication *)application
+ didReceiveRemoteNotification:(NSDictionary *)notification
+ fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
+ [[Appboy sharedInstance] registerApplication:application didReceiveRemoteNotification:notification fetchCompletionHandler:completionHandler];
+ [self forwardNotification:notification];
+}
+
+# pragma mark - UNUserNotificationCenterDelegate
+
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+ didReceiveNotificationResponse:(UNNotificationResponse *)response
+ withCompletionHandler:(void (^)(void))completionHandler {
+ if (completionHandler) {
+ completionHandler();
+ }
+
+ if ([self.appboyUnityPlist[ABKUnityAutomaticPushIntegrationKey] boolValue]) {
+ [[Appboy sharedInstance] userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
+ [self forwardNotification:response.notification.request.content.userInfo];
+ }
+}
+
+# pragma mark - ABKInAppMessageControllerDelegate
+
+/**
+ * @discussion Set on the shared Appboy instance when a game object is configured to receive in-app messages.
+ */
+- (ABKInAppMessageDisplayChoice)beforeInAppMessageDisplayed:(ABKInAppMessage *)inAppMessage {
+ if (self.unityInAppMessageCallbackFunctionName == nil || self.unityInAppMessageGameObjectName == nil) {
+ NSLog(@"No properly configured game object for in-app messages. Returning ABKDisplayInAppMessageNow.",
+ self.unityInAppMessageGameObjectName);
+ return ABKDisplayInAppMessageNow;
+ }
+
+ NSData *inAppMessageData = [inAppMessage serializeToData];
+ NSString *dataString = [[NSString alloc] initWithData:inAppMessageData encoding:NSUTF8StringEncoding];
+ [self unitySendMessageTo:self.unityInAppMessageGameObjectName withMethod:self.unityInAppMessageCallbackFunctionName withMessage:dataString];
+ if ([self.appboyUnityPlist[ABKUnityHandleInAppMessageDisplayKey] boolValue]) {
+ NSLog(@"Braze configured to display in-app messages despite presence of game object listener. Returning ABKDisplayInAppMessageNow.");
+ return ABKDisplayInAppMessageNow;
+ }
+ return ABKDiscardInAppMessage;
+}
+
+# pragma mark - Internal Communication
+
+- (void)unitySendMessageTo:(NSString *)gameObjectName withMethod:(NSString *)methodName withMessage:(NSString *)message {
+ NSLog(@"Sending message to %@:%@.", gameObjectName, methodName);
+ UnitySendMessage([gameObjectName UTF8String],
+ [methodName UTF8String],
+ [message UTF8String]);
+}
+
+- (void)configureInternalListenerFor:(NSInteger)messageType {
+ switch ((ABKUnityMessageType)messageType) {
+ case ABKPushPermissionsPromptResponse:
+ NSLog(@"Enabling internal push permissions prompt response listener.");
+ self.sendInternalPushPermissionsPromptResponse = YES;
+ break;
+ case ABKPushTokenReceivedFromSystem:
+ NSLog(@"Enabling push token received from system listener.");
+ self.sendPushTokenReceivedFromSystem = YES;
+ break;
+ default:
+ NSLog(@"Unknown internal message type received.");
+ return;
}
}
diff --git a/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Appboy_iOS_SDK.meta b/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Appboy_iOS_SDK.meta
new file mode 100644
index 000000000..6c94f8019
--- /dev/null
+++ b/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Appboy_iOS_SDK.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 5e8ae10fcfc554bd8840e2d1787a6af4
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Headers.meta b/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Headers.meta
new file mode 100644
index 000000000..a1f67790c
--- /dev/null
+++ b/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Headers.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 59d3d1cc8cbe24b21a98cdd0463614fe
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Modules.meta b/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Modules.meta
new file mode 100644
index 000000000..c39a88287
--- /dev/null
+++ b/Assets/Plugins/iOS/Appboy_iOS_SDK.framework/Modules.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 878ec4b6e380f47dbbb98e0507600728
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/SDWebImage.framework/Headers.meta b/Assets/Plugins/iOS/SDWebImage.framework/Headers.meta
new file mode 100644
index 000000000..3eb061e5b
--- /dev/null
+++ b/Assets/Plugins/iOS/SDWebImage.framework/Headers.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 60eb0b185d9144c55985149ff6e5db95
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/SDWebImage.framework/Modules.meta b/Assets/Plugins/iOS/SDWebImage.framework/Modules.meta
new file mode 100644
index 000000000..657cb69c0
--- /dev/null
+++ b/Assets/Plugins/iOS/SDWebImage.framework/Modules.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2bd9c2ede956d47afb9a427a5a138aee
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/SDWebImage.framework/PrivateHeaders.meta b/Assets/Plugins/iOS/SDWebImage.framework/PrivateHeaders.meta
new file mode 100644
index 000000000..7a3c23b84
--- /dev/null
+++ b/Assets/Plugins/iOS/SDWebImage.framework/PrivateHeaders.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0f38ec10d63a145f9bd48f39127b169c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/iOS/SDWebImage.framework/SDWebImage.meta b/Assets/Plugins/iOS/SDWebImage.framework/SDWebImage.meta
new file mode 100644
index 000000000..432d24a09
--- /dev/null
+++ b/Assets/Plugins/iOS/SDWebImage.framework/SDWebImage.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 69663173c0f5c4712a7e738101a6ab0c
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3c88db47..7cddbb546 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,36 @@
+## 3.0.0
+
+##### Important
+- This release contains several minor changes to our iOS push code. Most integrations will be unaffected, however, we recommend additional testing.
+
+##### Breaking
+- Updated the Android plugin to use [Braze Android SDK 13.0.0](https://github.com/Appboy/appboy-android-sdk/blob/master/CHANGELOG.md#1300).
+- If automatic iOS push integration is enabled, Braze will now automatically add the Xcode Push Capability in `OnPostprocessBuild()`.
+ - To disable this, check "Disable Automatic Push Capability" in the Braze configuration editor.
+- In `AppboyUnityManager.mm`:
+ - `registerForRemoteNotifications:` has been replaced with `registerForRemoteNotificationsWithProvisional:(BOOL)provisional`. If using this method, note that the new method calls Apple's APIs directly and does not respect Braze configuration's settings for automatic push integration and registration.
+ - `registerApplication:didReceiveRemoteNotification:fetchCompletionHandler:` and `registerPushToken` have also been updated to no longer internally read Braze config.
+ - Several obsolete methods were removed, including methods where the manager trivially wrapped the native `Appboy` instance.
+ - Most integrations will not be affected by these changes.
+
+##### Added
+- Added the option to disable iOS provisional push authorization when automatic iOS push integration is enabled.
+ - To use, check "Disable Provisional Authorization" in the Braze configuration editor.
+ - When provisional push authorization is disabled, users will see the native push prompt dialog at app startup.
+- Added `AppboyBinding.ConfigureListener()` as an alternative method for configuring GameObject listeners for push, in-app messages, Content Cards, and News Feed. Use the new `BrazeUnityMessageType` enum to specify the desired message type.
+ - On iOS, to receive push opened and received callbacks, `Integrate Push With Braze` must be enabled.
+- Added `AppboyBinding.PromptUserForPushPermissions(bool provisional)` to request authorization and register for push notifications on iOS.
+ - Set `provisional` to `true` to request provisional authorization, or `false` to show the push prompt directly.
+ - If you would like to read the user response, pass an instance of `PushPromptResponseReceived` into the method.
+ - We recommend using this method with the following settings:
+ - `Integrate Push With Braze` enabled.
+ - `Disable Automatic Push Registration` enabled.
+- Added `AppboyBinding.SetPushTokenReceivedFromSystemDelegate()` to receive push tokens Braze receives from the OS (iOS only).
+
+##### Fixed
+- Braze push delegates are no longer called automatically in fully manual integrations.
+ - Automatic push integration must be enabled for Braze push delegates to function.
+
## 2.8.0
##### Breaking
diff --git a/scripts/manual_move_aars_from_m2.sh b/scripts/manual_move_aars_from_m2.sh
new file mode 100755
index 000000000..fe1e9619d
--- /dev/null
+++ b/scripts/manual_move_aars_from_m2.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+VERSION=$1
+
+cp ~/.m2/repository/com/appboy/android-sdk-base/$VERSION/android-sdk-base-$VERSION.aar ../Assets/Plugins/Android/appboy.aar
+cp ~/.m2/repository/com/appboy/android-sdk-ui/$VERSION/android-sdk-ui-$VERSION.aar ../Assets/Plugins/Android/appboy-ui.aar
+cp ~/.m2/repository/com/appboy/android-sdk-unity/$VERSION/android-sdk-unity-$VERSION.aar ../Assets/Plugins/Android/appboy-unity.aar
diff --git a/scripts/release.rb b/scripts/release.rb
index 7811543f9..fdcbdbbba 100755
--- a/scripts/release.rb
+++ b/scripts/release.rb
@@ -10,7 +10,7 @@
def check_and_remove_directory(directory)
if File.exists?(directory)
- `rm -rf #{directory}`
+ `rm -rf #{directory}`
end
end
@@ -83,6 +83,7 @@ def pretty_puts(msg)
check_and_remove_directory("Public/Plugins")
check_and_remove_directory("Public/Assets")
check_and_remove_directory("Public/scripts")
+check_and_remove_directory("unity-samples/build")
pretty_puts("Copying sample app, scripts and Assets folder into Public")
puts `cp -vR "Assets" "Public"`