Skip to content

Commit

Permalink
Push notification extensions in example
Browse files Browse the repository at this point in the history
  • Loading branch information
adam1929 authored Sep 27, 2023
1 parent bca0fa6 commit bf0f293
Show file tree
Hide file tree
Showing 39 changed files with 602 additions and 94 deletions.
4 changes: 3 additions & 1 deletion BloomreachSDK/BloomreachSDK.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<PropertyGroup>
<PackageId>BloomreachSDK</PackageId>
<PackageVersion>0.1.0</PackageVersion>
<ReleaseVersion>0.1.0</ReleaseVersion>
<Authors>Bloomreach</Authors>
<Title>BloomreachSDK</Title>
<Description>Bloomreach SDK allows your application to interact with the Bloomreach Customer Data &amp; Experience Platform. Bloomreach empowers B2C marketers to raise conversion rates, improve acquisition ROI, and maximize customer lifetime value.</Description>
Expand Down Expand Up @@ -46,6 +45,9 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-ios|AnyCPU'">
<CreatePackage>false</CreatePackage>
</PropertyGroup>
<ItemGroup>
<None Remove="Platforms\Android\" />
<None Remove="Platforms\iOS\" />
Expand Down
36 changes: 31 additions & 5 deletions BloomreachSDK/Lib/BloomreachSDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading.Tasks;
using Bloomreach.Utils;
#if IOS
using UIKit;
using UserNotifications;
using Foundation;
#endif
Expand Down Expand Up @@ -339,9 +340,13 @@ public static bool HandleRemoteMessage(NotificationPayload payload)

#if IOS
[SupportedOSPlatform("ios")]
public static bool HandleRemoteMessage(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
public static bool HandleRemoteMessage(
string appGroup,
UNNotificationRequest request,
Action<UNNotificationContent> contentHandler
)
{
string? result = Instance.Channel.HandleRemoteMessage(request, contentHandler);
string? result = Instance.Channel.HandleRemoteMessage(appGroup, request, contentHandler);
return ConverterUtils.ToBool(result);
}

Expand All @@ -350,11 +355,23 @@ public static void HandleRemoteMessageTimeWillExpire()
{
Instance.Channel.InvokeMethod("HandleRemoteMessageTimeWillExpire", null);
}

[SupportedOSPlatform("ios")]
public static void HandleNotificationReceived(
UNNotification notification,
NSExtensionContext? extensionContext,
UIViewController notificationViewController
)
{
Instance.Channel.HandleNotificationReceived(notification, extensionContext, notificationViewController);
}
#endif

public static void HandlePushNotificationOpened(NotificationAction action)
{
Console.WriteLine("APNS-BR Calling HandlePushNotificationOpened");
Instance.Channel.InvokeMethod("HandlePushNotificationOpened", ConverterUtils.SerializeInput(action));
Console.WriteLine("APNS-BR Calling HandlePushNotificationOpened is DONE");
}

public static void HandlePushNotificationOpenedWithoutTrackingConsent(NotificationAction action)
Expand All @@ -378,9 +395,15 @@ public static void HandlePushToken(string pushToken)
}

#if IOS
public static void HandlePushToken(NSData pushToken)
public static void HandlePushToken(NSData deviceToken)
{
Instance.Channel.InvokeMethod("HandlePushToken", pushToken.ToString(NSStringEncoding.UTF8));
var bytes = deviceToken.ToArray<byte>();
var hexArray = bytes.Select(b => b.ToString("X2")).ToArray();
var deviceTokenString = string.Join(string.Empty, hexArray);
Console.WriteLine("APNS-BR Push token received");
Console.WriteLine("APNS-BR Push token " + deviceTokenString);
Console.WriteLine("APNS-BR Push token printed");
Instance.Channel.InvokeMethod("HandlePushToken", deviceTokenString);
}
#endif

Expand Down Expand Up @@ -437,7 +460,10 @@ public static void TrackHmsPushToken(string pushToken)

public static void RequestPushAuthorization()
{
Instance.Channel.InvokeMethod("RequestPushAuthorization", null);
Instance.Channel.InvokeMethodAsync("RequestAuthorization", null, (s, exception) =>
{
Console.WriteLine("APNS-BR Requested permission with result " + s);
});
}

public static void SetReceivedPushCallback(Action<NotificationPayload> listener)
Expand Down
48 changes: 43 additions & 5 deletions BloomreachSDK/Lib/MethodChannelConsumer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#if IOS
#if IOS
using Bloomreach.Platforms.iOS;
using Foundation;
using UIKit;
using UserNotifications;
#endif

Expand Down Expand Up @@ -134,23 +135,60 @@ internal virtual void InvokeMethodAsync(string method, string? data, Action<stri
#elif IOS
try
{
Console.WriteLine("APNS-BR Invoking handle remote message");
var result = ((MethodChannelConsumerIos)_channelInternal!).HandleRemoteMessage(
(UNNotificationRequest)args[0],
(Action<UNNotificationContent>)args[1]
(string)args[0],
(UNNotificationRequest)args[1],
(Action<UNNotificationContent>)args[2]
);
if (result?.Success == false)
{
BloomreachSDK.ThrowOrLog(new Exception($"Method HandleRemoteMessage return failure status, see logs"));
BloomreachSDK.ThrowOrLog(
new Exception($"Method HandleRemoteMessage return failure status, see logs: {result?.Error}")
);
}
Console.WriteLine("APNS-BR HandleRemoteMessage done");
return result?.Data;
}
catch (Exception e)
{
Console.WriteLine("APNS-BR Handle remote message errored " + e);
BloomreachSDK.ThrowOrLog(e);
return null;
}
#else
return null;
#endif
}

public void HandleNotificationReceived(params object[] args)
{
#if ANDROID
BloomreachSDK.ThrowOrLog(new Exception($"Method HandleNotificationReceived is not supported on Android"));
#elif IOS
try
{
Console.WriteLine("APNS-BR Invoking HandleNotificationReceived");
var result = ((MethodChannelConsumerIos)_channelInternal!).HandleNotificationReceived(
(UNNotification)args[0],
(NSExtensionContext?)args[1],
(UIViewController)args[2]
);
if (result?.Success == false)
{
BloomreachSDK.ThrowOrLog(
new Exception($"Method HandleNotificationReceived return failure status, see logs: {result?.Error}")
);
}
Console.WriteLine("APNS-BR HandleNotificationReceived done");
}
catch (Exception e)
{
Console.WriteLine("APNS-BR HandleNotificationReceived errored " + e);
BloomreachSDK.ThrowOrLog(e);
}
#else
BloomreachSDK.ThrowOrLog(new Exception($"Method HandleNotificationReceived is working only on iOS platform"));
#endif
}
}
Expand Down
10 changes: 7 additions & 3 deletions BloomreachSDK/Lib/Models/NotificationAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public NotificationAction(string actionType, string actionName, string url)

public string? ActionIdentifier { get; set; }

public Dictionary<string, object> Attributes { get; set; } = new ();
public Dictionary<string, object?> Attributes { get; set; } = new ();

public NotificationAction WithAttribute(string key, object value)
{
Expand All @@ -43,11 +43,15 @@ public NotificationAction WithAttributes(IDictionary<string, object> properties)
#if IOS
public static NotificationAction Parse(UNNotificationResponse response)
{
#pragma warning disable CA1416
var payload = response.Notification.Request.Content.UserInfo;
var identifier = response.ActionIdentifier;
return new NotificationAction(
var identifier = response.ActionIdentifier.ToString();
#pragma warning restore CA1416
var target = new NotificationAction(
identifier, identifier, identifier
).WithAttributes(ConverterUtils.NormalizeDictionary(payload));
target.ActionIdentifier = identifier;
return target;
}

public static NotificationAction Parse(NSDictionary userInfo)
Expand Down
17 changes: 12 additions & 5 deletions BloomreachSDK/Lib/Utils/ConverterUtils.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
#if IOS
using Bloomreach.Platforms.iOS;
using Foundation;
#endif
using Newtonsoft.Json;
Expand All @@ -18,10 +16,14 @@ public static class ConverterUtils
Formatting = Formatting.None,
Converters = new List<JsonConverter>()
{
#if IOS
new NSObjectConverter(),
#endif
new DictionaryConverter(),
new StringEnumConverter()
},
ContractResolver = new CamelCasePropertyNamesContractResolver()
ContractResolver = new CamelCasePropertyNamesContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

public static string? SerializeInput(object? data)
Expand Down Expand Up @@ -60,10 +62,15 @@ public static IDictionary<string, object> NormalizeDictionary(IDictionary<string
#if IOS
public static IDictionary<string, object> NormalizeDictionary(NSDictionary source)
{
return source.ToDictionary<KeyValuePair<NSObject, NSObject>, string, object>(
#pragma warning disable CA1416
Console.WriteLine("APNS-BR Normalizing NSDictionary");
var result = source.ToDictionary<KeyValuePair<NSObject, NSObject>, string, object>(
item => item.Key as NSString,
item => item.Value
);
Console.WriteLine("APNS-BR Normalizing done");
return result;
#pragma warning restore CA1416
}
#endif

Expand Down
44 changes: 42 additions & 2 deletions BloomreachSDK/Platforms/iOS/MethodChannelConsumerIos.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@


using Foundation;
using UIKit;
using UserNotifications;

namespace Bloomreach.Platforms.iOS
Expand All @@ -23,10 +25,18 @@ void IMethodChannelConsumerPlatformSpecific.InvokeMethodAsync(string method, str
{
try
{
if (method == "RequestAuthorization")
{
Console.WriteLine("APNS-BR PushRequest requested");
}
NativeSdk.InvokeMethodAsyncWithMethod(method, data, delegate (BloomreachSdkNativeiOS.MethodResult nativeResult)
{
try
{
if (method == "RequestAuthorization")
{
Console.WriteLine("APNS-BR PushRequest responded " + nativeResult.Success);
}
var mauiResult = new MethodMauiResult(
nativeResult.Success,
nativeResult.Data,
Expand Down Expand Up @@ -64,17 +74,47 @@ MethodMauiResultForView IMethodChannelConsumerPlatformSpecific.InvokeUiMethod(st
return mauiResult;
}

internal MethodMauiResult HandleRemoteMessage(UNNotificationRequest notificationRequest, Action<UNNotificationContent> handler)
internal MethodMauiResult HandleRemoteMessage(
string appGroup,
UNNotificationRequest notificationRequest,
Action<UNNotificationContent> handler
)
{
var nativeResult = NativeSdk.HandleRemoteMessageWithNotificationRequest(
Console.WriteLine("APNS-BR Native Handle message consumer starts");
var nativeResult = NativeSdk.HandleRemoteMessageWithAppGroup(
appGroup,
notificationRequest,
handler
);
Console.WriteLine("APNS-BR Native handle message consumer done");
var mauiResult = new MethodMauiResult(
nativeResult.Success,
nativeResult.Data,
nativeResult.Error
);
Console.WriteLine("APNS-BR Native handle message consumer mapped");
return mauiResult;
}

internal MethodMauiResult HandleNotificationReceived(
UNNotification notification,
NSExtensionContext? context,
UIViewController viewController
)
{
Console.WriteLine("APNS-BR Native HandleNotificationReceived starts");
var nativeResult = NativeSdk.HandleRemoteMessageContentWithNotification(
notification,
context,
viewController
);
Console.WriteLine("APNS-BR Native HandleNotificationReceived done");
var mauiResult = new MethodMauiResult(
nativeResult.Success,
nativeResult.Data,
nativeResult.Error
);
Console.WriteLine("APNS-BR Native HandleNotificationReceived mapped");
return mauiResult;
}
}
Expand Down
56 changes: 56 additions & 0 deletions BloomreachSDK/Platforms/iOS/NSObjectConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Foundation;
using Newtonsoft.Json;

namespace Bloomreach.Platforms.iOS;

public class NSObjectConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(NSObject).IsAssignableFrom(objectType);
}

public override bool CanRead => false;

public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value == null)
{
return;
}
if (value is NSDictionary dictionary)
{
writer.WriteStartObject();
foreach (var pair in dictionary)
{
if (pair.Key == null || pair.Value == null) continue;
writer.WritePropertyName(pair.Key.ToString());
serializer.Serialize(writer, pair.Value);
}
writer.WriteEndObject();
return;
}
if (value is NSArray array)
{
writer.WriteStartArray();
foreach (var item in array)
{
if (item == null) continue;
serializer.Serialize(writer, item);
}
writer.WriteEndArray();
return;
}
if (value is NSNull nsNull)
{
writer.WriteNull();
return;
}
writer.WriteValue(value.ToString());
}

public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Loading

0 comments on commit bf0f293

Please sign in to comment.