cleanup and simplify ios push reg/handling

This commit is contained in:
Kyle Spearrin 2017-12-21 23:26:46 -05:00
parent fb76ecf198
commit bcf49ab396
5 changed files with 96 additions and 228 deletions

View file

@ -1,78 +0,0 @@
namespace Bit.App.Utilities
{
public static class PushNotificationContants
{
/// <summary>
/// Type
/// </summary>
public const string Type = "type";
/// <summary>
/// Error
/// </summary>
public const string Error = "error";
/// <summary>
/// Domain Name
/// </summary>
public const string DomainName = "CrossPushNotification";
/// <summary>
/// Title
/// </summary>
public const string Title = "title";
/// <summary>
/// Text
/// </summary>
public const string Text = "text";
/// <summary>
/// Subtitle
/// </summary>
public const string Subtitle = "subtitle";
/// <summary>
/// Message
/// </summary>
public const string Message = "message";
/// <summary>
/// Silent
/// </summary>
public const string Silent = "silent";
/// <summary>
/// Alert
/// </summary>
public const string Alert = "alert";
/// <summary>
/// Data
/// </summary>
public const string Data = "data";
/// <summary>
/// Token
/// </summary>
public const string Token = "token";
/// <summary>
/// App Version
/// </summary>
public const string AppVersion = "appVersion";
/// <summary>
/// IntentFromGcmMessage
/// </summary>
public const string IntentFromGcmMessage = "com.google.android.c2dm.intent.RECEIVE";
/// <summary>
/// BackOffMilliseconds
/// </summary>
public const string BackOffMilliseconds = "backoff_ms";
/// <summary>
/// ErrorServiceNotAvailable
/// </summary>
public const string ErrorServiceNotAvailable = "SERVICE_NOT_AVAILABLE";
/// <summary>
/// Tag
/// </summary>
public const string Tag = "tag";
/// <summary>
/// Id
/// </summary>
public const string Id = "id";
/// <summary>
/// RegistrationComplete
/// </summary>
public const string RegistrationComplete = "registrationComplete";
}
}

View file

@ -29,6 +29,7 @@ namespace Bit.iOS
{ {
private GaiCompletionHandler _dispatchHandler = null; private GaiCompletionHandler _dispatchHandler = null;
private ILockService _lockService; private ILockService _lockService;
private iOSPushNotificationHandler _pushHandler = null;
public ISettings Settings { get; set; } public ISettings Settings { get; set; }
@ -42,7 +43,9 @@ namespace Bit.iOS
} }
_lockService = Resolver.Resolve<ILockService>(); _lockService = Resolver.Resolve<ILockService>();
_pushHandler = new iOSPushNotificationHandler(Resolver.Resolve<IPushNotificationListener>());
var appIdService = Resolver.Resolve<IAppIdService>(); var appIdService = Resolver.Resolve<IAppIdService>();
var crashManagerDelegate = new HockeyAppCrashManagerDelegate( var crashManagerDelegate = new HockeyAppCrashManagerDelegate(
appIdService, Resolver.Resolve<IAuthService>()); appIdService, Resolver.Resolve<IAuthService>());
var manager = BITHockeyManager.SharedHockeyManager; var manager = BITHockeyManager.SharedHockeyManager;
@ -201,18 +204,12 @@ namespace Bit.iOS
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{ {
if(CrossPushNotification.Current is IPushNotificationHandler handler) _pushHandler?.OnErrorReceived(error);
{
handler.OnErrorReceived(error);
}
} }
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{ {
if(CrossPushNotification.Current is IPushNotificationHandler handler) _pushHandler?.OnRegisteredSuccess(deviceToken);
{
handler.OnRegisteredSuccess(deviceToken);
}
} }
public override void DidRegisterUserNotificationSettings(UIApplication application, public override void DidRegisterUserNotificationSettings(UIApplication application,
@ -224,18 +221,12 @@ namespace Bit.iOS
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
Action<UIBackgroundFetchResult> completionHandler) Action<UIBackgroundFetchResult> completionHandler)
{ {
if(CrossPushNotification.Current is IPushNotificationHandler handler) _pushHandler?.OnMessageReceived(userInfo);
{
handler.OnMessageReceived(userInfo);
}
} }
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{ {
if(CrossPushNotification.Current is IPushNotificationHandler handler) _pushHandler?.OnMessageReceived(userInfo);
{
handler.OnMessageReceived(userInfo);
}
} }
private void SendResumedMessage() private void SendResumedMessage()
@ -298,12 +289,10 @@ namespace Bit.iOS
container.RegisterSingleton(Settings); container.RegisterSingleton(Settings);
// Push // Push
var pushListener = new PushNotificationListener(); container.RegisterSingleton<IPushNotificationListener, PushNotificationListener>();
container.RegisterSingleton<IPushNotificationListener>(pushListener); container.RegisterSingleton<IPushNotificationService, iOSPushNotificationService>();
CrossPushNotification.Initialize(pushListener);
container.RegisterSingleton(CrossPushNotification.Current);
CachedImageRenderer.Init();
CachedImageRenderer.Init();
Resolver.SetResolver(new SimpleInjectorResolver(container)); Resolver.SetResolver(new SimpleInjectorResolver(container));
} }

View file

@ -0,0 +1,71 @@
using Bit.App.Abstractions;
using Foundation;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using Xamarin.Forms;
namespace Bit.iOS.Services
{
public class iOSPushNotificationHandler
{
private const string TokenSetting = "token";
private const string DomainName = "iOSPushNotificationService";
private readonly IPushNotificationListener _pushNotificationListener;
public iOSPushNotificationHandler(
IPushNotificationListener pushNotificationListener)
{
_pushNotificationListener = pushNotificationListener;
}
public void OnMessageReceived(NSDictionary userInfo)
{
var json = DictionaryToJson(userInfo);
var values = JObject.Parse(json);
var keyAps = new NSString("aps");
if(userInfo.ContainsKey(keyAps) && userInfo.ValueForKey(keyAps) is NSDictionary aps)
{
foreach(var apsKey in aps)
{
if(!values.TryGetValue(apsKey.Key.ToString(), out JToken temp))
{
values.Add(apsKey.Key.ToString(), apsKey.Value.ToString());
}
}
}
_pushNotificationListener.OnMessage(values, Device.iOS);
}
public void OnErrorReceived(NSError error)
{
Debug.WriteLine("{0} - Registration Failed.", DomainName);
_pushNotificationListener.OnError(error.LocalizedDescription, Device.iOS);
}
public void OnRegisteredSuccess(NSData token)
{
Debug.WriteLine("{0} - Successfully Registered.", DomainName);
var trimmedDeviceToken = token.Description;
if(!string.IsNullOrWhiteSpace(trimmedDeviceToken))
{
trimmedDeviceToken = trimmedDeviceToken.Trim('<').Trim('>').Trim().Replace(" ", string.Empty);
}
Console.WriteLine("{0} - Token: {1}", DomainName, trimmedDeviceToken);
_pushNotificationListener.OnRegistered(trimmedDeviceToken, Device.iOS);
NSUserDefaults.StandardUserDefaults.SetString(trimmedDeviceToken, TokenSetting);
NSUserDefaults.StandardUserDefaults.Synchronize();
}
private static string DictionaryToJson(NSDictionary dictionary)
{
var json = NSJsonSerialization.Serialize(dictionary, NSJsonWritingOptions.PrettyPrinted, out NSError error);
return json.ToString(NSStringEncoding.UTF8);
}
}
}

View file

@ -1,20 +1,23 @@
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Utilities;
using Foundation; using Foundation;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using UIKit; using UIKit;
using UserNotifications;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.iOS.Services namespace Bit.iOS.Services
{ {
public class iOSPushNotificationService : IPushNotificationService, IPushNotificationHandler public class iOSPushNotificationService : IPushNotificationService
{ {
public string Token => NSUserDefaults.StandardUserDefaults.StringForKey(PushNotificationContants.Token); private const string TokenSetting = "token";
private readonly IPushNotificationListener _pushNotificationListener;
public iOSPushNotificationService(
IPushNotificationListener pushNotificationListener)
{
_pushNotificationListener = pushNotificationListener;
}
public string Token => NSUserDefaults.StandardUserDefaults.StringForKey(TokenSetting);
public void Register() public void Register()
{ {
@ -27,127 +30,9 @@ namespace Bit.iOS.Services
public void Unregister() public void Unregister()
{ {
UIApplication.SharedApplication.UnregisterForRemoteNotifications(); UIApplication.SharedApplication.UnregisterForRemoteNotifications();
OnUnregisteredSuccess(); _pushNotificationListener.OnUnregistered(Device.iOS);
} NSUserDefaults.StandardUserDefaults.SetString(string.Empty, TokenSetting);
private static string DictionaryToJson(NSDictionary dictionary)
{
NSError error;
var json = NSJsonSerialization.Serialize(dictionary, NSJsonWritingOptions.PrettyPrinted, out error);
return json.ToString(NSStringEncoding.UTF8);
}
public void OnMessageReceived(NSDictionary userInfo)
{
var parameters = new Dictionary<string, object>();
var json = DictionaryToJson(userInfo);
var values = JObject.Parse(json);
var keyAps = new NSString("aps");
if(userInfo.ContainsKey(keyAps))
{
var aps = userInfo.ValueForKey(keyAps) as NSDictionary;
if(aps != null)
{
foreach(var apsKey in aps)
{
parameters.Add(apsKey.Key.ToString(), apsKey.Value);
JToken temp;
if(!values.TryGetValue(apsKey.Key.ToString(), out temp))
{
values.Add(apsKey.Key.ToString(), apsKey.Value.ToString());
}
}
}
}
CrossPushNotification.PushNotificationListener.OnMessage(values, Device.iOS);
}
public void OnErrorReceived(NSError error)
{
Debug.WriteLine("{0} - Registration Failed.", PushNotificationContants.DomainName);
CrossPushNotification.PushNotificationListener.OnError(error.LocalizedDescription, Device.iOS);
}
public void OnRegisteredSuccess(NSData token)
{
Debug.WriteLine("{0} - Succesfully Registered.", PushNotificationContants.DomainName);
var trimmedDeviceToken = token.Description;
if(!string.IsNullOrWhiteSpace(trimmedDeviceToken))
{
trimmedDeviceToken = trimmedDeviceToken.Trim('<');
trimmedDeviceToken = trimmedDeviceToken.Trim('>');
trimmedDeviceToken = trimmedDeviceToken.Trim();
trimmedDeviceToken = trimmedDeviceToken.Replace(" ", "");
}
Console.WriteLine("{0} - Token: {1}", PushNotificationContants.DomainName, trimmedDeviceToken);
CrossPushNotification.PushNotificationListener.OnRegistered(trimmedDeviceToken, Device.iOS);
NSUserDefaults.StandardUserDefaults.SetString(trimmedDeviceToken, PushNotificationContants.Token);
NSUserDefaults.StandardUserDefaults.Synchronize(); NSUserDefaults.StandardUserDefaults.Synchronize();
} }
public void OnUnregisteredSuccess()
{
CrossPushNotification.PushNotificationListener.OnUnregistered(Device.iOS);
NSUserDefaults.StandardUserDefaults.SetString(string.Empty, PushNotificationContants.Token);
NSUserDefaults.StandardUserDefaults.Synchronize();
}
}
public interface IPushNotificationHandler
{
void OnMessageReceived(NSDictionary parameters);
void OnErrorReceived(NSError error);
void OnRegisteredSuccess(NSData token);
void OnUnregisteredSuccess();
}
internal class CrossPushNotification
{
private static Lazy<IPushNotificationService> Implementation = new Lazy<IPushNotificationService>(
() => new iOSPushNotificationService(),
LazyThreadSafetyMode.PublicationOnly);
public static bool IsInitialized => PushNotificationListener != null;
public static IPushNotificationListener PushNotificationListener { get; private set; }
public static void Initialize<T>(T listener) where T : IPushNotificationListener
{
if(PushNotificationListener == null)
{
PushNotificationListener = listener;
Debug.WriteLine("PushNotification plugin initialized.");
}
else
{
Debug.WriteLine("PushNotification plugin already initialized.");
}
}
public static void Initialize<T>() where T : IPushNotificationListener, new()
{
Initialize(new T());
}
public static IPushNotificationService Current
{
get
{
if(!IsInitialized)
{
throw new Exception("Not initialized.");
}
var ret = Implementation.Value;
if(ret == null)
{
throw new Exception("Not in PCL");
}
return ret;
}
}
} }
} }

View file

@ -236,6 +236,7 @@
<Compile Include="Services\DeviceActionService.cs" /> <Compile Include="Services\DeviceActionService.cs" />
<Compile Include="Main.cs" /> <Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" /> <Compile Include="AppDelegate.cs" />
<Compile Include="Services\iOSPushNotificationHandler.cs" />
<Compile Include="Services\iOSPushNotificationService.cs" /> <Compile Include="Services\iOSPushNotificationService.cs" />
<Compile Include="Services\ReflectionService.cs" /> <Compile Include="Services\ReflectionService.cs" />
<None Include="Entitlements.plist" /> <None Include="Entitlements.plist" />