diff --git a/Assets/Plugins/Android/appboy-unity.aar b/Assets/Plugins/Android/appboy-unity.aar index 771c552d..7d4b7375 100644 Binary files a/Assets/Plugins/Android/appboy-unity.aar and b/Assets/Plugins/Android/appboy-unity.aar differ diff --git a/Assets/Plugins/Appboy/AppboyBinding.cs b/Assets/Plugins/Appboy/AppboyBinding.cs index aff13cd6..4554f8e7 100755 --- a/Assets/Plugins/Appboy/AppboyBinding.cs +++ b/Assets/Plugins/Appboy/AppboyBinding.cs @@ -76,6 +76,26 @@ public enum BrazeUnityMessageType { CONTENT_CARDS_UPDATED = 7 } + public enum BrazeUnityInAppMessageDisplayActionType { + /// + /// Sets In-App Messages to display immediately when triggered. + /// + IAM_DISPLAY_NOW = 0, + /// + /// Sets In-App Messages to display at a later time and be saved in a stack. + /// + IAM_DISPLAY_LATER = 1, + /// + /// Sets In-App Messages to be discarded after being triggered. + /// + IAM_DISCARD = 2, + // TODO - Blocked by SDK-1596 + // /// + // /// Requests that any In-App Message previously saved to a stack to be displayed immediately. + // /// + // REQUEST_IAM_DISPLAY = 3 + } + public delegate void PushPromptResponseReceived(bool granted); public delegate void PushTokenReceivedFromSystem(string token); @@ -86,6 +106,8 @@ public static BrazePlatform mBinding { return new BrazeAndroidPlatform(); #elif UNITY_IOS return new BrazeiOSPlatform(); + #else + return null; #endif } } @@ -598,5 +620,17 @@ public static void ConfigureListener(BrazeUnityMessageType messageType, string g mBinding.ConfigureListener(messageType, gameobject, method); #endif } + + public static void SetInAppMessageDisplayAction(BrazeUnityInAppMessageDisplayActionType actionType) { + #if HAS_BRAZE_SDK + mBinding.SetInAppMessageDisplayAction(actionType); + #endif + } + + public static void DisplayContentCards() { + #if HAS_BRAZE_SDK + mBinding.DisplayContentCards(); + #endif + } } } diff --git a/Assets/Plugins/Appboy/BrazeAndroidPlatform.cs b/Assets/Plugins/Appboy/BrazeAndroidPlatform.cs index e0df4ea2..826fb008 100644 --- a/Assets/Plugins/Appboy/BrazeAndroidPlatform.cs +++ b/Assets/Plugins/Appboy/BrazeAndroidPlatform.cs @@ -474,6 +474,14 @@ public void AddAlias(string alias, string label) { public void ConfigureListener(BrazeUnityMessageType messageType, string gameobject, string method) { UnityConfigurationProvider.Call("configureListener", (int)messageType, gameobject, method); } + + public void SetInAppMessageDisplayAction(BrazeUnityInAppMessageDisplayActionType actionType) { + AppboyUnityActivity.Call("onNewUnityInAppMessageManagerAction", (int)actionType); + } + + public void DisplayContentCards() { + AppboyUnityActivity.Call("launchContentCardsActivity"); + } } #endif diff --git a/Assets/Plugins/Appboy/BrazePlatform.cs b/Assets/Plugins/Appboy/BrazePlatform.cs index 7fa00c53..ce60a4da 100644 --- a/Assets/Plugins/Appboy/BrazePlatform.cs +++ b/Assets/Plugins/Appboy/BrazePlatform.cs @@ -116,4 +116,6 @@ string profileImageUrl void RequestImmediateDataFlush(); void AddAlias(string alias, string label); void ConfigureListener(BrazeUnityMessageType messageType, string gameobject, string method); + void SetInAppMessageDisplayAction(BrazeUnityInAppMessageDisplayActionType actionType); + void DisplayContentCards(); } diff --git a/Assets/Plugins/Appboy/BrazeiOSPlatform.cs b/Assets/Plugins/Appboy/BrazeiOSPlatform.cs index e3c95acc..772f50dd 100644 --- a/Assets/Plugins/Appboy/BrazeiOSPlatform.cs +++ b/Assets/Plugins/Appboy/BrazeiOSPlatform.cs @@ -92,6 +92,9 @@ public class BrazeiOSPlatform : BrazePlatform { [System.Runtime.InteropServices.DllImport("__Internal")] private static extern void _setUserTwitterData(int twitterUserId, string twitterHandle, string name, string description, int followerCount, int followingCount, int tweetCount, string profileImageUrl); + [System.Runtime.InteropServices.DllImport("__Internal")] + private static extern void _setInAppMessageDisplayAction(int actionType); + [System.Runtime.InteropServices.DllImport("__Internal")] private static extern void _logInAppMessageClicked(string inAppMessageJSONString); @@ -131,6 +134,9 @@ public class BrazeiOSPlatform : BrazePlatform { [System.Runtime.InteropServices.DllImport("__Internal")] private static extern void _requestContentCardsRefreshFromCache(); + [System.Runtime.InteropServices.DllImport("__Internal")] + private static extern void _displayContentCards(); + [System.Runtime.InteropServices.DllImport("__Internal")] private static extern void _logContentCardsDisplayed(); @@ -299,6 +305,10 @@ public void DisplayNextInAppMessage(bool withDelegate) { _displayNextInAppMessage(withDelegate); } + public void SetInAppMessageDisplayAction(BrazeUnityInAppMessageDisplayActionType actionType) { + _setInAppMessageDisplayAction((int)actionType); + } + public void LogInAppMessageClicked(string inAppMessageJSONString) { _logInAppMessageClicked(inAppMessageJSONString); } @@ -351,6 +361,10 @@ public void RequestContentCardsRefreshFromCache() { _requestContentCardsRefreshFromCache(); } + public void DisplayContentCards() { + _displayContentCards(); + } + public void LogContentCardsDisplayed() { _logContentCardsDisplayed(); } diff --git a/Assets/Plugins/iOS/AppboyBinding.m b/Assets/Plugins/iOS/AppboyBinding.m index 96d25967..f0e41c7d 100644 --- a/Assets/Plugins/iOS/AppboyBinding.m +++ b/Assets/Plugins/iOS/AppboyBinding.m @@ -218,6 +218,10 @@ void _displayNextInAppMessage(bool withDelegate) { [[AppboyUnityManager sharedInstance] displayNextInAppMessageWithDelegate:withDelegate]; } +void _setInAppMessageDisplayAction(int actionType) { + [[AppboyUnityManager sharedInstance] setInAppMessageDisplayAction:actionType]; +} + # pragma mark - News Feed analytics void _logCardImpression(const char* cardJSONString) { @@ -256,6 +260,10 @@ void _logContentCardDismissed(const char* cardJSONString) { [[AppboyUnityManager sharedInstance] logContentCardDismissed:GetStringParam(cardJSONString)]; } +void _displayContentCards() { + [[AppboyUnityManager sharedInstance] displayContentCards]; +} + void _logContentCardsDisplayed() { [[Appboy sharedInstance] logContentCardsDisplayed]; } diff --git a/Assets/Plugins/iOS/AppboyUnityManager.h b/Assets/Plugins/iOS/AppboyUnityManager.h index f5acba03..7e50a9e0 100644 --- a/Assets/Plugins/iOS/AppboyUnityManager.h +++ b/Assets/Plugins/iOS/AppboyUnityManager.h @@ -32,6 +32,16 @@ typedef NS_ENUM(NSInteger, ABKUnityMessageType) { ABKContentCardsUpdated = 7 }; +/** + * These must correspond 1:1 to BrazeUnityInAppMessageDisplayActionType in AppboyBinding.cs. + */ +typedef NS_ENUM(NSInteger, ABKUnityInAppMessageDisplayActionType) { + ABKIAMDisplayNow = 0, + ABKIAMDisplayLater = 1, + ABKIAMDiscard = 2, + ABKIAMRequestIAMDisplay = 3 +}; + @interface AppboyUnityManager : NSObject @property (nonatomic,copy) NSDictionary *appboyUnityPlist; @@ -51,6 +61,7 @@ typedef NS_ENUM(NSInteger, ABKUnityMessageType) { @property (nonatomic, copy) NSString *unityPushTokenReceivedFromSystemFunctionName; @property (nonatomic) BOOL sendInternalPushPermissionsPromptResponse; @property (nonatomic) BOOL sendPushTokenReceivedFromSystem; +@property (nonatomic) ABKInAppMessageDisplayChoice displayAction; + (AppboyUnityManager *) sharedInstance; - (NSString *)getApiKeyFromUnity; @@ -65,6 +76,7 @@ typedef NS_ENUM(NSInteger, ABKUnityMessageType) { - (void)logInAppMessageClicked:(NSString *)inAppMessageJSONString; - (void)logInAppMessageButtonClicked:(NSString *)inAppMessageJSONString withButtonID:(NSInteger)buttonID; - (void)displayNextInAppMessageWithDelegate:(BOOL)withDelegate; +- (void)setInAppMessageDisplayAction:(int)actionType; // News Feed - (void)logCardImpression:(NSString *)cardJSONString; @@ -78,6 +90,7 @@ typedef NS_ENUM(NSInteger, ABKUnityMessageType) { - (void)logContentCardDismissed:(NSString *)cardJSONString; - (void)requestContentCardsRefresh; - (void)requestContentCardsFromCache:(NSNotification *)notification; +- (void)displayContentCards; /*! * @discussion Passes the device token to Braze. The caller is responsible for respecting diff --git a/Assets/Plugins/iOS/AppboyUnityManager.mm b/Assets/Plugins/iOS/AppboyUnityManager.mm index 12d070d7..aa19c631 100644 --- a/Assets/Plugins/iOS/AppboyUnityManager.mm +++ b/Assets/Plugins/iOS/AppboyUnityManager.mm @@ -3,6 +3,8 @@ #import #import #import +#import +#import static NSString *const ABKInternalCallback = @"BrazeInternalCallback"; static NSString *const ABKInternalPushPermissionsPromptResponse = @"onPushPromptResponseReceived"; @@ -31,6 +33,16 @@ + (AppboyUnityManager*)sharedInstance { return sharedInstance; } +# pragma mark - Init + +- (instancetype)init { + self = [super init]; + if (self) { + self.displayAction = ABKDisplayInAppMessageNow; + } + return self; +} + # pragma mark - Config - (NSString *)getApiKeyFromUnity { @@ -120,13 +132,39 @@ - (void)getInAppMessageFromString:(NSString *)inAppMessageJSONString withInAppMe # pragma mark - In-app message display - (void)displayNextInAppMessageWithDelegate:(BOOL)withDelegate { - ABKInAppMessageController *delegate = nil; + id delegate = nil; if (withDelegate) { delegate = [Appboy sharedInstance].inAppMessageController.delegate; } [[Appboy sharedInstance].inAppMessageController displayNextInAppMessageWithDelegate:delegate]; } +- (void)setInAppMessageDisplayAction:(int)actionType { + [Appboy sharedInstance].inAppMessageController.delegate = self; + switch ((ABKUnityInAppMessageDisplayActionType)actionType) { + case ABKIAMDisplayNow: + NSLog(@"Setting in-app message display action to ABKDisplayInAppMessageNow."); + self.displayAction = ABKDisplayInAppMessageNow; + break; + case ABKIAMDisplayLater: + NSLog(@"Setting in-app message display action to ABKDisplayInAppMessageLater."); + self.displayAction = ABKDisplayInAppMessageLater; + break; + case ABKIAMDiscard: + NSLog(@"Setting in-app message display action to ABKIAMDiscard."); + self.displayAction = ABKDiscardInAppMessage; + break; + case ABKIAMRequestIAMDisplay: + // FIXME: Blocked by SDK-1596 + NSLog(@"Requesting in-app message display (currently unimplemented)."); + // [[Appboy sharedInstance].inAppMessageController displayNextInAppMessageWithDelegate:nil]; + break; + default: + NSLog(@"Unknown in-app message display action type received."); + return; + } +} + # pragma mark - News Feed analytics - (void)logCardImpression:(NSString *)cardJSONString { @@ -267,6 +305,15 @@ - (void)requestContentCardsFromCache:(NSNotification *)notification { [self unitySendMessageTo:self.unityContentCardsGameObjectName withMethod:self.unityContentCardsCallbackFunctionName withMessage:contentCardsString]; } +# pragma mark - Content Card UI + +- (void)displayContentCards { + ABKContentCardsViewController *contentCards = [[ABKContentCardsViewController alloc] init]; + [ABKUIUtils.activeApplicationViewController presentViewController:contentCards + animated:YES + completion:nil]; +} + # pragma mark - Push - (void)registerPushToken:(NSData *)data { @@ -493,17 +540,16 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center */ - (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; + NSLog(@"No properly configured game object for in-app messages. Using display action: %ld.", (long)self.displayAction); + return self.displayAction; } 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; + NSLog(@"Braze configured to display in-app messages despite presence of game object listener. Using display action: %ld.", (long)self.displayAction); + return self.displayAction; } return ABKDiscardInAppMessage; } diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bcb6be3..cfa78f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 3.4.0 + +##### Added +- Added the ability to change the display flow of In-App Messages directly from Unity code via `AppboyBinding.SetInAppMessageDisplayAction()`. + - See the `BrazeUnityInAppMessageDisplayActionType` enum. +- Added the ability to open the default Content Cards UI via `DisplayContentCards()` on the binding. + - For Android, this requires the following dependencies: + ``` + implementation "androidx.swiperefreshlayout:swiperefreshlayout:+" + implementation "androidx.recyclerview:recyclerview:+" + ``` + ## 3.3.0 ##### Breaking