Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge android-notification-channel-groups into develop #87

Merged
merged 40 commits into from
Apr 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
07f6383
Update PR template
Oct 30, 2024
3395a1c
Initialize notification channels before firebase app is initialized
Oct 30, 2024
d01337b
Add model for notification channel group and add sample data
Oct 30, 2024
126a14e
Create and delete notification channel groups
Oct 30, 2024
3682303
Extend sample app to create/delete notification channel groups
Oct 30, 2024
e86119c
Merge remote-tracking branch 'origin/develop' into android-notificati…
Oct 30, 2024
ac1a9e2
Internal refactoring of INotificationChannels implementation. Add API…
Oct 30, 2024
f72703b
Disable sentry by default
Oct 31, 2024
6ce6c32
Restore platform-independent implementation of INotificationChannels …
Oct 31, 2024
fb12adb
Extend log messages
Oct 31, 2024
fad9792
Fix log messages
Oct 31, 2024
165a8f0
Add methods to open notification settings
Oct 31, 2024
ad9c1b8
Remove prop set in android/ios specific options
Oct 31, 2024
8325e6b
Update release notes
Oct 31, 2024
3dc547b
Fix wrong label text
Oct 31, 2024
2a2e443
Fix bug in SetNotificationChannels so that no longer used channels ar…
Oct 31, 2024
c35a2ae
Fix bug in SetNotificationChannelGroups to delete existing groups
Oct 31, 2024
07810fd
Set AutoInitEnabled=true by default
Nov 12, 2024
7c2f1fd
Format enums in channel viewmodel
Nov 12, 2024
ee3eb2e
Merge remote-tracking branch 'origin/android-get-context-fix' into an…
Jan 13, 2025
c2930d2
Move methods + add comments
Feb 17, 2025
fbef6a3
Improve readability of notification channels in sample app
Feb 17, 2025
2bc8bbf
Return if channelIds is empty
Feb 17, 2025
dd0d3ca
Improve alignment of information in notification channels list (sampl…
Feb 17, 2025
6127b65
Simplify code
Feb 17, 2025
ca9a54d
Merge remote-tracking branch 'origin/develop' into android-notificati…
Feb 17, 2025
31cf4a9
Cleanup obsolete statements in csproj
Feb 17, 2025
9ef5c21
Cleanup
Feb 17, 2025
52cec57
Use GetById method
Feb 17, 2025
9a8f591
Reformat code
Feb 17, 2025
e528df7
Call RegisterForRemoteNotifications on iOS also if RequestAuthorizati…
Feb 20, 2025
7665657
Use reportgenerator 5
Feb 20, 2025
1b4bdea
Cleanup
Feb 20, 2025
9d4bd6f
Add unit tests for tokenformatter
Feb 20, 2025
029c22a
Readd IsDefault property to NotificationChannelRequest + implement ne…
Feb 20, 2025
e9ae45d
Fix CA warning
Feb 21, 2025
3ea8f21
Increase efficiency in parsing
Feb 26, 2025
7c5a130
Add demo for DefaultNotificationImportance
Feb 26, 2025
7e55680
Fix bug in PNFirebaseMessagingService which avoids displaying notific…
Feb 26, 2025
aec5cd3
Use LaunchMode SingleTask (instead of SingleInstance) in Android samp…
Apr 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,4 @@ dotnet_diagnostic.IDE0051.severity = warning
dotnet_diagnostic.CS1591.severity = none

# CA1416: Validate platform compatibility
dotnet_diagnostic.CA1416.severity = info
dotnet_diagnostic.CA1416.severity = suggestion
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#### Issues
<!-- Add affected issue(s) here. -->
*
*

#### Checklist
<!-- Read the following checklist and tick items off when complete. Use an `X` inside the brackets to mark as done. -->
Expand Down
2 changes: 0 additions & 2 deletions Plugin.FirebasePushNotifications/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ internal static partial class Constants
internal const string NotificationDataKey = "data";
internal const string PriorityKey = "priority";

internal const string SuppressedString = "{suppressed}";

internal static class Preferences
{
private const string KeyPrefix = "Plugin.FirebasePushNotifications";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ private static IFirebasePushNotification CreateFirebasePushNotification()
var preferences = IPlatformApplication.Current.Services.GetService<IFirebasePushNotificationPreferences>();

#if ANDROID
var notificationChannels = IPlatformApplication.Current.Services.GetService<INotificationChannels>();
var notificationBuilder = IPlatformApplication.Current.Services.GetService<INotificationBuilder>();
#endif

Expand All @@ -58,6 +59,7 @@ private static IFirebasePushNotification CreateFirebasePushNotification()
preferences
#if ANDROID
,
notificationChannels,
notificationBuilder
#endif
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,18 @@ public static bool TryGetBool(this IDictionary<string, object> items, string key
value = boolValue;
return true;
}
else if (items.TryGetString(key, out var stringValue))

if (items.TryGetString(key, out var stringValue))
{
if (stringValue.Equals("true", StringComparison.InvariantCultureIgnoreCase) ||
stringValue.Equals("1", StringComparison.InvariantCultureIgnoreCase))
if (stringValue.Equals("1", StringComparison.InvariantCultureIgnoreCase) ||
stringValue.Equals("true", StringComparison.InvariantCultureIgnoreCase))
{
value = true;
return true;
}
else if (
stringValue.Equals("false", StringComparison.InvariantCultureIgnoreCase) ||
stringValue.Equals("0", StringComparison.InvariantCultureIgnoreCase))

if (stringValue.Equals("0", StringComparison.InvariantCultureIgnoreCase) ||
stringValue.Equals("false", StringComparison.InvariantCultureIgnoreCase))
{
value = false;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#if ANDROID || IOS
using Plugin.FirebasePushNotifications.Platforms;
using Plugin.FirebasePushNotifications.Platforms.Channels;
using Plugin.FirebasePushNotifications.Model.Queues;
using Microsoft.Extensions.DependencyInjection.Extensions;
#endif

Expand Down Expand Up @@ -101,8 +100,8 @@ public static MauiAppBuilder UseFirebasePushNotifications(this MauiAppBuilder bu

// Service registrations
#if ANDROID || IOS
builder.Services.AddSingleton(c => IFirebasePushNotification.Current);
builder.Services.AddSingleton(c => INotificationPermissions.Current);
builder.Services.AddSingleton(_ => IFirebasePushNotification.Current);
builder.Services.AddSingleton(_ => INotificationPermissions.Current);
builder.Services.TryAddSingleton<IFirebasePushNotificationPreferences, FirebasePushNotificationPreferences>();
builder.Services.TryAddSingleton<IPreferences>(_ => Preferences.Default);
builder.Services.AddSingleton(defaultOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ namespace Plugin.FirebasePushNotifications
{
public class FirebasePushNotificationOptions
{
public virtual bool AutoInitEnabled { get; set; }
/// <summary>
/// Indicates if the underlying Firebase library should be initialized automatically.
/// Default: <c>true</c>
/// </summary>
public virtual bool AutoInitEnabled { get; set; } = true;

/// <summary>
/// The factory used to create new queues to intercept push notification events.
Expand All @@ -21,9 +25,15 @@ public class FirebasePushNotificationOptions
public virtual IQueueFactory QueueFactory { get; set; }

#if ANDROID
public virtual FirebasePushNotificationAndroidOptions Android { get; set; } = new FirebasePushNotificationAndroidOptions();
/// <summary>
/// Android-specific options.
/// </summary>
public virtual FirebasePushNotificationAndroidOptions Android { get; } = new FirebasePushNotificationAndroidOptions();
#elif IOS
public virtual FirebasePushNotificationiOSOptions iOS { get; set; } = new FirebasePushNotificationiOSOptions();
/// <summary>
/// iOS-specific options.
/// </summary>
public virtual FirebasePushNotificationiOSOptions iOS { get; } = new FirebasePushNotificationiOSOptions();
#endif

public override string ToString()
Expand Down
31 changes: 13 additions & 18 deletions Plugin.FirebasePushNotifications/INotificationChannels.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
namespace Plugin.FirebasePushNotifications
{
/// <summary>
/// Cross-platform interface to handle notification channels.
/// </summary>
/// <remarks>
/// The concept of notification channels does only exist on Android.
/// This cross-platform interfaces allows to update all existing
/// notification channels from platform-independent code.
/// </remarks>
public partial interface INotificationChannels
{
/// <summary>
/// Updates all existing notification channels.
/// </summary>
void UpdateChannels();
}
}
namespace Plugin.FirebasePushNotifications
{
/// <summary>
/// Cross-platform interface to handle notification channels.
/// </summary>
/// <remarks>
/// The concept of notification channels exists on Android only.
/// This interface is mainly used to simplify dependency injection.
/// </remarks>
public partial interface INotificationChannels
{
}
}
10 changes: 5 additions & 5 deletions Plugin.FirebasePushNotifications/Internals/TokenFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ internal static string AnonymizeToken(string token)
var substringLength = Math.Min(10, token.Length / 10);
if (substringLength < 5)
{
return Constants.SuppressedString;
return "...";
}

return $"{Constants.SuppressedString}...{token[^substringLength..]}";
return $"{token[..substringLength]}...{token[^substringLength..]}".Trim(new[] { '\n', '\r', ' ' });
}
catch
catch (Exception ex)
{
return Constants.SuppressedString;
return ex.Message;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Plugin.FirebasePushNotifications.Platforms.Channels;
using System.Diagnostics.CodeAnalysis;
using Android.App;
using Plugin.FirebasePushNotifications.Platforms.Channels;

namespace Plugin.FirebasePushNotifications
{
Expand All @@ -7,32 +9,100 @@ namespace Plugin.FirebasePushNotifications
/// </summary>
public partial interface INotificationChannels
{
/// <summary>
/// Gets the singleton instance of <see cref="INotificationChannels"/>.
/// </summary>
public static INotificationChannels Current { get; set; } = NotificationChannels.Current;

/// <summary>
/// Gets the list of configured notification channels.
/// </summary>
IEnumerable<NotificationChannelRequest> Channels { get; }
NotificationChannels.NotificationChannelsDelegate Channels { get; }

/// <summary>
/// Gets the list of configured notification channel groups.
/// </summary>
IEnumerable<NotificationChannelGroup> ChannelGroups { get; }

/// <summary>
/// Sets notification channel groups from given <paramref name="notificationChannelGroupRequests"/>.
/// </summary>
/// <remarks>
/// If the <paramref name="notificationChannelGroupRequests"/> already exist, they're updated.
/// </remarks>
/// <param name="notificationChannelGroupRequests">The notification channel group requests.</param>
void SetNotificationChannelGroups(NotificationChannelGroupRequest[] notificationChannelGroupRequests);

/// <summary>
/// Creates notification channel groups.
/// </summary>
/// <remarks>
/// Important: Create notification channel groups before you create notification channels!
/// </remarks>
/// <param name="notificationChannelGroupRequests">The notification channel group requests.</param>
void CreateNotificationChannelGroups(NotificationChannelGroupRequest[] notificationChannelGroupRequests);

/// <summary>
/// Deletes the notification channel group with <paramref name="groupId"/>.
/// </summary>
/// <param name="groupId">The identifier of the notification channel group.</param>
void DeleteNotificationChannelGroup(string groupId);

/// <summary>
/// Create Android notification channels from given <paramref name="notificationChannelRequests"/>.
/// Deletes the notification channel groups with <paramref name="groupIds"/>.
/// </summary>
/// <param name="groupIds">The identifiers of the notification channel group.</param>
void DeleteNotificationChannelGroups(string[] groupIds);

/// <summary>
/// Deletes all notification channel groups which are configured in <see cref="Channels"/>.
/// </summary>
void DeleteAllNotificationChannelGroups();

/// <summary>
/// Sets notification channels from given <paramref name="notificationChannelRequests"/>.
/// </summary>
/// <remarks>
/// If the <paramref name="notificationChannelRequests"/> already exist, they're updated.
/// </remarks>
/// <param name="notificationChannelRequests">The notification channel requests.</param>
void CreateChannels(NotificationChannelRequest[] notificationChannelRequests);
void SetNotificationChannels(NotificationChannelRequest[] notificationChannelRequests);

/// <summary>
/// Update Android notification channels from given <paramref name="notificationChannelRequests"/>.
/// Creates notification channels from given <paramref name="notificationChannelRequests"/>.
/// </summary>
/// <remarks>
/// If the <paramref name="notificationChannelRequests"/> already exist, they're updated.
/// </remarks>
/// <param name="notificationChannelRequests">The notification channel requests.</param>
void UpdateChannels(NotificationChannelRequest[] notificationChannelRequests);
void CreateNotificationChannels([NotNull] NotificationChannelRequest[] notificationChannelRequests);

/// <summary>
/// Deletes the notification channel with the given <paramref name="notificationChannelId"/>.
/// </summary>
/// <param name="notificationChannelId">The notification channel identifier.</param>
void DeleteNotificationChannel(string notificationChannelId);

/// <summary>
/// Deletes the notification channels with the given <paramref name="notificationChannelIds"/>.
/// </summary>
/// <param name="notificationChannelIds">The notification channel identifiers.</param>
void DeleteNotificationChannels(string[] notificationChannelIds);

/// <summary>
/// Deletes all existing notification channels which are configured in <see cref="Channels"/>.
/// </summary>
void DeleteAllNotificationChannels();

/// <summary>
/// Delete Android notification channels from given <paramref name="channelIds"/>.
/// Open the notification settings.
/// </summary>
/// <param name="channelIds">The notification channel identifiers.</param>
void DeleteChannels(string[] channelIds);
void OpenNotificationSettings();

/// <summary>
/// Deletes all existing notification channels.
/// Opens the notification channel settings for <paramref name="notificationChannelId"/>.
/// </summary>
void DeleteAllChannels();
/// <param name="notificationChannelId">The notification channel identifier.</param>
void OpenNotificationChannelSettings(string notificationChannelId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Diagnostics;

namespace Plugin.FirebasePushNotifications.Platforms.Channels
{
/// <summary>
/// Notification channel group request.
/// </summary>
[DebuggerDisplay("{GroupId}")]
public class NotificationChannelGroupRequest
{
/// <summary>
/// Creates a new instance of <see cref="NotificationChannelRequest"/>.
/// </summary>
/// <param name="groupId">The group identifier.</param>
/// <param name="name">The group name.</param>
/// <param name="description">The group description (optional).</param>
public NotificationChannelGroupRequest(string groupId, string name, string description = null)
{
if (string.IsNullOrEmpty(groupId))
{
throw new ArgumentException("The group identifier must not be null or empty", nameof(groupId));
}

if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("The group name must not be null or empty", nameof(name));
}

this.GroupId = groupId;
this.Name = name;
this.Description = description;
}

/// <summary>
/// The group identifier.
/// </summary>
public string GroupId { get; }

/// <summary>
/// The group name (displayed in the notification settings of the app).
/// </summary>
public string Name { get; }

/// <summary>
/// The group description (optional).
/// </summary>
public string Description { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,7 @@ public class NotificationChannelRequest
public bool IsDefault { get; set; }

/// <summary>
/// Determines if the current notification channel is active.
/// Default: <c>true</c>
/// </summary>
/// <remarks>
/// Inactive notification channels will be removed at app startup.
/// </remarks>
public bool IsActive { get; set; } = true;

/// <summary>
/// Sets or gets, what group this channel belongs to.
/// The group ID this channel belongs to.
/// </summary>
public string Group { get; set; }

Expand Down
Loading
Loading