AppIcon Badge with .NET MAUI

AppIcon Badge with .NET MAUI

01 December 2022

.NET MAUI/Xamarin

Buy Me A Coffee

Winter is coming!

This article is a continuation of a series of potential Essentials APIs, that can be added to .NET MAUI later. It is devoted to the AppIcon badge. If your app sends notifications or you want the user to pay attention to the app, this API is what you need.

As usual, starting from creating the interface:

public interface INotificationCounter
{
	void SetNotificationCount(int count);
}

public static class NotificationCounter
{
	static INotificationCounter? defaultImplementation;

	public static void SetNotificationCount(int count)
	{
		Default.SetNotificationCount(count);
	}

	public static INotificationCounter Default =>
		defaultImplementation ??= new NotificationCounterImplementation();

	internal static void SetDefault(INotificationCounter? implementation) =>
		defaultImplementation = implementation;
}

We need only 1 method that sets badge count. If the count is 0 or less, the badge is removed.

Android

In Android, icons are displayed in the launcher, and there are a lot of different launchers. Each of them requires its own permissions and implementations. I recommend installing the next NuGet package:

<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-android'">
  <PackageReference Include="Xamarin.Android.ShortcutBadger" Version="1.2.0" />
</ItemGroup>

Add the next permissions to AndroidManifest.xml:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<uses-permission android:name="com.sonymobile.home.permission.PROVIDER_INSERT_BADGE" />
<uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE" />
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />
<uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_APP_BADGE" />
<uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.oppo.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="me.everything.badger.permission.BADGE_COUNT_READ" />
<uses-permission android:name="me.everything.badger.permission.BADGE_COUNT_WRITE" />

<!-- Apex -->
<uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT"/>

<!-- Default -->
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS"/>
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />

<!-- HTC -->
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT" /> 

<!-- Samsung -->
<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />

<!-- Sony -->
<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" />
<uses-permission android:name="com.sonymobile.home.permission.PROVIDER_INSERT_BADGE" />

And finally, implement our interface:

public class NotificationCounterImplementation : INotificationCounter
{
	public void SetNotificationCount(int count)
	{
		ME.Leolin.Shortcutbadger.ShortcutBadger.ApplyCount(Application.Context, count);
    }
}

Android

iOS/MacCatalyst

Apple's implementation is much simpler:

public class NotificationCounterImplementation : INotificationCounter
{
	public void SetNotificationCount(int count)
	{
		UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Badge, (r, e) =>
		{
		});
		UIApplication.SharedApplication.ApplicationIconBadgeNumber = count;
	}
}

You request NotificationCenter permission to update the badge. After that, you can update the Badge number.

iOS/MacCatalyst

Windows

Windows doesn't require any permissions or additional packages:

public class NotificationCounterImplementation : INotificationCounter
{
	public void SetNotificationCount(int count)
	{
		var badgeUpdater =	BadgeUpdateManager.CreateBadgeUpdaterForApplication();
		if (count <= 0)
		{
			badgeUpdater.Clear();
		}
		else
		{
			var badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);

			var badgeElement = badgeXml.SelectSingleNode("/badge") as XmlElement;
			badgeElement?.SetAttribute("value", count.ToString());

			var badge = new BadgeNotification(badgeXml);
			badgeUpdater.Update(badge);
		}
	}
}

Windows

Tizen

And last, but not least. Tizen has its own control to work with badges - BadgeControl.

But first, you need to set permission in tizen-manifest.xml:

<privilege>http://tizen.org/privilege/notification</privilege>

Then implement our interface:

public class NotificationCounterImplementation : INotificationCounter
{
	public void SetNotificationCount(int count)
	{
		var appId = Application.Current.ApplicationInfo.ApplicationId;
		if (count is 0)
		{
			BadgeControl.Remove(appId);
			return;
		}
		
		var badge = BadgeControl.Find(appId);
		if (badge is null)
		{
			badge = new Badge(appId, count);
			BadgeControl.Add(badge);
		}
		else
		{
			badge.Count = count;
			BadgeControl.Update(badge);
		}
	}
}

Tizen doesn't allow adding multiple badges to the same application, so you also need to check if the badge already exists and update it.

Tizen

Result

Now we can call our API and see the result:

var count = 1;
NotificationCounter.Default.SetNotificationCount(count);

The final code can be found on GitHub.

Happy coding!

Buy Me A Coffee

Related:

Drag and Drop any content to a .NET MAUI application

The article demonstrates how to add drop functionality to easily move content from the operating system to the .NET MAUI application.

Create a gallery app using .NET MAUI Blazor

Create infinite scrolling gallery app using .NET MAUI Blazor. Replicate Google Photos and Instagram Gallery UI.

An unhandled error has occurred. Reload

🗙