Skip to content

Commit

Permalink
C# modernizing & centralizing models on push
Browse files Browse the repository at this point in the history
  • Loading branch information
aritchie committed May 25, 2024
1 parent 13acfe7 commit a12a695
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 136 deletions.
14 changes: 13 additions & 1 deletion src/Shiny.Push/PushAccessState.cs → src/Shiny.Push/Models.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Shiny.Push;
using System.Collections.Generic;

namespace Shiny.Push;

public record PushAccessState(
AccessState Status,
Expand All @@ -13,3 +15,13 @@ public void Assert()
throw new PermissionException("Push registration fail", this.Status);
}
}

public record PushNotification(
IDictionary<string, string> Data,
Notification? Notification
);

public record Notification(
string? Title,
string? Message
);
6 changes: 0 additions & 6 deletions src/Shiny.Push/Notification.cs

This file was deleted.

114 changes: 51 additions & 63 deletions src/Shiny.Push/Platforms/Android/PushManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,79 +17,67 @@
namespace Shiny.Push;


public class PushManager : NotifyPropertyChanged,
IPushManager,
IShinyStartupTask,
IAndroidLifecycle.IOnActivityOnCreate,
IAndroidLifecycle.IOnActivityNewIntent
public class PushManager(
AndroidPlatform platform,
FirebaseConfig config,
IServiceProvider services,
ILogger<PushManager> logger,
IPushProvider? provider = null
) : NotifyPropertyChanged,
IPushManager,
IShinyStartupTask,
IAndroidLifecycle.IOnActivityOnCreate,
IAndroidLifecycle.IOnActivityNewIntent
{
readonly AndroidPlatform platform;
readonly IServiceProvider services;
readonly FirebaseConfig config;
readonly ILogger logger;
readonly IPushProvider provider;
IPushProvider useProvider = null!;
bool registrationRequest = false;

public PushManager(
AndroidPlatform platform,
FirebaseConfig config,
IServiceProvider services,
ILogger<PushManager> logger,
IPushProvider? provider = null
)
{
this.platform = platform;
this.config = config;
this.services = services;
this.logger = logger;
this.provider = provider ?? new FirebasePushProvider();
}


public async void Start()
{
this.useProvider = provider ?? new FirebasePushProvider();
this.TryCreateConfiguredChannel();
if (this.RegistrationToken.IsEmpty())
return;

try
{
this.NativeRegistrationToken = await this.RequestNativeToken();
var regToken = await this.provider.Register(this.NativeRegistrationToken); // never null on firebase
var regToken = await this.useProvider.Register(this.NativeRegistrationToken); // never null on firebase

if (regToken != this.RegistrationToken)
{
this.RegistrationToken = regToken;
await this.services
await services
.RunDelegates<IPushDelegate>(
x => x.OnNewToken(regToken),
this.logger
logger
)
.ConfigureAwait(false);
}
}
catch (Exception ex)
{
this.logger.LogWarning(ex, "There was an error restarting push services");
logger.LogWarning(ex, "There was an error restarting push services");
}
}


void TryCreateConfiguredChannel()
{
if (this.config.DefaultChannel == null)
if (config.DefaultChannel == null)
return;

using var nativeManager = this.platform.GetSystemService<NotificationManager>(Context.NotificationService);
var channel = nativeManager.GetNotificationChannel(this.config.DefaultChannel.Id);
using var nativeManager = platform.GetSystemService<NotificationManager>(Context.NotificationService);
var channel = nativeManager.GetNotificationChannel(config.DefaultChannel.Id);
if (channel != null)
nativeManager.DeleteNotificationChannel(channel.Id);

nativeManager.CreateNotificationChannel(this.config.DefaultChannel);
nativeManager.CreateNotificationChannel(config.DefaultChannel);
}


public IPushTagSupport? Tags => (this.provider as IPushTagSupport);
public IPushTagSupport? Tags => this.useProvider as IPushTagSupport;

string? regToken;
public string? RegistrationToken
Expand All @@ -115,7 +103,7 @@ public async Task<PushAccessState> RequestAccess(CancellationToken cancelToken =
// TODO: verify google signed in
if (OperatingSystem.IsAndroidVersionAtLeast(33))
{
var access = await this.platform
var access = await platform
.RequestAccess(Manifest.Permission.PostNotifications)
.ToTask(cancelToken);

Expand All @@ -124,14 +112,14 @@ public async Task<PushAccessState> RequestAccess(CancellationToken cancelToken =
}

var nativeToken = await this.RequestNativeToken();
var regToken = await this.provider.Register(nativeToken); // never null on firebase
var regToken = await this.useProvider.Register(nativeToken); // never null on firebase

if (regToken != null && this.RegistrationToken != regToken)
{
await this.services
await services
.RunDelegates<IPushDelegate>(
x => x.OnNewToken(regToken),
this.logger
logger
)
.ConfigureAwait(false);
}
Expand All @@ -152,7 +140,7 @@ public async Task UnRegister()
if (this.RegistrationToken == null)
return;

await this.provider
await this.useProvider
.UnRegister()
.ConfigureAwait(false);

Expand All @@ -162,10 +150,10 @@ await FirebaseMessaging
.AsAsync()
.ConfigureAwait(false);

await this.services
await services
.RunDelegates<IPushDelegate>(
x => x.OnUnRegistered(this.RegistrationToken!),
this.logger
logger
)
.ConfigureAwait(false);

Expand All @@ -179,12 +167,12 @@ public void ActivityOnCreate(Activity activity, Bundle? savedInstanceState)

public void Handle(Activity activity, Intent? intent)
{
var intentAction = this.config.IntentAction ?? ShinyPushIntents.NotificationClickAction;
var intentAction = config.IntentAction ?? ShinyPushIntents.NotificationClickAction;
var clickAction = intent?.Action?.Equals(intentAction, StringComparison.InvariantCultureIgnoreCase) ?? false;
if (!clickAction)
return;

this.logger.LogDebug("Detected incoming remote notification intent");
logger.LogDebug("Detected incoming remote notification intent");
var dict = new Dictionary<string, string>();

if (intent!.Extras != null)
Expand All @@ -198,13 +186,13 @@ public void Handle(Activity activity, Intent? intent)
}
// can I extract the notification here?
var data = new PushNotification(dict, null);
this.services
services
.RunDelegates<IPushDelegate>(
x => x.OnEntry(data),
this.logger
logger
)
.ContinueWith(x =>
this.logger.LogInformation("Finished executing push delegates")
logger.LogInformation("Finished executing push delegates")
);
}

Expand All @@ -227,22 +215,22 @@ void DoInit()

if (!this.IsFirebaseAappAlreadyInitialized())
{
if (this.config.UseEmbeddedConfiguration)
if (config.UseEmbeddedConfiguration)
{
FirebaseApp.InitializeApp(this.platform.AppContext);
FirebaseApp.InitializeApp(platform.AppContext);
if (FirebaseApp.Instance == null)
throw new InvalidOperationException("Firebase did not initialize. Ensure your google.services.json is property setup. Install the nuget package `Xamarin.GooglePlayServices.Tasks` into your Android head project, restart visual studio, and then set your google-services.json to GoogleServicesJson");
}
else
{
var options = new FirebaseOptions.Builder()
.SetApplicationId(this.config.AppId)
.SetProjectId(this.config.ProjectId)
.SetApiKey(this.config.ApiKey)
.SetGcmSenderId(this.config.SenderId)
.Build();
.SetApplicationId(config.AppId)
.SetProjectId(config.ProjectId)
.SetApiKey(config.ApiKey)
.SetGcmSenderId(config.SenderId)
.Build();

FirebaseApp.InitializeApp(this.platform.AppContext, options);
FirebaseApp.InitializeApp(platform.AppContext, options);
}
}

Expand All @@ -252,12 +240,12 @@ void DoInit()
return;
this.NativeRegistrationToken = token;
this.RegistrationToken = await this.provider.Register(token);
this.RegistrationToken = await provider.Register(token);
await this.services
await services
.RunDelegates<IPushDelegate>(
x => x.OnNewToken(this.RegistrationToken),
this.logger
logger
)
.ConfigureAwait(false);
};
Expand All @@ -279,19 +267,19 @@ await this.services
var push = new AndroidPushNotification(
notification,
msg,
this.config,
this.platform
config,
platform
);
await this.services
await services
.RunDelegates<IPushDelegate>(
x => x.OnReceived(push),
this.logger
logger
)
.ConfigureAwait(false);
}
catch (Exception ex)
{
this.logger.LogError(ex, "Failed to receive firebase message");
logger.LogError(ex, "Failed to receive firebase message");
}
};

Expand All @@ -302,7 +290,7 @@ await this.services
bool IsFirebaseAappAlreadyInitialized()
{
var isAppInitialized = false;
var firebaseApps = FirebaseApp.GetApps(this.platform.AppContext);
var firebaseApps = FirebaseApp.GetApps(platform.AppContext);
foreach (var app in firebaseApps)
{
if (string.Equals(app.Name, FirebaseApp.DefaultAppName))
Expand Down
Loading

0 comments on commit a12a695

Please sign in to comment.